// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <list>
#include <map>
#include <set>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/version.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/extension_sync_data.h"
#include "chrome/browser/extensions/test_extension_prefs.h"
#include "chrome/browser/extensions/test_extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/extensions/updater/chrome_extension_downloader_factory.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/google/google_brand.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/crx_file/id_util.h"
#include "components/update_client/update_query_params.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/updater/extension_downloader.h"
#include "extensions/browser/updater/extension_downloader_delegate.h"
#include "extensions/browser/updater/manifest_fetch_data.h"
#include "extensions/browser/updater/request_queue_impl.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/manifest_constants.h"
#include "google_apis/gaia/fake_identity_provider.h"
#include "google_apis/gaia/fake_oauth2_token_service.h"
#include "libxml/globals.h"
#include "net/base/backoff_entry.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_status.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/third_party/mozilla/url_parse.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#endif

using base::Time;
using base::TimeDelta;
using content::BrowserThread;
using update_client::UpdateQueryParams;
using testing::DoAll;
using testing::Invoke;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::Return;
using testing::SetArgPointee;
using testing::_;

namespace extensions {

typedef ExtensionDownloaderDelegate::Error Error;
typedef ExtensionDownloaderDelegate::PingResult PingResult;

namespace {

const net::BackoffEntry::Policy kNoBackoffPolicy = {
  // Number of initial errors (in sequence) to ignore before applying
  // exponential back-off rules.
  1000,

  // Initial delay for exponential back-off in ms.
  0,

  // Factor by which the waiting time will be multiplied.
  0,

  // Fuzzing percentage. ex: 10% will spread requests randomly
  // between 90%-100% of the calculated time.
  0,

  // Maximum amount of time we are willing to delay our request in ms.
  0,

  // Time to keep an entry from being discarded even when it
  // has no significant state, -1 to never discard.
  -1,

  // Don't use initial delay unless the last request was an error.
  false,
};

const char kEmptyUpdateUrlData[] = "";

const char kAuthUserQueryKey[] = "authuser";

int kExpectedLoadFlags =
    net::LOAD_DO_NOT_SEND_COOKIES |
    net::LOAD_DO_NOT_SAVE_COOKIES |
    net::LOAD_DISABLE_CACHE;

int kExpectedLoadFlagsForDownloadWithCookies = net::LOAD_DISABLE_CACHE;

// Fake authentication constants
const char kFakeAccountId[] = "bobloblaw@lawblog.example.com";
const char kFakeOAuth2Token[] = "ce n'est pas un jeton";

const ManifestFetchData::PingData kNeverPingedData(
    ManifestFetchData::kNeverPinged,
    ManifestFetchData::kNeverPinged,
    true,
    0);

class MockExtensionDownloaderDelegate : public ExtensionDownloaderDelegate {
 public:
  MOCK_METHOD4(OnExtensionDownloadFailed, void(const std::string&,
                                               Error,
                                               const PingResult&,
                                               const std::set<int>&));
  MOCK_METHOD7(OnExtensionDownloadFinished,
               void(const extensions::CRXFileInfo&,
                    bool,
                    const GURL&,
                    const std::string&,
                    const PingResult&,
                    const std::set<int>&,
                    const InstallCallback&));
  MOCK_METHOD2(GetPingDataForExtension,
               bool(const std::string&, ManifestFetchData::PingData*));
  MOCK_METHOD1(GetUpdateUrlData, std::string(const std::string&));
  MOCK_METHOD1(IsExtensionPending, bool(const std::string&));
  MOCK_METHOD2(GetExtensionExistingVersion,
               bool(const std::string&, std::string*));

  void Wait() {
    scoped_refptr<content::MessageLoopRunner> runner =
        new content::MessageLoopRunner;
    quit_closure_ = runner->QuitClosure();
    runner->Run();
    quit_closure_.Reset();
  }

  void Quit() {
    quit_closure_.Run();
  }

  void DelegateTo(ExtensionDownloaderDelegate* delegate) {
    ON_CALL(*this, OnExtensionDownloadFailed(_, _, _, _))
        .WillByDefault(Invoke(delegate,
            &ExtensionDownloaderDelegate::OnExtensionDownloadFailed));
    ON_CALL(*this, OnExtensionDownloadFinished(_, _, _, _, _, _, _))
        .WillByDefault(
            Invoke(delegate,
                   &ExtensionDownloaderDelegate::OnExtensionDownloadFinished));
    ON_CALL(*this, GetPingDataForExtension(_, _))
        .WillByDefault(Invoke(delegate,
            &ExtensionDownloaderDelegate::GetPingDataForExtension));
    ON_CALL(*this, GetUpdateUrlData(_))
        .WillByDefault(Invoke(delegate,
            &ExtensionDownloaderDelegate::GetUpdateUrlData));
    ON_CALL(*this, IsExtensionPending(_))
        .WillByDefault(Invoke(delegate,
            &ExtensionDownloaderDelegate::IsExtensionPending));
    ON_CALL(*this, GetExtensionExistingVersion(_, _))
        .WillByDefault(Invoke(delegate,
            &ExtensionDownloaderDelegate::GetExtensionExistingVersion));
  }

 private:
  base::Closure quit_closure_;
};

const int kNotificationsObserved[] = {
    extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED,
    extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND,
};

// A class that observes the notifications sent by the ExtensionUpdater and
// the ExtensionDownloader.
class NotificationsObserver : public content::NotificationObserver {
 public:
  NotificationsObserver() {
    for (size_t i = 0; i < arraysize(kNotificationsObserved); ++i) {
      count_[i] = 0;
      registrar_.Add(this,
                     kNotificationsObserved[i],
                     content::NotificationService::AllSources());
    }
  }

  ~NotificationsObserver() override {
    for (size_t i = 0; i < arraysize(kNotificationsObserved); ++i) {
      registrar_.Remove(this,
                        kNotificationsObserved[i],
                        content::NotificationService::AllSources());
    }
  }

  size_t StartedCount() { return count_[0]; }
  size_t UpdatedCount() { return count_[1]; }

  bool Updated(const std::string& id) {
    return updated_.find(id) != updated_.end();
  }

  void Wait() {
    scoped_refptr<content::MessageLoopRunner> runner =
        new content::MessageLoopRunner;
    quit_closure_ = runner->QuitClosure();
    runner->Run();
    quit_closure_.Reset();
  }

 private:
  void Observe(int type,
               const content::NotificationSource& source,
               const content::NotificationDetails& details) override {
    if (!quit_closure_.is_null())
      quit_closure_.Run();
    for (size_t i = 0; i < arraysize(kNotificationsObserved); ++i) {
      if (kNotificationsObserved[i] == type) {
        count_[i]++;
        if (type == extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND) {
          updated_.insert(
              content::Details<UpdateDetails>(details)->id);
        }
        return;
      }
    }
    NOTREACHED();
  }

  content::NotificationRegistrar registrar_;
  size_t count_[arraysize(kNotificationsObserved)];
  std::set<std::string> updated_;
  base::Closure quit_closure_;

  DISALLOW_COPY_AND_ASSIGN(NotificationsObserver);
};

// Extracts the integer value of the |authuser| query parameter. Returns 0 if
// the parameter is not set.
int GetAuthUserQueryValue(const GURL& url) {
  std::string query_string = url.query();
  url::Component query(0, query_string.length());
  url::Component key, value;
  while (
      url::ExtractQueryKeyValue(query_string.c_str(), &query, &key, &value)) {
    std::string key_string = query_string.substr(key.begin, key.len);
    if (key_string == kAuthUserQueryKey) {
      int user_index = 0;
      base::StringToInt(query_string.substr(value.begin, value.len),
                        &user_index);
      return user_index;
    }
  }
  return 0;
}

}  // namespace

// Base class for further specialized test classes.
class MockService : public TestExtensionService {
 public:
  explicit MockService(TestExtensionPrefs* prefs)
      : prefs_(prefs),
        pending_extension_manager_(&profile_),
        downloader_delegate_override_(NULL),
        enable_metrics_(false) {}

  ~MockService() override {}

  PendingExtensionManager* pending_extension_manager() override {
    ADD_FAILURE() << "Subclass should override this if it will "
                  << "be accessed by a test.";
    return &pending_extension_manager_;
  }

  Profile* profile() { return &profile_; }

  net::URLRequestContextGetter* request_context() {
    return profile_.GetRequestContext();
  }

  ExtensionPrefs* extension_prefs() { return prefs_->prefs(); }

  PrefService* pref_service() { return prefs_->pref_service(); }

  FakeOAuth2TokenService* fake_token_service() {
    return fake_token_service_.get();
  }

  // Controls whether metrics (enable/disabled state, etc.) are sent in the
  // autoupdate ping requests.
  void set_enable_metrics(bool enable) { enable_metrics_ = enable; }

  // Creates test extensions and inserts them into list. The name and
  // version are all based on their index. If |update_url| is non-null, it
  // will be used as the update_url for each extension.
  // The |id| is used to distinguish extension names and make sure that
  // no two extensions share the same name.
  void CreateTestExtensions(int id, int count, ExtensionList *list,
                            const std::string* update_url,
                            Manifest::Location location) {
    for (int i = 1; i <= count; i++) {
      base::DictionaryValue manifest;
      manifest.SetString(manifest_keys::kVersion,
                         base::StringPrintf("%d.0.0.0", i));
      manifest.SetString(manifest_keys::kName,
                         base::StringPrintf("Extension %d.%d", id, i));
      if (update_url)
        manifest.SetString(manifest_keys::kUpdateURL, *update_url);
      scoped_refptr<Extension> e =
          prefs_->AddExtensionWithManifest(manifest, location);
      ASSERT_TRUE(e.get() != NULL);
      list->push_back(e);
    }
  }

  ExtensionDownloader::Factory GetDownloaderFactory() {
    return base::Bind(&MockService::CreateExtensionDownloader,
                      base::Unretained(this));
  }

  ExtensionDownloader::Factory GetAuthenticatedDownloaderFactory() {
    return base::Bind(&MockService::CreateExtensionDownloaderWithIdentity,
                      base::Unretained(this));
  }

  void OverrideDownloaderDelegate(ExtensionDownloaderDelegate* delegate) {
    downloader_delegate_override_ = delegate;
  }

 protected:
  TestExtensionPrefs* const prefs_;
  TestingProfile profile_;
  PendingExtensionManager pending_extension_manager_;

 private:
  scoped_ptr<ExtensionDownloader> CreateExtensionDownloader(
      ExtensionDownloaderDelegate* delegate) {
    scoped_ptr<ExtensionDownloader> downloader =
        ChromeExtensionDownloaderFactory::CreateForRequestContext(
            request_context(),
            downloader_delegate_override_ ? downloader_delegate_override_
                                          : delegate);
    if (enable_metrics_)
      downloader->set_enable_extra_update_metrics(true);
    return downloader.Pass();
  }

  scoped_ptr<ExtensionDownloader> CreateExtensionDownloaderWithIdentity(
      ExtensionDownloaderDelegate* delegate) {
    scoped_ptr<FakeIdentityProvider> fake_identity_provider;
    fake_token_service_.reset(new FakeOAuth2TokenService());
    fake_identity_provider.reset(new FakeIdentityProvider(
          fake_token_service_.get()));
    fake_identity_provider->LogIn(kFakeAccountId);
    fake_token_service_->AddAccount(kFakeAccountId);

    scoped_ptr<ExtensionDownloader> downloader(
        CreateExtensionDownloader(delegate));
    downloader->SetWebstoreIdentityProvider(fake_identity_provider.Pass());
    return downloader.Pass();
  }

  scoped_ptr<FakeOAuth2TokenService> fake_token_service_;

  ExtensionDownloaderDelegate* downloader_delegate_override_;

  bool enable_metrics_;

  DISALLOW_COPY_AND_ASSIGN(MockService);
};


bool ShouldInstallExtensionsOnly(const Extension* extension) {
  return extension->GetType() == Manifest::TYPE_EXTENSION;
}

bool ShouldInstallThemesOnly(const Extension* extension) {
  return extension->is_theme();
}

bool ShouldAlwaysInstall(const Extension* extension) {
  return true;
}

// Loads some pending extension records into a pending extension manager.
void SetupPendingExtensionManagerForTest(
    int count,
    const GURL& update_url,
    PendingExtensionManager* pending_extension_manager) {
  for (int i = 1; i <= count; ++i) {
    PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install =
        (i % 2 == 0) ? &ShouldInstallThemesOnly : &ShouldInstallExtensionsOnly;
    const bool kIsFromSync = true;
    const bool kMarkAcknowledged = false;
    const bool kRemoteInstall = false;
    std::string id =
        crx_file::id_util::GenerateId(base::StringPrintf("extension%i", i));

    pending_extension_manager->AddForTesting(
        PendingExtensionInfo(id,
                             std::string(),
                             update_url,
                             Version(),
                             should_allow_install,
                             kIsFromSync,
                             Manifest::INTERNAL,
                             Extension::NO_FLAGS,
                             kMarkAcknowledged,
                             kRemoteInstall));
  }
}

class ServiceForManifestTests : public MockService {
 public:
  explicit ServiceForManifestTests(TestExtensionPrefs* prefs)
      : MockService(prefs),
        registry_(ExtensionRegistry::Get(profile())) {
  }

  ~ServiceForManifestTests() override {}

  const Extension* GetExtensionById(const std::string& id,
                                    bool include_disabled) const override {
    const Extension* result = registry_->enabled_extensions().GetByID(id);
    if (result || !include_disabled)
      return result;
    return registry_->disabled_extensions().GetByID(id);
  }

  PendingExtensionManager* pending_extension_manager() override {
    return &pending_extension_manager_;
  }

  const Extension* GetPendingExtensionUpdate(
      const std::string& id) const override {
    return NULL;
  }

  bool IsExtensionEnabled(const std::string& id) const override {
    return !registry_->disabled_extensions().Contains(id);
  }

  void set_extensions(ExtensionList extensions,
                      ExtensionList disabled_extensions) {
    registry_->ClearAll();
    for (ExtensionList::const_iterator it = extensions.begin();
         it != extensions.end(); ++it) {
      registry_->AddEnabled(*it);
    }
    for (ExtensionList::const_iterator it = disabled_extensions.begin();
         it != disabled_extensions.end(); ++it) {
      registry_->AddDisabled(*it);
    }
  }

 private:
  ExtensionRegistry* registry_;
};

class ServiceForDownloadTests : public MockService {
 public:
  explicit ServiceForDownloadTests(TestExtensionPrefs* prefs)
      : MockService(prefs) {
  }

  // Add a fake crx installer to be returned by a call to UpdateExtension()
  // with a specific ID.  Caller keeps ownership of |crx_installer|.
  void AddFakeCrxInstaller(const std::string& id, CrxInstaller* crx_installer) {
    fake_crx_installers_[id] = crx_installer;
  }

  bool UpdateExtension(const CRXFileInfo& file,
                       bool file_ownership_passed,
                       CrxInstaller** out_crx_installer) override {
    extension_id_ = file.extension_id;
    install_path_ = file.path;

    if (ContainsKey(fake_crx_installers_, extension_id_)) {
      *out_crx_installer = fake_crx_installers_[extension_id_];
      return true;
    }

    return false;
  }

  PendingExtensionManager* pending_extension_manager() override {
    return &pending_extension_manager_;
  }

  const Extension* GetExtensionById(const std::string& id,
                                    bool) const override {
    last_inquired_extension_id_ = id;
    return NULL;
  }

  const std::string& extension_id() const { return extension_id_; }
  const base::FilePath& install_path() const { return install_path_; }

 private:
  // Hold the set of ids that UpdateExtension() should fake success on.
  // UpdateExtension(id, ...) will return true iff fake_crx_installers_
  // contains key |id|.  |out_install_notification_source| will be set
  // to Source<CrxInstaller(fake_crx_installers_[i]).
  std::map<std::string, CrxInstaller*> fake_crx_installers_;

  std::string extension_id_;
  base::FilePath install_path_;
  GURL download_url_;

  // The last extension ID that GetExtensionById was called with.
  // Mutable because the method that sets it (GetExtensionById) is const
  // in the actual extension service, but must record the last extension
  // ID in this test class.
  mutable std::string last_inquired_extension_id_;
};

static const int kUpdateFrequencySecs = 15;

// Takes a string with KEY=VALUE parameters separated by '&' in |params| and
// puts the key/value pairs into |result|. For keys with no value, the empty
// string is used. So for "a=1&b=foo&c", result would map "a" to "1", "b" to
// "foo", and "c" to "".
static void ExtractParameters(const std::string& params,
                              std::map<std::string, std::string>* result) {
  std::vector<std::string> pairs;
  base::SplitString(params, '&', &pairs);
  for (size_t i = 0; i < pairs.size(); i++) {
    std::vector<std::string> key_val;
    base::SplitString(pairs[i], '=', &key_val);
    if (!key_val.empty()) {
      std::string key = key_val[0];
      EXPECT_TRUE(result->find(key) == result->end());
      (*result)[key] = (key_val.size() == 2) ? key_val[1] : std::string();
    } else {
      NOTREACHED();
    }
  }
}

// Helper function to extract the ping data param values for each extension in
// a manifest fetch url, returned in a map keyed by extension id.
// E.g. for "x=id%3Dabcdef%26ping%3Ddr%253D1%2526dr%253D1024" we'd return
// {"abcdef": {"dr": set("1", "1024")}}
typedef std::map<std::string, std::set<std::string>> ParamsMap;
static std::map<std::string, ParamsMap> GetPingDataFromURL(
    const GURL& manifest_url) {
  std::map<std::string, ParamsMap> result;

  base::StringPairs toplevel_params;
  base::SplitStringIntoKeyValuePairs(
      manifest_url.query(), '=', '&', &toplevel_params);
  for (const auto& param : toplevel_params) {
    if (param.first != "x")
      continue;

    // We've found "x=<something>", now unescape <something> and look for
    // the "id=<id>&ping=<ping_value>" parameters within.
    std::string unescaped = net::UnescapeURLComponent(
        param.second, net::UnescapeRule::URL_SPECIAL_CHARS);
    base::StringPairs extension_params;
    base::SplitStringIntoKeyValuePairs(unescaped, '=', '&', &extension_params);
    std::multimap<std::string, std::string> param_map;
    param_map.insert(extension_params.begin(), extension_params.end());
    if (ContainsKey(param_map, "id") && ContainsKey(param_map, "ping")) {
      std::string id = param_map.find("id")->second;
      result[id] = ParamsMap();

      // Pull the key=value pairs out of the ping parameter for this id and
      // put into the result.
      std::string ping = net::UnescapeURLComponent(
          param_map.find("ping")->second, net::UnescapeRule::URL_SPECIAL_CHARS);
      base::StringPairs ping_params;
      base::SplitStringIntoKeyValuePairs(ping, '=', '&', &ping_params);
      for (const auto& ping_param : ping_params) {
        if (!ContainsKey(result[id], ping_param.first))
          result[id][ping_param.first] = std::set<std::string>();
        result[id][ping_param.first].insert(ping_param.second);
      }
    }
  }
  return result;
}

static void VerifyQueryAndExtractParameters(
    const std::string& query,
    std::map<std::string, std::string>* result) {
  std::map<std::string, std::string> params;
  ExtractParameters(query, &params);

  std::string omaha_params = UpdateQueryParams::Get(UpdateQueryParams::CRX);
  std::map<std::string, std::string> expected;
  ExtractParameters(omaha_params, &expected);

  for (std::map<std::string, std::string>::iterator it = expected.begin();
       it != expected.end(); ++it) {
    EXPECT_EQ(it->second, params[it->first]);
  }

  EXPECT_EQ(1U, params.count("x"));
  std::string decoded = net::UnescapeURLComponent(
      params["x"], net::UnescapeRule::URL_SPECIAL_CHARS);
  ExtractParameters(decoded, result);
}

// All of our tests that need to use private APIs of ExtensionUpdater live
// inside this class (which is a friend to ExtensionUpdater).
class ExtensionUpdaterTest : public testing::Test {
 public:
  ExtensionUpdaterTest()
      : thread_bundle_(
            content::TestBrowserThreadBundle::IO_MAINLOOP),
        testing_local_state_(TestingBrowserProcess::GetGlobal()) {
  }

  void SetUp() override {
    prefs_.reset(new TestExtensionPrefs(base::ThreadTaskRunnerHandle::Get()));
  }

  void TearDown() override {
    // Some tests create URLRequestContextGetters, whose destruction must run
    // on the IO thread. Make sure the IO loop spins before shutdown so that
    // those objects are released.
    RunUntilIdle();
    prefs_.reset();
  }

  void RunUntilIdle() {
    prefs_->pref_service()->CommitPendingWrite();
    base::RunLoop().RunUntilIdle();
  }

  void SimulateTimerFired(ExtensionUpdater* updater) {
    EXPECT_TRUE(updater->timer_.IsRunning());
    updater->timer_.Stop();
    updater->TimerFired();
    content::RunAllBlockingPoolTasksUntilIdle();
  }

  // Adds a Result with the given data to results.
  void AddParseResult(const std::string& id,
                      const std::string& version,
                      const std::string& url,
                      UpdateManifest::Results* results) {
    UpdateManifest::Result result;
    result.extension_id = id;
    result.version = version;
    result.crx_url = GURL(url);
    results->list.push_back(result);
  }

  void StartUpdateCheck(ExtensionDownloader* downloader,
                        ManifestFetchData* fetch_data) {
    downloader->StartUpdateCheck(scoped_ptr<ManifestFetchData>(fetch_data));
  }

  size_t ManifestFetchersCount(ExtensionDownloader* downloader) {
    return downloader->manifests_queue_.size() +
           (downloader->manifest_fetcher_.get() ? 1 : 0);
  }

  void TestExtensionUpdateCheckRequests(bool pending) {
    // Create an extension with an update_url.
    ServiceForManifestTests service(prefs_.get());
    std::string update_url("http://foo.com/bar");
    ExtensionList extensions;
    NotificationsObserver observer;
    PendingExtensionManager* pending_extension_manager =
        service.pending_extension_manager();
    if (pending) {
      SetupPendingExtensionManagerForTest(1, GURL(update_url),
                                          pending_extension_manager);
    } else {
      service.CreateTestExtensions(1, 1, &extensions, &update_url,
                                   Manifest::INTERNAL);
      service.set_extensions(extensions, ExtensionList());
    }

    // Set up and start the updater.
    net::TestURLFetcherFactory factory;
    ExtensionUpdater updater(&service,
                             service.extension_prefs(),
                             service.pref_service(),
                             service.profile(),
                             60 * 60 * 24,
                             NULL,
                             service.GetDownloaderFactory());
    updater.Start();

    // Tell the update that it's time to do update checks.
    EXPECT_EQ(0u, observer.StartedCount());
    SimulateTimerFired(&updater);
    EXPECT_EQ(1u, observer.StartedCount());

    // Get the url our mock fetcher was asked to fetch.
    net::TestURLFetcher* fetcher =
        factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    const GURL& url = fetcher->GetOriginalURL();
    EXPECT_FALSE(url.is_empty());
    EXPECT_TRUE(url.is_valid());
    EXPECT_TRUE(url.SchemeIs("http"));
    EXPECT_EQ("foo.com", url.host());
    EXPECT_EQ("/bar", url.path());

    // Validate the extension request parameters in the query. It should
    // look something like "x=id%3D<id>%26v%3D<version>%26uc".
    EXPECT_TRUE(url.has_query());
    std::map<std::string, std::string> params;
    VerifyQueryAndExtractParameters(url.query(), &params);
    if (pending) {
      EXPECT_TRUE(pending_extension_manager->IsIdPending(params["id"]));
      EXPECT_EQ("0.0.0.0", params["v"]);
    } else {
      EXPECT_EQ(extensions[0]->id(), params["id"]);
      EXPECT_EQ(extensions[0]->VersionString(), params["v"]);
    }
    EXPECT_EQ("", params["uc"]);
  }

  void TestUpdateUrlDataEmpty() {
    const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    const std::string version = "1.0";

    // Make sure that an empty update URL data string does not cause a ap=
    // option to appear in the x= parameter.
    scoped_ptr<ManifestFetchData> fetch_data(
        CreateManifestFetchData(GURL("http://localhost/foo")));
    fetch_data->AddExtension(
        id, version, &kNeverPingedData, std::string(), std::string(), false);

    std::map<std::string, std::string> params;
    VerifyQueryAndExtractParameters(fetch_data->full_url().query(), &params);
    EXPECT_EQ(id, params["id"]);
    EXPECT_EQ(version, params["v"]);
    EXPECT_EQ(0U, params.count("ap"));
  }

  void TestUpdateUrlDataSimple() {
    const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    const std::string version = "1.0";

    // Make sure that an update URL data string causes an appropriate ap=
    // option to appear in the x= parameter.
    scoped_ptr<ManifestFetchData> fetch_data(
        CreateManifestFetchData(GURL("http://localhost/foo")));
    fetch_data->AddExtension(
        id, version, &kNeverPingedData, "bar", std::string(), false);
    std::map<std::string, std::string> params;
    VerifyQueryAndExtractParameters(fetch_data->full_url().query(), &params);
    EXPECT_EQ(id, params["id"]);
    EXPECT_EQ(version, params["v"]);
    EXPECT_EQ("bar", params["ap"]);
  }

  void TestUpdateUrlDataCompound() {
    const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    const std::string version = "1.0";

    // Make sure that an update URL data string causes an appropriate ap=
    // option to appear in the x= parameter.
    scoped_ptr<ManifestFetchData> fetch_data(
        CreateManifestFetchData(GURL("http://localhost/foo")));
    fetch_data->AddExtension(
        id, version, &kNeverPingedData, "a=1&b=2&c", std::string(), false);
    std::map<std::string, std::string> params;
    VerifyQueryAndExtractParameters(fetch_data->full_url().query(), &params);
    EXPECT_EQ(id, params["id"]);
    EXPECT_EQ(version, params["v"]);
    EXPECT_EQ("a%3D1%26b%3D2%26c", params["ap"]);
  }

  void TestUpdateUrlDataFromGallery(const std::string& gallery_url) {
    net::TestURLFetcherFactory factory;

    MockService service(prefs_.get());
    MockExtensionDownloaderDelegate delegate;
    ExtensionDownloader downloader(&delegate, service.request_context());
    ExtensionList extensions;
    std::string url(gallery_url);

    service.CreateTestExtensions(1, 1, &extensions, &url, Manifest::INTERNAL);

    const std::string& id = extensions[0]->id();
    EXPECT_CALL(delegate, GetPingDataForExtension(id, _));

    downloader.AddExtension(*extensions[0].get(), 0);
    downloader.StartAllPending(NULL);
    net::TestURLFetcher* fetcher =
        factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    ASSERT_TRUE(fetcher);
    // Make sure that extensions that update from the gallery ignore any
    // update URL data.
    const std::string& update_url = fetcher->GetOriginalURL().spec();
    std::string::size_type x = update_url.find("x=");
    EXPECT_NE(std::string::npos, x);
    std::string::size_type ap = update_url.find("ap%3D", x);
    EXPECT_EQ(std::string::npos, ap);
  }

  void TestInstallSource() {
    const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    const std::string version = "1.0";
    const std::string install_source = "instally";

    // Make sure that an installsource= appears in the x= parameter.
    scoped_ptr<ManifestFetchData> fetch_data(
        CreateManifestFetchData(GURL("http://localhost/foo")));
    fetch_data->AddExtension(id, version, &kNeverPingedData,
                             kEmptyUpdateUrlData, install_source, false);
    std::map<std::string, std::string> params;
    VerifyQueryAndExtractParameters(fetch_data->full_url().query(), &params);
    EXPECT_EQ(id, params["id"]);
    EXPECT_EQ(version, params["v"]);
    EXPECT_EQ(install_source, params["installsource"]);
  }

  void TestDetermineUpdates() {
    TestingProfile profile;
    MockExtensionDownloaderDelegate delegate;
    ExtensionDownloader downloader(&delegate, profile.GetRequestContext());

    // Check passing an empty list of parse results to DetermineUpdates
    scoped_ptr<ManifestFetchData> fetch_data(
        CreateManifestFetchData(GURL("http://localhost/foo")));
    UpdateManifest::Results updates;
    std::vector<int> updateable;
    downloader.DetermineUpdates(*fetch_data, updates, &updateable);
    EXPECT_TRUE(updateable.empty());

    // Create two updates - expect that DetermineUpdates will return the first
    // one (v1.0 installed, v1.1 available) but not the second one (both
    // installed and available at v2.0).
    const std::string id1 = crx_file::id_util::GenerateId("1");
    const std::string id2 = crx_file::id_util::GenerateId("2");
    fetch_data->AddExtension(
        id1, "1.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string(),
        false);
    AddParseResult(id1, "1.1", "http://localhost/e1_1.1.crx", &updates);
    fetch_data->AddExtension(
        id2, "2.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string(),
        false);
    AddParseResult(id2, "2.0.0.0", "http://localhost/e2_2.0.crx", &updates);

    EXPECT_CALL(delegate, IsExtensionPending(_)).WillRepeatedly(Return(false));
    EXPECT_CALL(delegate, GetExtensionExistingVersion(id1, _))
        .WillOnce(DoAll(SetArgPointee<1>("1.0.0.0"),
                        Return(true)));
    EXPECT_CALL(delegate, GetExtensionExistingVersion(id2, _))
        .WillOnce(DoAll(SetArgPointee<1>("2.0.0.0"),
                        Return(true)));

    downloader.DetermineUpdates(*fetch_data, updates, &updateable);
    EXPECT_EQ(1u, updateable.size());
    EXPECT_EQ(0, updateable[0]);
  }

  void TestDetermineUpdatesPending() {
    // Create a set of test extensions
    ServiceForManifestTests service(prefs_.get());
    PendingExtensionManager* pending_extension_manager =
        service.pending_extension_manager();
    SetupPendingExtensionManagerForTest(3, GURL(), pending_extension_manager);

    TestingProfile profile;
    MockExtensionDownloaderDelegate delegate;
    ExtensionDownloader downloader(&delegate, profile.GetRequestContext());

    scoped_ptr<ManifestFetchData> fetch_data(
        CreateManifestFetchData(GURL("http://localhost/foo")));
    UpdateManifest::Results updates;

    std::list<std::string> ids_for_update_check;
    pending_extension_manager->GetPendingIdsForUpdateCheck(
        &ids_for_update_check);

    std::list<std::string>::const_iterator it;
    for (it = ids_for_update_check.begin();
         it != ids_for_update_check.end(); ++it) {
      fetch_data->AddExtension(*it,
                               "1.0.0.0",
                               &kNeverPingedData,
                               kEmptyUpdateUrlData,
                               std::string(),
                               false);
      AddParseResult(*it, "1.1", "http://localhost/e1_1.1.crx", &updates);
    }

    // The delegate will tell the downloader that all the extensions are
    // pending.
    EXPECT_CALL(delegate, IsExtensionPending(_)).WillRepeatedly(Return(true));

    std::vector<int> updateable;
    downloader.DetermineUpdates(*fetch_data, updates, &updateable);
    // All the apps should be updateable.
    EXPECT_EQ(3u, updateable.size());
    for (std::vector<int>::size_type i = 0; i < updateable.size(); ++i) {
      EXPECT_EQ(static_cast<int>(i), updateable[i]);
    }
  }

  void TestMultipleManifestDownloading() {
    net::TestURLFetcherFactory factory;
    factory.set_remove_fetcher_on_delete(true);
    net::TestURLFetcher* fetcher = NULL;
    MockService service(prefs_.get());
    MockExtensionDownloaderDelegate delegate;
    ExtensionDownloader downloader(&delegate, service.request_context());
    downloader.manifests_queue_.set_backoff_policy(&kNoBackoffPolicy);

    GURL kUpdateUrl("http://localhost/manifest1");

    scoped_ptr<ManifestFetchData> fetch1(CreateManifestFetchData(kUpdateUrl));
    scoped_ptr<ManifestFetchData> fetch2(CreateManifestFetchData(kUpdateUrl));
    scoped_ptr<ManifestFetchData> fetch3(CreateManifestFetchData(kUpdateUrl));
    scoped_ptr<ManifestFetchData> fetch4(CreateManifestFetchData(kUpdateUrl));
    ManifestFetchData::PingData zeroDays(0, 0, true, 0);
    fetch1->AddExtension(
        "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
    fetch2->AddExtension(
        "2222", "2.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
    fetch3->AddExtension(
        "3333", "3.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);
    fetch4->AddExtension(
        "4444", "4.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);

    // This will start the first fetcher and queue the others. The next in queue
    // is started as each fetcher receives its response. Note that the fetchers
    // don't necessarily run in the order that they are started from here.
    GURL fetch1_url = fetch1->full_url();
    GURL fetch2_url = fetch2->full_url();
    GURL fetch3_url = fetch3->full_url();
    GURL fetch4_url = fetch4->full_url();
    downloader.StartUpdateCheck(fetch1.Pass());
    downloader.StartUpdateCheck(fetch2.Pass());
    downloader.StartUpdateCheck(fetch3.Pass());
    downloader.StartUpdateCheck(fetch4.Pass());
    RunUntilIdle();

    for (int i = 0; i < 4; ++i) {
      fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
      ASSERT_TRUE(fetcher);
      ASSERT_TRUE(fetcher->delegate());
      EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
      EXPECT_FALSE(fetcher->GetOriginalURL().is_empty());

      if (fetcher->GetOriginalURL() == fetch1_url) {
        // The first fetch will fail.
        EXPECT_CALL(delegate, OnExtensionDownloadFailed(
            "1111", ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED, _, _));
        fetcher->set_url(kUpdateUrl);
        fetcher->set_status(net::URLRequestStatus());
        fetcher->set_response_code(400);
        fetcher->delegate()->OnURLFetchComplete(fetcher);
        RunUntilIdle();
        Mock::VerifyAndClearExpectations(&delegate);
        fetch1_url = GURL();
      } else if (fetcher->GetOriginalURL() == fetch2_url) {
        // The second fetch gets invalid data.
        const std::string kInvalidXml = "invalid xml";
        EXPECT_CALL(delegate, OnExtensionDownloadFailed(
            "2222", ExtensionDownloaderDelegate::MANIFEST_INVALID, _, _))
            .WillOnce(InvokeWithoutArgs(
                &delegate,
                &MockExtensionDownloaderDelegate::Quit));
        fetcher->set_url(kUpdateUrl);
        fetcher->set_status(net::URLRequestStatus());
        fetcher->set_response_code(200);
        fetcher->SetResponseString(kInvalidXml);
        fetcher->delegate()->OnURLFetchComplete(fetcher);
        delegate.Wait();
        Mock::VerifyAndClearExpectations(&delegate);
        fetch2_url = GURL();
      } else if (fetcher->GetOriginalURL() == fetch3_url) {
        // The third fetcher doesn't have an update available.
        const std::string kNoUpdate =
            "<?xml version='1.0' encoding='UTF-8'?>"
            "<gupdate xmlns='http://www.google.com/update2/response'"
            "                protocol='2.0'>"
            " <app appid='3333'>"
            "  <updatecheck codebase='http://example.com/extension_3.0.0.0.crx'"
            "               version='3.0.0.0' prodversionmin='3.0.0.0' />"
            " </app>"
            "</gupdate>";
        EXPECT_CALL(delegate, IsExtensionPending("3333"))
            .WillOnce(Return(false));
        EXPECT_CALL(delegate, GetExtensionExistingVersion("3333", _))
            .WillOnce(DoAll(SetArgPointee<1>("3.0.0.0"),
                            Return(true)));
        EXPECT_CALL(delegate, OnExtensionDownloadFailed(
            "3333", ExtensionDownloaderDelegate::NO_UPDATE_AVAILABLE, _, _))
            .WillOnce(InvokeWithoutArgs(
                &delegate,
                &MockExtensionDownloaderDelegate::Quit));
        fetcher->set_url(kUpdateUrl);
        fetcher->set_status(net::URLRequestStatus());
        fetcher->set_response_code(200);
        fetcher->SetResponseString(kNoUpdate);
        fetcher->delegate()->OnURLFetchComplete(fetcher);
        delegate.Wait();
        Mock::VerifyAndClearExpectations(&delegate);
        fetch3_url = GURL();
      } else if (fetcher->GetOriginalURL() == fetch4_url) {
        // The last fetcher has an update.
        NotificationsObserver observer;
        const std::string kUpdateAvailable =
            "<?xml version='1.0' encoding='UTF-8'?>"
            "<gupdate xmlns='http://www.google.com/update2/response'"
            "                protocol='2.0'>"
            " <app appid='4444'>"
            "  <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'"
            "               version='4.0.42.0' prodversionmin='4.0.42.0' />"
            " </app>"
            "</gupdate>";
        EXPECT_CALL(delegate, IsExtensionPending("4444"))
            .WillOnce(Return(false));
        EXPECT_CALL(delegate, GetExtensionExistingVersion("4444", _))
            .WillOnce(DoAll(SetArgPointee<1>("4.0.0.0"),
                            Return(true)));
        fetcher->set_url(kUpdateUrl);
        fetcher->set_status(net::URLRequestStatus());
        fetcher->set_response_code(200);
        fetcher->SetResponseString(kUpdateAvailable);
        fetcher->delegate()->OnURLFetchComplete(fetcher);
        observer.Wait();
        Mock::VerifyAndClearExpectations(&delegate);

        // Verify that the downloader decided to update this extension.
        EXPECT_EQ(1u, observer.UpdatedCount());
        EXPECT_TRUE(observer.Updated("4444"));
        fetch4_url = GURL();
      } else {
        ADD_FAILURE() << "Unexpected fetch: " << fetcher->GetOriginalURL();
      }
    }

    fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    if (fetcher)
      ADD_FAILURE() << "Unexpected fetch: " << fetcher->GetOriginalURL();
  }

  void TestManifestRetryDownloading() {
    net::TestURLFetcherFactory factory;
    net::TestURLFetcher* fetcher = NULL;
    NotificationsObserver observer;
    MockService service(prefs_.get());
    MockExtensionDownloaderDelegate delegate;
    ExtensionDownloader downloader(&delegate, service.request_context());
    downloader.manifests_queue_.set_backoff_policy(&kNoBackoffPolicy);

    GURL kUpdateUrl("http://localhost/manifest1");

    scoped_ptr<ManifestFetchData> fetch(CreateManifestFetchData(kUpdateUrl));
    ManifestFetchData::PingData zeroDays(0, 0, true, 0);
    fetch->AddExtension(
        "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);

    // This will start the first fetcher.
    downloader.StartUpdateCheck(fetch.Pass());
    RunUntilIdle();

    // ExtensionDownloader should retry kMaxRetries times and then fail.
    EXPECT_CALL(delegate, OnExtensionDownloadFailed(
        "1111", ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED, _, _));
    for (int i = 0; i <= ExtensionDownloader::kMaxRetries; ++i) {
      // All fetches will fail.
      fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
      EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
      EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
      fetcher->set_url(kUpdateUrl);
      fetcher->set_status(net::URLRequestStatus());
      // Code 5xx causes ExtensionDownloader to retry.
      fetcher->set_response_code(500);
      fetcher->delegate()->OnURLFetchComplete(fetcher);
      RunUntilIdle();
    }
    Mock::VerifyAndClearExpectations(&delegate);


    // For response codes that are not in the 5xx range ExtensionDownloader
    // should not retry.
    fetch.reset(CreateManifestFetchData(kUpdateUrl));
    fetch->AddExtension(
        "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false);

    // This will start the first fetcher.
    downloader.StartUpdateCheck(fetch.Pass());
    RunUntilIdle();

    EXPECT_CALL(delegate, OnExtensionDownloadFailed(
        "1111", ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED, _, _));
    // The first fetch will fail, and require retrying.
    fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
    fetcher->set_url(kUpdateUrl);
    fetcher->set_status(net::URLRequestStatus());
    fetcher->set_response_code(500);
    fetcher->delegate()->OnURLFetchComplete(fetcher);
    RunUntilIdle();

    // The second fetch will fail with response 400 and should not cause
    // ExtensionDownloader to retry.
    fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
    fetcher->set_url(kUpdateUrl);
    fetcher->set_status(net::URLRequestStatus());
    fetcher->set_response_code(400);
    fetcher->delegate()->OnURLFetchComplete(fetcher);
    RunUntilIdle();

    Mock::VerifyAndClearExpectations(&delegate);
  }

  void TestSingleExtensionDownloading(bool pending, bool retry, bool fail) {
    net::TestURLFetcherFactory factory;
    net::TestURLFetcher* fetcher = NULL;
    scoped_ptr<ServiceForDownloadTests> service(
        new ServiceForDownloadTests(prefs_.get()));
    ExtensionUpdater updater(service.get(),
                             service->extension_prefs(),
                             service->pref_service(),
                             service->profile(),
                             kUpdateFrequencySecs,
                             NULL,
                             service->GetDownloaderFactory());
    MockExtensionDownloaderDelegate delegate;
    delegate.DelegateTo(&updater);
    service->OverrideDownloaderDelegate(&delegate);
    updater.Start();
    updater.EnsureDownloaderCreated();
    updater.downloader_->extensions_queue_.set_backoff_policy(
        &kNoBackoffPolicy);

    GURL test_url("http://localhost/extension.crx");

    std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    std::string hash;
    Version version("0.0.1");
    std::set<int> requests;
    requests.insert(0);
    scoped_ptr<ExtensionDownloader::ExtensionFetch> fetch(
        new ExtensionDownloader::ExtensionFetch(
            id, test_url, hash, version.GetString(), requests));
    updater.downloader_->FetchUpdatedExtension(fetch.Pass());

    if (pending) {
      const bool kIsFromSync = true;
      const bool kMarkAcknowledged = false;
      const bool kRemoteInstall = false;
      PendingExtensionManager* pending_extension_manager =
          service->pending_extension_manager();
      pending_extension_manager->AddForTesting(
          PendingExtensionInfo(id,
                               std::string(),
                               test_url,
                               version,
                               &ShouldAlwaysInstall,
                               kIsFromSync,
                               Manifest::INTERNAL,
                               Extension::NO_FLAGS,
                               kMarkAcknowledged,
                               kRemoteInstall));
    }

    // Call back the ExtensionUpdater with a 200 response and some test data
    base::FilePath extension_file_path(FILE_PATH_LITERAL("/whatever"));
    fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);

    if (retry) {
      // Reply with response code 500 to cause ExtensionDownloader to retry
      fetcher->set_url(test_url);
      fetcher->set_status(net::URLRequestStatus());
      fetcher->set_response_code(500);
      fetcher->delegate()->OnURLFetchComplete(fetcher);

      RunUntilIdle();
      fetcher = factory.GetFetcherByID(
          ExtensionDownloader::kExtensionFetcherId);
      EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
      EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
    }

    fetcher->set_url(test_url);
    fetcher->set_status(net::URLRequestStatus());
    if (fail) {
      fetcher->set_response_code(404);
      EXPECT_CALL(delegate, OnExtensionDownloadFailed(id, _, _, requests));
    } else {
      fetcher->set_response_code(200);
      fetcher->SetResponseFilePath(extension_file_path);
      EXPECT_CALL(delegate, OnExtensionDownloadFinished(
                                CRXFileInfo(id, extension_file_path, hash), _,
                                _, version.GetString(), _, requests, _));
    }
    fetcher->delegate()->OnURLFetchComplete(fetcher);

    RunUntilIdle();

    if (fail) {
      // Don't expect any extension to have been installed.
      EXPECT_TRUE(service->extension_id().empty());
    } else {
      // Expect that ExtensionUpdater asked the mock extensions service to
      // install a file with the test data for the right id.
      EXPECT_EQ(id, service->extension_id());
      base::FilePath tmpfile_path = service->install_path();
      EXPECT_FALSE(tmpfile_path.empty());
      EXPECT_EQ(extension_file_path, tmpfile_path);
    }
  }

  // Update a single extension in an environment where the download request
  // initially responds with a 403 status. If |identity_provider| is not NULL,
  // this will first expect a request which includes an Authorization header
  // with an OAuth2 bearer token; otherwise, or if OAuth2 failure is simulated,
  // this expects the downloader to fall back onto cookie-based credentials.
  void TestProtectedDownload(
      const std::string& url_prefix,
      bool enable_oauth2,
      bool succeed_with_oauth2,
      int valid_authuser,
      int max_authuser) {
    net::TestURLFetcherFactory factory;
    net::TestURLFetcher* fetcher = NULL;
    scoped_ptr<ServiceForDownloadTests> service(
        new ServiceForDownloadTests(prefs_.get()));
    const ExtensionDownloader::Factory& downloader_factory =
        enable_oauth2 ? service->GetAuthenticatedDownloaderFactory()
            : service->GetDownloaderFactory();
    ExtensionUpdater updater(
        service.get(),
        service->extension_prefs(),
        service->pref_service(),
        service->profile(),
        kUpdateFrequencySecs,
        NULL,
        downloader_factory);
    updater.Start();
    updater.EnsureDownloaderCreated();
    updater.downloader_->extensions_queue_.set_backoff_policy(
        &kNoBackoffPolicy);

    GURL test_url(base::StringPrintf("%s/extension.crx", url_prefix.c_str()));
    std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    std::string hash;
  Version version("0.0.1");
    std::set<int> requests;
    requests.insert(0);
    scoped_ptr<ExtensionDownloader::ExtensionFetch> fetch(
        new ExtensionDownloader::ExtensionFetch(
            id, test_url, hash, version.GetString(), requests));
    updater.downloader_->FetchUpdatedExtension(fetch.Pass());

    fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    EXPECT_EQ(kExpectedLoadFlags, fetcher->GetLoadFlags());

    // Fake a 403 response.
    fetcher->set_url(test_url);
    fetcher->set_status(net::URLRequestStatus());
    fetcher->set_response_code(403);
    fetcher->delegate()->OnURLFetchComplete(fetcher);

    if (service->fake_token_service()) {
      service->fake_token_service()->IssueAllTokensForAccount(
          kFakeAccountId, kFakeOAuth2Token, base::Time::Now());
    }
    RunUntilIdle();

    bool using_oauth2 = false;
    int expected_load_flags = kExpectedLoadFlags;
    // Verify that the fetch has had its credentials properly incremented.
    fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    net::HttpRequestHeaders fetch_headers;
    fetcher->GetExtraRequestHeaders(&fetch_headers);
    // If the download URL is not https, no credentials should be provided.
    if (!test_url.SchemeIsCryptographic()) {
      // No cookies.
      EXPECT_EQ(kExpectedLoadFlags, fetcher->GetLoadFlags());
      // No Authorization header.
      EXPECT_FALSE(fetch_headers.HasHeader(
          net::HttpRequestHeaders::kAuthorization));
      expected_load_flags = kExpectedLoadFlags;
    } else {
      // HTTPS is in use, so credentials are allowed.
      if (enable_oauth2 && test_url.DomainIs("google.com")) {
        // If an IdentityProvider is present and the URL is a google.com
        // URL, the fetcher should be in OAuth2 mode after the intitial
        // challenge.
        EXPECT_TRUE(fetch_headers.HasHeader(
            net::HttpRequestHeaders::kAuthorization));
        std::string expected_header_value = base::StringPrintf("Bearer %s",
            kFakeOAuth2Token);
        std::string actual_header_value;
        fetch_headers.GetHeader(net::HttpRequestHeaders::kAuthorization,
                                &actual_header_value);
        EXPECT_EQ(expected_header_value, actual_header_value);
        using_oauth2 = true;
      } else {
        // No IdentityProvider (or no google.com), so expect cookies instead of
        // an Authorization header.
        EXPECT_FALSE(fetch_headers.HasHeader(
            net::HttpRequestHeaders::kAuthorization));
        EXPECT_EQ(kExpectedLoadFlagsForDownloadWithCookies,
            fetcher->GetLoadFlags());
        expected_load_flags = kExpectedLoadFlagsForDownloadWithCookies;
      }
    }

    bool success = false;
    if (using_oauth2) {
      if (succeed_with_oauth2) {
        success = true;
      } else {
        // Simulate OAuth2 failure and ensure that we fall back on cookies.
        fetcher->set_url(test_url);
        fetcher->set_status(net::URLRequestStatus());
        fetcher->set_response_code(403);
        fetcher->delegate()->OnURLFetchComplete(fetcher);
        RunUntilIdle();

        const ExtensionDownloader::ExtensionFetch& fetch =
            *updater.downloader_->extensions_queue_.active_request();
        EXPECT_EQ(0, GetAuthUserQueryValue(fetch.url));
        EXPECT_EQ(ExtensionDownloader::ExtensionFetch::CREDENTIALS_COOKIES,
                  fetch.credentials);

        fetcher = factory.GetFetcherByID(
            ExtensionDownloader::kExtensionFetcherId);
        EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
        fetcher->GetExtraRequestHeaders(&fetch_headers);
        EXPECT_FALSE(fetch_headers.HasHeader(
            net::HttpRequestHeaders::kAuthorization));
        EXPECT_EQ(kExpectedLoadFlagsForDownloadWithCookies,
            fetcher->GetLoadFlags());
        expected_load_flags = kExpectedLoadFlagsForDownloadWithCookies;
      }
    }

    if (!success) {
      // Not yet ready to simulate a successful fetch. At this point we begin
      // simulating cookie-based authentication with increasing values of
      // authuser (starting from 0.)
      int user_index = 0;
      for (; user_index <= max_authuser; ++user_index) {
        const ExtensionDownloader::ExtensionFetch& fetch =
            *updater.downloader_->extensions_queue_.active_request();
        EXPECT_EQ(user_index, GetAuthUserQueryValue(fetch.url));
        if (user_index == valid_authuser) {
          success = true;
          break;
        }
        // Simulate an authorization failure which should elicit an increment
        // of the authuser value.
        fetcher =
            factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
        EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
        EXPECT_EQ(expected_load_flags, fetcher->GetLoadFlags());
        fetcher->set_url(fetch.url);
        fetcher->set_status(net::URLRequestStatus());
        fetcher->set_response_code(403);
        fetcher->delegate()->OnURLFetchComplete(fetcher);
        RunUntilIdle();
      }

      // Simulate exhaustion of all available authusers.
      if (!success && user_index > max_authuser) {
        const ExtensionDownloader::ExtensionFetch& fetch =
            *updater.downloader_->extensions_queue_.active_request();
        fetcher =
            factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
        EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
        fetcher->set_url(fetch.url);
        fetcher->set_status(net::URLRequestStatus());
        fetcher->set_response_code(401);
        fetcher->delegate()->OnURLFetchComplete(fetcher);
        RunUntilIdle();
      }
    }

    // Simulate successful authorization with a 200 response.
    if (success) {
      fetcher =
          factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
      EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
      base::FilePath extension_file_path(FILE_PATH_LITERAL("/whatever"));
      fetcher->set_url(test_url);
      fetcher->set_status(net::URLRequestStatus());
      fetcher->set_response_code(200);
      fetcher->SetResponseFilePath(extension_file_path);
      fetcher->delegate()->OnURLFetchComplete(fetcher);
      RunUntilIdle();

      // Verify installation would proceed as normal.
      EXPECT_EQ(id, service->extension_id());
      base::FilePath tmpfile_path = service->install_path();
      EXPECT_FALSE(tmpfile_path.empty());
      EXPECT_EQ(extension_file_path, tmpfile_path);
    }
  }

  // Two extensions are updated.  If |updates_start_running| is true, the
  // mock extensions service has UpdateExtension(...) return true, and
  // the test is responsible for creating fake CrxInstallers.  Otherwise,
  // UpdateExtension() returns false, signaling install failures.
  void TestMultipleExtensionDownloading(bool updates_start_running) {
    net::TestURLFetcherFactory factory;
    net::TestURLFetcher* fetcher = NULL;
    ServiceForDownloadTests service(prefs_.get());
    ExtensionUpdater updater(&service,
                             service.extension_prefs(),
                             service.pref_service(),
                             service.profile(),
                             kUpdateFrequencySecs,
                             NULL,
                             service.GetDownloaderFactory());
    updater.Start();
    updater.EnsureDownloaderCreated();
    updater.downloader_->extensions_queue_.set_backoff_policy(
        &kNoBackoffPolicy);

    EXPECT_FALSE(updater.crx_install_is_running_);

    GURL url1("http://localhost/extension1.crx");
    GURL url2("http://localhost/extension2.crx");

    std::string id1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    std::string id2 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";

    std::string hash1;
    std::string hash2;

    std::string version1 = "0.1";
    std::string version2 = "0.1";
    std::set<int> requests;
    requests.insert(0);
    // Start two fetches
    scoped_ptr<ExtensionDownloader::ExtensionFetch> fetch1(
        new ExtensionDownloader::ExtensionFetch(
            id1, url1, hash1, version1, requests));
    scoped_ptr<ExtensionDownloader::ExtensionFetch> fetch2(
        new ExtensionDownloader::ExtensionFetch(
            id2, url2, hash2, version2, requests));
    updater.downloader_->FetchUpdatedExtension(fetch1.Pass());
    updater.downloader_->FetchUpdatedExtension(fetch2.Pass());

    // Make the first fetch complete.
    base::FilePath extension_file_path(FILE_PATH_LITERAL("/whatever"));

    fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);

    // We need some CrxInstallers, and CrxInstallers require a real
    // ExtensionService.  Create one on the testing profile.  Any action
    // the CrxInstallers take is on the testing profile's extension
    // service, not on our mock |service|.  This allows us to fake
    // the CrxInstaller actions we want.
    TestingProfile profile;
    static_cast<TestExtensionSystem*>(ExtensionSystem::Get(&profile))
        ->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
                                 base::FilePath(), false);
    ExtensionService* extension_service =
        ExtensionSystem::Get(&profile)->extension_service();
    extension_service->set_extensions_enabled(true);
    extension_service->set_show_extensions_prompts(false);

    scoped_refptr<CrxInstaller> fake_crx1(
        CrxInstaller::CreateSilent(extension_service));
    scoped_refptr<CrxInstaller> fake_crx2(
        CrxInstaller::CreateSilent(extension_service));

    if (updates_start_running) {
      // Add fake CrxInstaller to be returned by service.UpdateExtension().
      service.AddFakeCrxInstaller(id1, fake_crx1.get());
      service.AddFakeCrxInstaller(id2, fake_crx2.get());
    } else {
      // If we don't add fake CRX installers, the mock service fakes a failure
      // starting the install.
    }

    fetcher->set_url(url1);
    fetcher->set_status(net::URLRequestStatus());
    fetcher->set_response_code(200);
    fetcher->SetResponseFilePath(extension_file_path);
    fetcher->delegate()->OnURLFetchComplete(fetcher);

    RunUntilIdle();

    // Expect that the service was asked to do an install with the right data.
    base::FilePath tmpfile_path = service.install_path();
    EXPECT_FALSE(tmpfile_path.empty());
    EXPECT_EQ(id1, service.extension_id());
    RunUntilIdle();

    // Make sure the second fetch finished and asked the service to do an
    // update.
    base::FilePath extension_file_path2(FILE_PATH_LITERAL("/whatever2"));
    fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);

    fetcher->set_url(url2);
    fetcher->set_status(net::URLRequestStatus());
    fetcher->set_response_code(200);
    fetcher->SetResponseFilePath(extension_file_path2);
    fetcher->delegate()->OnURLFetchComplete(fetcher);
    RunUntilIdle();

    if (updates_start_running) {
      EXPECT_TRUE(updater.crx_install_is_running_);

      // The second install should not have run, because the first has not
      // sent a notification that it finished.
      EXPECT_EQ(id1, service.extension_id());

      // Fake install notice.  This should start the second installation,
      // which will be checked below.
      fake_crx1->NotifyCrxInstallComplete(false);

      EXPECT_TRUE(updater.crx_install_is_running_);
    }

    EXPECT_EQ(id2, service.extension_id());
    EXPECT_FALSE(service.install_path().empty());

    // Make sure the correct crx contents were passed for the update call.
    EXPECT_EQ(extension_file_path2, service.install_path());

    if (updates_start_running) {
      EXPECT_TRUE(updater.crx_install_is_running_);
      fake_crx2->NotifyCrxInstallComplete(false);
    }
    EXPECT_FALSE(updater.crx_install_is_running_);
  }

  void TestGalleryRequestsWithBrand(bool use_organic_brand_code) {
    google_brand::BrandForTesting brand_for_testing(
        use_organic_brand_code ? "GGLS" : "TEST");

    // We want to test a variety of combinations of expected ping conditions for
    // rollcall and active pings.
    int ping_cases[] = { ManifestFetchData::kNeverPinged, 0, 1, 5 };

    for (size_t i = 0; i < arraysize(ping_cases); i++) {
      for (size_t j = 0; j < arraysize(ping_cases); j++) {
        for (size_t k = 0; k < 2; k++) {
          int rollcall_ping_days = ping_cases[i];
          int active_ping_days = ping_cases[j];
          // Skip cases where rollcall_ping_days == -1, but
          // active_ping_days > 0, because rollcall_ping_days == -1 means the
          // app was just installed and this is the first update check after
          // installation.
          if (rollcall_ping_days == ManifestFetchData::kNeverPinged &&
              active_ping_days > 0)
            continue;

          bool active_bit = k > 0;
          TestGalleryRequests(rollcall_ping_days, active_ping_days, active_bit,
                              !use_organic_brand_code);
          ASSERT_FALSE(HasFailure()) <<
            " rollcall_ping_days=" << ping_cases[i] <<
            " active_ping_days=" << ping_cases[j] <<
            " active_bit=" << active_bit;
        }
      }
    }
  }

  // Test requests to both a Google server and a non-google server. This allows
  // us to test various combinations of installed (ie roll call) and active
  // (ie app launch) ping scenarios. The invariant is that each type of ping
  // value should be present at most once per day, and can be calculated based
  // on the delta between now and the last ping time (or in the case of active
  // pings, that delta plus whether the app has been active).
  void TestGalleryRequests(int rollcall_ping_days,
                           int active_ping_days,
                           bool active_bit,
                           bool expect_brand_code) {
    net::TestURLFetcherFactory factory;

    // Set up 2 mock extensions, one with a google.com update url and one
    // without.
    prefs_.reset(new TestExtensionPrefs(base::ThreadTaskRunnerHandle::Get()));
    ServiceForManifestTests service(prefs_.get());
    ExtensionList tmp;
    GURL url1("http://clients2.google.com/service/update2/crx");
    GURL url2("http://www.somewebsite.com");
    service.CreateTestExtensions(1, 1, &tmp, &url1.possibly_invalid_spec(),
                                 Manifest::INTERNAL);
    service.CreateTestExtensions(2, 1, &tmp, &url2.possibly_invalid_spec(),
                                 Manifest::INTERNAL);
    EXPECT_EQ(2u, tmp.size());
    service.set_extensions(tmp, ExtensionList());

    ExtensionPrefs* prefs = service.extension_prefs();
    const std::string& id = tmp[0]->id();
    Time now = Time::Now();
    if (rollcall_ping_days == 0) {
      prefs->SetLastPingDay(id, now - TimeDelta::FromSeconds(15));
    } else if (rollcall_ping_days > 0) {
      Time last_ping_day = now -
                           TimeDelta::FromDays(rollcall_ping_days) -
                           TimeDelta::FromSeconds(15);
      prefs->SetLastPingDay(id, last_ping_day);
    }

    // Store a value for the last day we sent an active ping.
    if (active_ping_days == 0) {
      prefs->SetLastActivePingDay(id, now - TimeDelta::FromSeconds(15));
    } else if (active_ping_days > 0) {
      Time last_active_ping_day = now -
                                  TimeDelta::FromDays(active_ping_days) -
                                  TimeDelta::FromSeconds(15);
      prefs->SetLastActivePingDay(id, last_active_ping_day);
    }
    if (active_bit)
      prefs->SetActiveBit(id, true);

    ExtensionUpdater updater(&service,
                             service.extension_prefs(),
                             service.pref_service(),
                             service.profile(),
                             kUpdateFrequencySecs,
                             NULL,
                             service.GetDownloaderFactory());
    ExtensionUpdater::CheckParams params;
    updater.Start();
    updater.CheckNow(params);
    content::RunAllBlockingPoolTasksUntilIdle();

    // Make the updater do manifest fetching, and note the urls it tries to
    // fetch.
    std::vector<GURL> fetched_urls;
    net::TestURLFetcher* fetcher =
      factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    fetched_urls.push_back(fetcher->GetOriginalURL());

    fetcher->set_url(fetched_urls[0]);
    fetcher->set_status(net::URLRequestStatus());
    fetcher->set_response_code(500);
    fetcher->SetResponseString(std::string());
    fetcher->delegate()->OnURLFetchComplete(fetcher);

    fetcher = factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    fetched_urls.push_back(fetcher->GetOriginalURL());

    // The urls could have been fetched in either order, so use the host to
    // tell them apart and note the query each used.
    GURL url1_fetch_url;
    GURL url2_fetch_url;
    std::string url1_query;
    std::string url2_query;
    if (fetched_urls[0].host() == url1.host()) {
      url1_fetch_url = fetched_urls[0];
      url2_fetch_url = fetched_urls[1];

      url1_query = fetched_urls[0].query();
      url2_query = fetched_urls[1].query();
    } else if (fetched_urls[0].host() == url2.host()) {
      url1_fetch_url = fetched_urls[1];
      url2_fetch_url = fetched_urls[0];
      url1_query = fetched_urls[1].query();
      url2_query = fetched_urls[0].query();
    } else {
      NOTREACHED();
    }

    std::map<std::string, ParamsMap> url1_ping_data =
        GetPingDataFromURL(url1_fetch_url);
    ParamsMap url1_params = ParamsMap();
    if (!url1_ping_data.empty() && ContainsKey(url1_ping_data, id))
      url1_params = url1_ping_data[id];

    // First make sure the non-google query had no ping parameter.
    EXPECT_TRUE(GetPingDataFromURL(url2_fetch_url).empty());

    // Now make sure the google query had the correct ping parameter.
    bool did_rollcall = false;
    if (rollcall_ping_days != 0) {
      ASSERT_TRUE(ContainsKey(url1_params, "r"));
      ASSERT_EQ(1u, url1_params["r"].size());
      EXPECT_EQ(base::IntToString(rollcall_ping_days),
                *url1_params["r"].begin());
      did_rollcall = true;
    }
    if (active_bit && active_ping_days != 0 && did_rollcall) {
      ASSERT_TRUE(ContainsKey(url1_params, "a"));
      ASSERT_EQ(1u, url1_params["a"].size());
      EXPECT_EQ(base::IntToString(active_ping_days),
                *url1_params["a"].begin());
    }

    // Make sure the non-google query has no brand parameter.
    const std::string brand_string = "brand%3D";
    EXPECT_TRUE(url2_query.find(brand_string) == std::string::npos);

#if defined(GOOGLE_CHROME_BUILD)
    // Make sure the google query has a brand parameter, but only if the
    // brand is non-organic.
    if (expect_brand_code) {
      EXPECT_TRUE(url1_query.find(brand_string) != std::string::npos);
    } else {
      EXPECT_TRUE(url1_query.find(brand_string) == std::string::npos);
    }
#else
    // Chromium builds never add the brand to the parameter, even for google
    // queries.
    EXPECT_TRUE(url1_query.find(brand_string) == std::string::npos);
#endif

    RunUntilIdle();
  }

  // This makes sure that the extension updater properly stores the results
  // of a <daystart> tag from a manifest fetch in one of two cases: 1) This is
  // the first time we fetched the extension, or 2) We sent a ping value of
  // >= 1 day for the extension.
  void TestHandleManifestResults() {
    ServiceForManifestTests service(prefs_.get());
    GURL update_url("http://www.google.com/manifest");
    ExtensionList tmp;
    service.CreateTestExtensions(1, 1, &tmp, &update_url.spec(),
                                 Manifest::INTERNAL);
    service.set_extensions(tmp, ExtensionList());

    ExtensionUpdater updater(&service,
                             service.extension_prefs(),
                             service.pref_service(),
                             service.profile(),
                             kUpdateFrequencySecs,
                             nullptr,
                             service.GetDownloaderFactory());
    updater.Start();
    updater.EnsureDownloaderCreated();

    scoped_ptr<ManifestFetchData> fetch_data(
        CreateManifestFetchData(update_url));
    const Extension* extension = tmp[0].get();
    fetch_data->AddExtension(extension->id(),
                             extension->VersionString(),
                             &kNeverPingedData,
                             kEmptyUpdateUrlData,
                             std::string(),
                             false);
    UpdateManifest::Results results;
    results.daystart_elapsed_seconds = 750;

    updater.downloader_->HandleManifestResults(fetch_data.get(), &results);
    Time last_ping_day =
        service.extension_prefs()->LastPingDay(extension->id());
    EXPECT_FALSE(last_ping_day.is_null());
    int64 seconds_diff = (Time::Now() - last_ping_day).InSeconds();
    EXPECT_LT(seconds_diff - results.daystart_elapsed_seconds, 5);
  }

  // This lets us run a test with some enabled and some disabled
  // extensions. The |num_enabled| value specifies how many enabled extensions
  // to have, and |disabled| is a vector of DisableReason bitmasks for each
  // disabled extension we want.
  void TestPingMetrics(int num_enabled,
                       const std::vector<int>& disabled) {
    ServiceForManifestTests service(prefs_.get());
    ExtensionList enabled_extensions;
    ExtensionList disabled_extensions;

    std::string update_url = extension_urls::GetWebstoreUpdateUrl().spec();
    if (num_enabled > 0)
      service.CreateTestExtensions(
          1, num_enabled, &enabled_extensions, &update_url, Manifest::INTERNAL);
    if (disabled.size() > 0)
      service.CreateTestExtensions(2,
                                   disabled.size(),
                                   &disabled_extensions,
                                   &update_url,
                                   Manifest::INTERNAL);

    service.set_extensions(enabled_extensions, disabled_extensions);

    ExtensionPrefs* prefs = prefs_->prefs();

    for (size_t i = 0; i < disabled.size(); i++) {
      int reasons = disabled[i];
      const std::string& id = disabled_extensions[i]->id();
      // Iterate over the DisableReason values, marking that reason in prefs
      // for this id if it is set.
      for (int reason = 1; reason < Extension::DISABLE_REASON_LAST;
           reason <<= 1) {
        if (reasons & reason)
          prefs->AddDisableReason(
              id, static_cast<Extension::DisableReason>(reason));
      }
    }

    // Create the extension updater, make it issue an update, and capture the
    // URL that it tried to fetch.
    net::TestURLFetcherFactory factory;
    ExtensionUpdater updater(&service,
                             service.extension_prefs(),
                             service.pref_service(),
                             service.profile(),
                             kUpdateFrequencySecs,
                             nullptr,
                             service.GetDownloaderFactory());
    updater.Start();
    SimulateTimerFired(&updater);
    net::TestURLFetcher* fetcher =
        factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
    ASSERT_NE(nullptr, fetcher);
    const GURL& url = fetcher->GetOriginalURL();
    EXPECT_FALSE(url.is_empty());
    EXPECT_TRUE(url.is_valid());
    EXPECT_TRUE(url.has_query());

    std::map<std::string, ParamsMap> all_pings = GetPingDataFromURL(url);

    // Make sure that all the enabled extensions have "e=1" in their ping
    // parameter.
    for (const auto& ext : enabled_extensions) {
      ASSERT_TRUE(ContainsKey(all_pings, ext->id()));
      ParamsMap& ping = all_pings[ext->id()];
      EXPECT_FALSE(ContainsKey(ping, "dr"));
      ASSERT_TRUE(ContainsKey(ping, "e")) << url;
      std::set<std::string> e = ping["e"];
      ASSERT_EQ(1u, e.size()) << url;
      EXPECT_EQ(std::string("1"), *e.begin()) << url;
      EXPECT_FALSE(ContainsKey(ping, "dr"));
    }

    // Make sure that all the disable extensions have the appropriate
    // "dr=<num>" values in their ping parameter if metrics are on, or omit
    // it otherwise.
    ASSERT_EQ(disabled_extensions.size(), disabled.size());
    for (size_t i = 0; i < disabled.size(); i++) {
      scoped_refptr<const Extension>& ext = disabled_extensions[i];
      int disable_reasons = disabled[i];
      ASSERT_TRUE(ContainsKey(all_pings, ext->id())) << url;
      ParamsMap& ping = all_pings[ext->id()];

      ASSERT_TRUE(ContainsKey(ping, "e")) << url;
      std::set<std::string> e = ping["e"];
      ASSERT_EQ(1u, e.size()) << url;
      EXPECT_EQ(std::string("0"), *e.begin()) << url;

      if (disable_reasons == 0) {
        EXPECT_FALSE(ContainsKey(ping, "dr"));
      } else {
        ASSERT_TRUE(ContainsKey(ping, "dr"));
        int found_reasons = 0;
        for (const auto& reason_string : ping["dr"]) {
          int reason = 0;
          ASSERT_TRUE(base::StringToInt(reason_string, &reason));
          // Make sure it's a power of 2.
          ASSERT_TRUE(reason < 2 || !(reason & (reason - 1))) << reason;
          found_reasons |= reason;
        }
        EXPECT_EQ(disable_reasons, found_reasons);
      }
    }
  }

 protected:
  scoped_ptr<TestExtensionPrefs> prefs_;

  ManifestFetchData* CreateManifestFetchData(const GURL& update_url) {
    return new ManifestFetchData(update_url, 0, "",
                                 UpdateQueryParams::Get(UpdateQueryParams::CRX),
                                 ManifestFetchData::PING);
  }

 private:
  content::TestBrowserThreadBundle thread_bundle_;
  content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
  ScopedTestingLocalState testing_local_state_;

#if defined OS_CHROMEOS
  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
  chromeos::ScopedTestCrosSettings test_cros_settings_;
  chromeos::ScopedTestUserManager test_user_manager_;
#endif
};

// Because we test some private methods of ExtensionUpdater, it's easier for the
// actual test code to live in ExtenionUpdaterTest methods instead of TEST_F
// subclasses where friendship with ExtenionUpdater is not inherited.

TEST_F(ExtensionUpdaterTest, TestExtensionUpdateCheckRequests) {
  TestExtensionUpdateCheckRequests(false);
}

TEST_F(ExtensionUpdaterTest, TestExtensionUpdateCheckRequestsPending) {
  TestExtensionUpdateCheckRequests(true);
}

TEST_F(ExtensionUpdaterTest, TestUpdateUrlData) {
  TestUpdateUrlDataEmpty();
  TestUpdateUrlDataSimple();
  TestUpdateUrlDataCompound();
  TestUpdateUrlDataFromGallery(
      extension_urls::GetWebstoreUpdateUrl().spec());
}

TEST_F(ExtensionUpdaterTest, TestInstallSource) {
  TestInstallSource();
}

TEST_F(ExtensionUpdaterTest, TestDetermineUpdates) {
  TestDetermineUpdates();
}

TEST_F(ExtensionUpdaterTest, TestDetermineUpdatesPending) {
  TestDetermineUpdatesPending();
}

TEST_F(ExtensionUpdaterTest, TestMultipleManifestDownloading) {
  TestMultipleManifestDownloading();
}

TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloading) {
  TestSingleExtensionDownloading(false, false, false);
}

TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingPending) {
  TestSingleExtensionDownloading(true, false, false);
}

TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingWithRetry) {
  TestSingleExtensionDownloading(false, true, false);
}

TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingPendingWithRetry) {
  TestSingleExtensionDownloading(true, true, false);
}

TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingFailure) {
  TestSingleExtensionDownloading(false, false, true);
}

TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingFailureWithRetry) {
  TestSingleExtensionDownloading(false, true, true);
}

TEST_F(ExtensionUpdaterTest, TestSingleExtensionDownloadingFailurePending) {
  TestSingleExtensionDownloading(true, false, true);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadCookieAuth) {
  TestProtectedDownload(
      "https://chrome.google.com/webstore/download",
      false, false,  // No OAuth2 support
      0, 0);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadCookieFailure) {
  TestProtectedDownload(
      "https://chrome.google.com/webstore/download",
      false, false,  // No OAuth2 support
      0, -1);  // max_authuser=-1 simulates no valid authuser value.
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithNonDefaultAuthUser1) {
  TestProtectedDownload("https://google.com", false, false, 1, 1);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithNonDefaultAuthUser2) {
  TestProtectedDownload("https://google.com", false, false, 2, 2);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadAuthUserExhaustionFailure) {
  TestProtectedDownload("https://google.com", false, false, 2, 5);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithOAuth2Token) {
  TestProtectedDownload(
      "https://google.com",
      true, true,
      0, -1);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadWithOAuth2Failure) {
  TestProtectedDownload(
      "https://google.com",
      true, false,
      0, -1);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadNoOAuth2WithNonGoogleDomain) {
  TestProtectedDownload(
      "https://not-google.com",
      true, true,
      0, -1);
}

TEST_F(ExtensionUpdaterTest, ProtectedDownloadFailWithoutHTTPS) {
  TestProtectedDownload(
      "http://google.com",
      true, true,
      0, 0);
}

TEST_F(ExtensionUpdaterTest, TestMultipleExtensionDownloadingUpdatesFail) {
  TestMultipleExtensionDownloading(false);
}
TEST_F(ExtensionUpdaterTest, TestMultipleExtensionDownloadingUpdatesSucceed) {
  TestMultipleExtensionDownloading(true);
}

TEST_F(ExtensionUpdaterTest, TestManifestRetryDownloading) {
  TestManifestRetryDownloading();
}

TEST_F(ExtensionUpdaterTest, TestGalleryRequestsWithOrganicBrand) {
  TestGalleryRequestsWithBrand(true);
}

TEST_F(ExtensionUpdaterTest, TestGalleryRequestsWithNonOrganicBrand) {
  TestGalleryRequestsWithBrand(false);
}

TEST_F(ExtensionUpdaterTest, TestHandleManifestResults) {
  TestHandleManifestResults();
}

TEST_F(ExtensionUpdaterTest, TestNonAutoUpdateableLocations) {
  net::TestURLFetcherFactory factory;
  ServiceForManifestTests service(prefs_.get());
  ExtensionUpdater updater(&service,
                           service.extension_prefs(),
                           service.pref_service(),
                           service.profile(),
                           kUpdateFrequencySecs,
                           NULL,
                           service.GetDownloaderFactory());
  MockExtensionDownloaderDelegate delegate;
  service.OverrideDownloaderDelegate(&delegate);

  // Non-internal non-external extensions should be rejected.
  ExtensionList extensions;
  service.CreateTestExtensions(1, 1, &extensions, NULL,
                               Manifest::INVALID_LOCATION);
  service.CreateTestExtensions(2, 1, &extensions, NULL, Manifest::INTERNAL);
  ASSERT_EQ(2u, extensions.size());
  const std::string& updateable_id = extensions[1]->id();

  // These expectations fail if the delegate's methods are invoked for the
  // first extension, which has a non-matching id.
  EXPECT_CALL(delegate,
              GetUpdateUrlData(updateable_id)).WillOnce(Return(""));
  EXPECT_CALL(delegate, GetPingDataForExtension(updateable_id, _));

  service.set_extensions(extensions, ExtensionList());
  ExtensionUpdater::CheckParams params;
  updater.Start();
  updater.CheckNow(params);
  content::RunAllBlockingPoolTasksUntilIdle();
}

TEST_F(ExtensionUpdaterTest, TestUpdatingDisabledExtensions) {
  net::TestURLFetcherFactory factory;
  ServiceForManifestTests service(prefs_.get());
  ExtensionUpdater updater(&service,
                           service.extension_prefs(),
                           service.pref_service(),
                           service.profile(),
                           kUpdateFrequencySecs,
                           NULL,
                           service.GetDownloaderFactory());
  MockExtensionDownloaderDelegate delegate;
  service.OverrideDownloaderDelegate(&delegate);

  // Non-internal non-external extensions should be rejected.
  ExtensionList enabled_extensions;
  ExtensionList disabled_extensions;
  service.CreateTestExtensions(1, 1, &enabled_extensions, NULL,
      Manifest::INTERNAL);
  service.CreateTestExtensions(2, 1, &disabled_extensions, NULL,
      Manifest::INTERNAL);
  ASSERT_EQ(1u, enabled_extensions.size());
  ASSERT_EQ(1u, disabled_extensions.size());
  const std::string& enabled_id = enabled_extensions[0]->id();
  const std::string& disabled_id = disabled_extensions[0]->id();

  // We expect that both enabled and disabled extensions are auto-updated.
  EXPECT_CALL(delegate, GetUpdateUrlData(enabled_id)).WillOnce(Return(""));
  EXPECT_CALL(delegate, GetPingDataForExtension(enabled_id, _));
  EXPECT_CALL(delegate,
              GetUpdateUrlData(disabled_id)).WillOnce(Return(""));
  EXPECT_CALL(delegate, GetPingDataForExtension(disabled_id, _));

  service.set_extensions(enabled_extensions, disabled_extensions);
  ExtensionUpdater::CheckParams params;
  updater.Start();
  updater.CheckNow(params);
  content::RunAllBlockingPoolTasksUntilIdle();
}

TEST_F(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) {
  net::TestURLFetcherFactory factory;
  MockService service(prefs_.get());
  MockExtensionDownloaderDelegate delegate;
  scoped_ptr<ExtensionDownloader> downloader(
      new ExtensionDownloader(&delegate, service.request_context()));
  EXPECT_EQ(0u, ManifestFetchersCount(downloader.get()));

  // First, verify that adding valid extensions does invoke the callbacks on
  // the delegate.
  std::string id = crx_file::id_util::GenerateId("foo");
  EXPECT_CALL(delegate, GetPingDataForExtension(id, _)).WillOnce(Return(false));
  EXPECT_TRUE(
      downloader->AddPendingExtension(id, GURL("http://example.com/update"),
                                      0));
  downloader->StartAllPending(NULL);
  Mock::VerifyAndClearExpectations(&delegate);
  EXPECT_EQ(1u, ManifestFetchersCount(downloader.get()));

  // Extensions with invalid update URLs should be rejected.
  id = crx_file::id_util::GenerateId("foo2");
  EXPECT_FALSE(
      downloader->AddPendingExtension(id, GURL("http:google.com:foo"), 0));
  downloader->StartAllPending(NULL);
  EXPECT_EQ(1u, ManifestFetchersCount(downloader.get()));

  // Extensions with empty IDs should be rejected.
  EXPECT_FALSE(downloader->AddPendingExtension(std::string(), GURL(), 0));
  downloader->StartAllPending(NULL);
  EXPECT_EQ(1u, ManifestFetchersCount(downloader.get()));

  // TODO(akalin): Test that extensions with empty update URLs
  // converted from user scripts are rejected.

  // Reset the ExtensionDownloader so that it drops the current fetcher.
  downloader.reset(
      new ExtensionDownloader(&delegate, service.request_context()));
  EXPECT_EQ(0u, ManifestFetchersCount(downloader.get()));

  // Extensions with empty update URLs should have a default one
  // filled in.
  id = crx_file::id_util::GenerateId("foo3");
  EXPECT_CALL(delegate, GetPingDataForExtension(id, _)).WillOnce(Return(false));
  EXPECT_TRUE(downloader->AddPendingExtension(id, GURL(), 0));
  downloader->StartAllPending(NULL);
  EXPECT_EQ(1u, ManifestFetchersCount(downloader.get()));

  net::TestURLFetcher* fetcher =
      factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
  ASSERT_TRUE(fetcher);
  EXPECT_FALSE(fetcher->GetOriginalURL().is_empty());
}

TEST_F(ExtensionUpdaterTest, TestStartUpdateCheckMemory) {
  net::TestURLFetcherFactory factory;
  MockService service(prefs_.get());
  MockExtensionDownloaderDelegate delegate;
  ExtensionDownloader downloader(&delegate, service.request_context());

  StartUpdateCheck(&downloader,
                   CreateManifestFetchData(GURL("http://localhost/foo")));
  // This should delete the newly-created ManifestFetchData.
  StartUpdateCheck(&downloader,
                   CreateManifestFetchData(GURL("http://localhost/foo")));
  // This should add into |manifests_pending_|.
  StartUpdateCheck(&downloader,
                   CreateManifestFetchData(GURL("http://www.google.com")));
  // The dtor of |downloader| should delete the pending fetchers.
}

TEST_F(ExtensionUpdaterTest, TestCheckSoon) {
  ServiceForManifestTests service(prefs_.get());
  net::TestURLFetcherFactory factory;
  ExtensionUpdater updater(&service,
                           service.extension_prefs(),
                           service.pref_service(),
                           service.profile(),
                           kUpdateFrequencySecs,
                           NULL,
                           service.GetDownloaderFactory());
  EXPECT_FALSE(updater.WillCheckSoon());
  updater.Start();
  EXPECT_FALSE(updater.WillCheckSoon());
  updater.CheckSoon();
  EXPECT_TRUE(updater.WillCheckSoon());
  updater.CheckSoon();
  EXPECT_TRUE(updater.WillCheckSoon());
  RunUntilIdle();
  EXPECT_FALSE(updater.WillCheckSoon());
  updater.CheckSoon();
  EXPECT_TRUE(updater.WillCheckSoon());
  updater.Stop();
  EXPECT_FALSE(updater.WillCheckSoon());
}

TEST_F(ExtensionUpdaterTest, TestDisabledReasons1) {
  std::vector<int> disabled;
  disabled.push_back(Extension::DISABLE_USER_ACTION);
  disabled.push_back(Extension::DISABLE_PERMISSIONS_INCREASE |
                     Extension::DISABLE_CORRUPTED);
  TestPingMetrics(1, disabled);
}

TEST_F(ExtensionUpdaterTest, TestDisabledReasons2) {
  std::vector<int> disabled;
  TestPingMetrics(1, disabled);
}

TEST_F(ExtensionUpdaterTest, TestDisabledReasons3) {
  std::vector<int> disabled;
  disabled.push_back(0);
  TestPingMetrics(0, disabled);
}

// TODO(asargent) - (http://crbug.com/12780) add tests for:
// -prodversionmin (shouldn't update if browser version too old)
// -manifests & updates arriving out of order / interleaved
// -malformed update url (empty, file://, has query, has a # fragment, etc.)
// -An extension gets uninstalled while updates are in progress (so it doesn't
//  "come back from the dead")
// -An extension gets manually updated to v3 while we're downloading v2 (ie
//  you don't get downgraded accidentally)
// -An update manifest mentions multiple updates

}  // namespace extensions
