Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <map>
      6 
      7 #include "base/file_util.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/stl_util-inl.h"
     10 #include "base/string_number_conversions.h"
     11 #include "base/string_split.h"
     12 #include "base/string_util.h"
     13 #include "base/stringprintf.h"
     14 #include "base/threading/thread.h"
     15 #include "base/version.h"
     16 #include "chrome/browser/extensions/extension_error_reporter.h"
     17 #include "chrome/browser/extensions/extension_updater.h"
     18 #include "chrome/browser/extensions/extension_service.h"
     19 #include "chrome/browser/extensions/test_extension_prefs.h"
     20 #include "chrome/browser/prefs/pref_service.h"
     21 #include "chrome/common/extensions/extension.h"
     22 #include "chrome/common/extensions/extension_constants.h"
     23 #include "chrome/common/pref_names.h"
     24 #include "chrome/common/net/test_url_fetcher_factory.h"
     25 #include "chrome/test/testing_profile.h"
     26 #include "content/browser/browser_thread.h"
     27 #include "net/base/escape.h"
     28 #include "net/base/load_flags.h"
     29 #include "net/url_request/url_request_status.h"
     30 #include "testing/gtest/include/gtest/gtest.h"
     31 #include "libxml/globals.h"
     32 
     33 using base::Time;
     34 using base::TimeDelta;
     35 
     36 namespace {
     37 
     38 const char kEmptyUpdateUrlData[] = "";
     39 
     40 int expected_load_flags =
     41     net::LOAD_DO_NOT_SEND_COOKIES |
     42     net::LOAD_DO_NOT_SAVE_COOKIES |
     43     net::LOAD_DISABLE_CACHE;
     44 
     45 const ManifestFetchData::PingData kNeverPingedData(
     46     ManifestFetchData::kNeverPinged, ManifestFetchData::kNeverPinged);
     47 
     48 }  // namespace
     49 
     50 // Base class for further specialized test classes.
     51 class MockService : public ExtensionServiceInterface {
     52  public:
     53   MockService()
     54       : pending_extension_manager_(ALLOW_THIS_IN_INITIALIZER_LIST(*this)) {}
     55   virtual ~MockService() {}
     56 
     57   virtual const ExtensionList* extensions() const {
     58     ADD_FAILURE();
     59     return NULL;
     60   }
     61 
     62   virtual const ExtensionList* disabled_extensions() const {
     63     ADD_FAILURE();
     64     return NULL;
     65   }
     66 
     67   virtual void UpdateExtension(const std::string& id,
     68                                const FilePath& path,
     69                                const GURL& download_url) {
     70     FAIL();
     71   }
     72 
     73   virtual const Extension* GetExtensionById(const std::string& id,
     74                                             bool include_disabled) const {
     75     ADD_FAILURE();
     76     return NULL;
     77   }
     78 
     79   virtual bool UninstallExtension(const std::string& extension_id,
     80                                   bool external_uninstall,
     81                                   std::string* error) {
     82     ADD_FAILURE();
     83     return false;
     84   }
     85 
     86   virtual bool IsExtensionEnabled(const std::string& extension_id) const {
     87     ADD_FAILURE();
     88     return false;
     89   }
     90 
     91   virtual bool IsExternalExtensionUninstalled(
     92       const std::string& extension_id) const {
     93     ADD_FAILURE();
     94     return false;
     95   }
     96 
     97   virtual void EnableExtension(const std::string& extension_id) {
     98     FAIL();
     99   }
    100 
    101   virtual void DisableExtension(const std::string& extension_id) {
    102     FAIL();
    103   }
    104 
    105 
    106   virtual void UpdateExtensionBlacklist(
    107       const std::vector<std::string>& blacklist) {
    108     FAIL();
    109   }
    110 
    111   virtual void CheckAdminBlacklist() {
    112     FAIL();
    113   }
    114 
    115   virtual bool IsIncognitoEnabled(const std::string& id) const {
    116     ADD_FAILURE();
    117     return false;
    118   }
    119 
    120   virtual void SetIsIncognitoEnabled(const std::string& id,
    121                                      bool enabled) {
    122     FAIL();
    123   }
    124 
    125   virtual void CheckForUpdatesSoon() {
    126     FAIL();
    127   }
    128 
    129   virtual PendingExtensionManager* pending_extension_manager() {
    130     ADD_FAILURE() << "Subclass should override this if it will "
    131                   << "be accessed by a test.";
    132     return &pending_extension_manager_;
    133   }
    134 
    135   virtual void ProcessSyncData(
    136       const ExtensionSyncData& extension_sync_data,
    137       PendingExtensionInfo::ShouldAllowInstallPredicate
    138           should_allow_install) {
    139     FAIL();
    140   }
    141 
    142   Profile* profile() { return &profile_; }
    143 
    144   ExtensionPrefs* extension_prefs() { return prefs_.prefs(); }
    145 
    146   PrefService* pref_service() { return prefs_.pref_service(); }
    147 
    148   // Creates test extensions and inserts them into list. The name and
    149   // version are all based on their index. If |update_url| is non-null, it
    150   // will be used as the update_url for each extension.
    151   // The |id| is used to distinguish extension names and make sure that
    152   // no two extensions share the same name.
    153   void CreateTestExtensions(int id, int count, ExtensionList *list,
    154                             const std::string* update_url,
    155                             Extension::Location location) {
    156     for (int i = 1; i <= count; i++) {
    157       DictionaryValue manifest;
    158       manifest.SetString(extension_manifest_keys::kVersion,
    159                          base::StringPrintf("%d.0.0.0", i));
    160       manifest.SetString(extension_manifest_keys::kName,
    161                          base::StringPrintf("Extension %d.%d", id, i));
    162       if (update_url)
    163         manifest.SetString(extension_manifest_keys::kUpdateURL, *update_url);
    164       scoped_refptr<Extension> e =
    165           prefs_.AddExtensionWithManifest(manifest, location);
    166       ASSERT_TRUE(e != NULL);
    167       list->push_back(e);
    168     }
    169   }
    170 
    171  protected:
    172   PendingExtensionManager pending_extension_manager_;
    173   TestExtensionPrefs prefs_;
    174   TestingProfile profile_;
    175 
    176  private:
    177   DISALLOW_COPY_AND_ASSIGN(MockService);
    178 };
    179 
    180 
    181 std::string GenerateId(std::string input) {
    182   std::string result;
    183   EXPECT_TRUE(Extension::GenerateId(input, &result));
    184   return result;
    185 }
    186 
    187 bool ShouldInstallExtensionsOnly(const Extension& extension) {
    188   return extension.GetType() == Extension::TYPE_EXTENSION;
    189 }
    190 
    191 bool ShouldInstallThemesOnly(const Extension& extension) {
    192   return extension.is_theme();
    193 }
    194 
    195 bool ShouldAlwaysInstall(const Extension& extension) {
    196   return true;
    197 }
    198 
    199 // Loads some pending extension records into a pending extension manager.
    200 void SetupPendingExtensionManagerForTest(
    201     int count,
    202     const GURL& update_url,
    203     PendingExtensionManager* pending_extension_manager) {
    204   for (int i = 1; i <= count; i++) {
    205     PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install =
    206         (i % 2 == 0) ? &ShouldInstallThemesOnly : &ShouldInstallExtensionsOnly;
    207     const bool kIsFromSync = true;
    208     const bool kInstallSilently = true;
    209     const Extension::State kInitialState = Extension::ENABLED;
    210     const bool kInitialIncognitoEnabled = false;
    211     std::string id = GenerateId(base::StringPrintf("extension%i", i));
    212 
    213     pending_extension_manager->AddForTesting(
    214         id,
    215         PendingExtensionInfo(update_url,
    216                              should_allow_install,
    217                              kIsFromSync,
    218                              kInstallSilently,
    219                              kInitialState,
    220                              kInitialIncognitoEnabled,
    221                              Extension::INTERNAL));
    222   }
    223 }
    224 
    225 class ServiceForManifestTests : public MockService {
    226  public:
    227   ServiceForManifestTests() {}
    228 
    229   virtual ~ServiceForManifestTests() {}
    230 
    231   virtual const Extension* GetExtensionById(const std::string& id,
    232                                             bool include_disabled) const {
    233     for (ExtensionList::const_iterator iter = extensions_.begin();
    234         iter != extensions_.end(); ++iter) {
    235       if ((*iter)->id() == id) {
    236         return *iter;
    237       }
    238     }
    239     return NULL;
    240   }
    241 
    242   virtual const ExtensionList* extensions() const { return &extensions_; }
    243 
    244   virtual PendingExtensionManager* pending_extension_manager() {
    245     return &pending_extension_manager_;
    246   }
    247 
    248   void set_extensions(ExtensionList extensions) {
    249     extensions_ = extensions;
    250   }
    251 
    252  private:
    253   ExtensionList extensions_;
    254 };
    255 
    256 class ServiceForDownloadTests : public MockService {
    257  public:
    258   virtual void UpdateExtension(const std::string& id,
    259                                const FilePath& extension_path,
    260                                const GURL& download_url) {
    261     extension_id_ = id;
    262     install_path_ = extension_path;
    263     download_url_ = download_url;
    264   }
    265 
    266   virtual PendingExtensionManager* pending_extension_manager() {
    267     return &pending_extension_manager_;
    268   }
    269 
    270   virtual const Extension* GetExtensionById(const std::string& id, bool) const {
    271     last_inquired_extension_id_ = id;
    272     return NULL;
    273   }
    274 
    275   const std::string& extension_id() const { return extension_id_; }
    276   const FilePath& install_path() const { return install_path_; }
    277   const GURL& download_url() const { return download_url_; }
    278   const std::string& last_inquired_extension_id() const {
    279     return last_inquired_extension_id_;
    280   }
    281 
    282  private:
    283   std::string extension_id_;
    284   FilePath install_path_;
    285   GURL download_url_;
    286 
    287   // The last extension ID that GetExtensionById was called with.
    288   // Mutable because the method that sets it (GetExtensionById) is const
    289   // in the actual extension service, but must record the last extension
    290   // ID in this test class.
    291   mutable std::string last_inquired_extension_id_;
    292 };
    293 
    294 class ServiceForBlacklistTests : public MockService {
    295  public:
    296   ServiceForBlacklistTests()
    297      : MockService(),
    298        processed_blacklist_(false) {
    299   }
    300   virtual void UpdateExtensionBlacklist(
    301     const std::vector<std::string>& blacklist) {
    302     processed_blacklist_ = true;
    303     return;
    304   }
    305   bool processed_blacklist() { return processed_blacklist_; }
    306   const std::string& extension_id() { return extension_id_; }
    307 
    308  private:
    309   bool processed_blacklist_;
    310   std::string extension_id_;
    311   FilePath install_path_;
    312 };
    313 
    314 static const int kUpdateFrequencySecs = 15;
    315 
    316 // Takes a string with KEY=VALUE parameters separated by '&' in |params| and
    317 // puts the key/value pairs into |result|. For keys with no value, the empty
    318 // string is used. So for "a=1&b=foo&c", result would map "a" to "1", "b" to
    319 // "foo", and "c" to "".
    320 static void ExtractParameters(const std::string& params,
    321                               std::map<std::string, std::string>* result) {
    322   std::vector<std::string> pairs;
    323   base::SplitString(params, '&', &pairs);
    324   for (size_t i = 0; i < pairs.size(); i++) {
    325     std::vector<std::string> key_val;
    326     base::SplitString(pairs[i], '=', &key_val);
    327     if (!key_val.empty()) {
    328       std::string key = key_val[0];
    329       EXPECT_TRUE(result->find(key) == result->end());
    330       (*result)[key] = (key_val.size() == 2) ? key_val[1] : "";
    331     } else {
    332       NOTREACHED();
    333     }
    334   }
    335 }
    336 
    337 // All of our tests that need to use private APIs of ExtensionUpdater live
    338 // inside this class (which is a friend to ExtensionUpdater).
    339 class ExtensionUpdaterTest : public testing::Test {
    340  public:
    341   static void SimulateTimerFired(ExtensionUpdater* updater) {
    342     EXPECT_TRUE(updater->timer_.IsRunning());
    343     updater->timer_.Stop();
    344     updater->TimerFired();
    345   }
    346 
    347   static void SimulateCheckSoon(const ExtensionUpdater& updater,
    348                                 MessageLoop* message_loop) {
    349     EXPECT_TRUE(updater.will_check_soon_);
    350     message_loop->RunAllPending();
    351   }
    352 
    353   // Adds a Result with the given data to results.
    354   static void AddParseResult(
    355       const std::string& id,
    356       const std::string& version,
    357       const std::string& url,
    358       UpdateManifest::Results* results) {
    359     UpdateManifest::Result result;
    360     result.extension_id = id;
    361     result.version = version;
    362     result.crx_url = GURL(url);
    363     results->list.push_back(result);
    364   }
    365 
    366   static void TestExtensionUpdateCheckRequests(bool pending) {
    367     MessageLoop message_loop;
    368     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
    369     BrowserThread file_thread(BrowserThread::FILE, &message_loop);
    370     BrowserThread io_thread(BrowserThread::IO);
    371     io_thread.Start();
    372 
    373     // Create an extension with an update_url.
    374     ServiceForManifestTests service;
    375     std::string update_url("http://foo.com/bar");
    376     ExtensionList extensions;
    377     PendingExtensionManager* pending_extension_manager =
    378         service.pending_extension_manager();
    379     if (pending) {
    380       SetupPendingExtensionManagerForTest(1, GURL(update_url),
    381                                           pending_extension_manager);
    382     } else {
    383       service.CreateTestExtensions(1, 1, &extensions, &update_url,
    384                                    Extension::INTERNAL);
    385       service.set_extensions(extensions);
    386     }
    387 
    388     // Set up and start the updater.
    389     TestURLFetcherFactory factory;
    390     URLFetcher::set_factory(&factory);
    391     ExtensionUpdater updater(
    392         &service, service.extension_prefs(), service.pref_service(),
    393         service.profile(), 60*60*24);
    394     updater.Start();
    395     // Disable blacklist checks (tested elsewhere) so that we only see the
    396     // update HTTP request.
    397     updater.set_blacklist_checks_enabled(false);
    398 
    399     // Tell the update that it's time to do update checks.
    400     SimulateTimerFired(&updater);
    401 
    402     // Get the url our mock fetcher was asked to fetch.
    403     TestURLFetcher* fetcher =
    404         factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId);
    405     const GURL& url = fetcher->original_url();
    406     EXPECT_FALSE(url.is_empty());
    407     EXPECT_TRUE(url.is_valid());
    408     EXPECT_TRUE(url.SchemeIs("http"));
    409     EXPECT_EQ("foo.com", url.host());
    410     EXPECT_EQ("/bar", url.path());
    411 
    412     // Validate the extension request parameters in the query. It should
    413     // look something like "?x=id%3D<id>%26v%3D<version>%26uc".
    414     EXPECT_TRUE(url.has_query());
    415     std::vector<std::string> parts;
    416     base::SplitString(url.query(), '=', &parts);
    417     EXPECT_EQ(2u, parts.size());
    418     EXPECT_EQ("x", parts[0]);
    419     std::string decoded = UnescapeURLComponent(parts[1],
    420                                                UnescapeRule::URL_SPECIAL_CHARS);
    421     std::map<std::string, std::string> params;
    422     ExtractParameters(decoded, &params);
    423     if (pending) {
    424       EXPECT_EQ(pending_extension_manager->begin()->first, params["id"]);
    425       EXPECT_EQ("0.0.0.0", params["v"]);
    426     } else {
    427       EXPECT_EQ(extensions[0]->id(), params["id"]);
    428       EXPECT_EQ(extensions[0]->VersionString(), params["v"]);
    429     }
    430     EXPECT_EQ("", params["uc"]);
    431   }
    432 
    433   static void TestBlacklistUpdateCheckRequests() {
    434     ServiceForManifestTests service;
    435 
    436     // Setup and start the updater.
    437     MessageLoop message_loop;
    438     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
    439     BrowserThread io_thread(BrowserThread::IO);
    440     io_thread.Start();
    441 
    442     TestURLFetcherFactory factory;
    443     URLFetcher::set_factory(&factory);
    444     ExtensionUpdater updater(
    445         &service, service.extension_prefs(), service.pref_service(),
    446         service.profile(), 60*60*24);
    447     updater.Start();
    448 
    449     // Tell the updater that it's time to do update checks.
    450     SimulateTimerFired(&updater);
    451 
    452     // Get the url our mock fetcher was asked to fetch.
    453     TestURLFetcher* fetcher =
    454         factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId);
    455     ASSERT_FALSE(fetcher == NULL);
    456     const GURL& url = fetcher->original_url();
    457 
    458     EXPECT_FALSE(url.is_empty());
    459     EXPECT_TRUE(url.is_valid());
    460     EXPECT_TRUE(url.SchemeIs("https"));
    461     EXPECT_EQ("clients2.google.com", url.host());
    462     EXPECT_EQ("/service/update2/crx", url.path());
    463 
    464     // Validate the extension request parameters in the query. It should
    465     // look something like "?x=id%3D<id>%26v%3D<version>%26uc".
    466     EXPECT_TRUE(url.has_query());
    467     std::vector<std::string> parts;
    468     base::SplitString(url.query(), '=', &parts);
    469     EXPECT_EQ(2u, parts.size());
    470     EXPECT_EQ("x", parts[0]);
    471     std::string decoded = UnescapeURLComponent(parts[1],
    472                                                UnescapeRule::URL_SPECIAL_CHARS);
    473     std::map<std::string, std::string> params;
    474     ExtractParameters(decoded, &params);
    475     EXPECT_EQ("com.google.crx.blacklist", params["id"]);
    476     EXPECT_EQ("0", params["v"]);
    477     EXPECT_EQ("", params["uc"]);
    478     EXPECT_TRUE(ContainsKey(params, "ping"));
    479   }
    480 
    481   static void TestUpdateUrlDataEmpty() {
    482     const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    483     const std::string version = "1.0";
    484 
    485     // Make sure that an empty update URL data string does not cause a ap=
    486     // option to appear in the x= parameter.
    487     ManifestFetchData fetch_data(GURL("http://localhost/foo"));
    488     fetch_data.AddExtension(id, version,
    489                             kNeverPingedData, "");
    490     EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    491               "%26v%3D1.0%26uc",
    492               fetch_data.full_url().spec());
    493   }
    494 
    495   static void TestUpdateUrlDataSimple() {
    496     const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    497     const std::string version = "1.0";
    498 
    499     // Make sure that an update URL data string causes an appropriate ap=
    500     // option to appear in the x= parameter.
    501     ManifestFetchData fetch_data(GURL("http://localhost/foo"));
    502     fetch_data.AddExtension(id, version,
    503                             kNeverPingedData, "bar");
    504     EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    505               "%26v%3D1.0%26uc%26ap%3Dbar",
    506               fetch_data.full_url().spec());
    507   }
    508 
    509   static void TestUpdateUrlDataCompound() {
    510     const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    511     const std::string version = "1.0";
    512 
    513     // Make sure that an update URL data string causes an appropriate ap=
    514     // option to appear in the x= parameter.
    515     ManifestFetchData fetch_data(GURL("http://localhost/foo"));
    516     fetch_data.AddExtension(id, version,
    517                             kNeverPingedData, "a=1&b=2&c");
    518     EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    519               "%26v%3D1.0%26uc%26ap%3Da%253D1%2526b%253D2%2526c",
    520               fetch_data.full_url().spec());
    521   }
    522 
    523   static void TestUpdateUrlDataFromGallery(const std::string& gallery_url) {
    524     MockService service;
    525     ManifestFetchesBuilder builder(&service, service.extension_prefs());
    526     ExtensionList extensions;
    527     std::string url(gallery_url);
    528 
    529     service.CreateTestExtensions(1, 1, &extensions, &url, Extension::INTERNAL);
    530     builder.AddExtension(*extensions[0]);
    531     std::vector<ManifestFetchData*> fetches = builder.GetFetches();
    532     EXPECT_EQ(1u, fetches.size());
    533     scoped_ptr<ManifestFetchData> fetch(fetches[0]);
    534     fetches.clear();
    535 
    536     // Make sure that extensions that update from the gallery ignore any
    537     // update URL data.
    538     const std::string& update_url = fetch->full_url().spec();
    539     std::string::size_type x = update_url.find("x=");
    540     EXPECT_NE(std::string::npos, x);
    541     std::string::size_type ap = update_url.find("ap%3D", x);
    542     EXPECT_EQ(std::string::npos, ap);
    543   }
    544 
    545   static void TestDetermineUpdates() {
    546     MessageLoop message_loop;
    547     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
    548     BrowserThread file_thread(BrowserThread::FILE, &message_loop);
    549 
    550     // Create a set of test extensions
    551     ServiceForManifestTests service;
    552     ExtensionList tmp;
    553     service.CreateTestExtensions(1, 3, &tmp, NULL, Extension::INTERNAL);
    554     service.set_extensions(tmp);
    555 
    556     ExtensionUpdater updater(
    557         &service, service.extension_prefs(), service.pref_service(),
    558         service.profile(), kUpdateFrequencySecs);
    559     updater.Start();
    560 
    561     // Check passing an empty list of parse results to DetermineUpdates
    562     ManifestFetchData fetch_data(GURL("http://localhost/foo"));
    563     UpdateManifest::Results updates;
    564     std::vector<int> updateable = updater.DetermineUpdates(fetch_data,
    565                                                            updates);
    566     EXPECT_TRUE(updateable.empty());
    567 
    568     // Create two updates - expect that DetermineUpdates will return the first
    569     // one (v1.0 installed, v1.1 available) but not the second one (both
    570     // installed and available at v2.0).
    571     scoped_ptr<Version> one(Version::GetVersionFromString("1.0"));
    572     EXPECT_TRUE(tmp[0]->version()->Equals(*one));
    573     fetch_data.AddExtension(tmp[0]->id(), tmp[0]->VersionString(),
    574                             kNeverPingedData,
    575                             kEmptyUpdateUrlData);
    576     AddParseResult(tmp[0]->id(),
    577         "1.1", "http://localhost/e1_1.1.crx", &updates);
    578     fetch_data.AddExtension(tmp[1]->id(), tmp[1]->VersionString(),
    579                             kNeverPingedData,
    580                             kEmptyUpdateUrlData);
    581     AddParseResult(tmp[1]->id(),
    582         tmp[1]->VersionString(), "http://localhost/e2_2.0.crx", &updates);
    583     updateable = updater.DetermineUpdates(fetch_data, updates);
    584     EXPECT_EQ(1u, updateable.size());
    585     EXPECT_EQ(0, updateable[0]);
    586   }
    587 
    588   static void TestDetermineUpdatesPending() {
    589     // Create a set of test extensions
    590     ServiceForManifestTests service;
    591     PendingExtensionManager* pending_extension_manager =
    592         service.pending_extension_manager();
    593     SetupPendingExtensionManagerForTest(3, GURL(), pending_extension_manager);
    594 
    595     MessageLoop message_loop;
    596     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
    597     ExtensionUpdater updater(
    598         &service, service.extension_prefs(), service.pref_service(),
    599         service.profile(), kUpdateFrequencySecs);
    600     updater.Start();
    601 
    602     ManifestFetchData fetch_data(GURL("http://localhost/foo"));
    603     UpdateManifest::Results updates;
    604     PendingExtensionManager::const_iterator it;
    605     for (it = pending_extension_manager->begin();
    606          it != pending_extension_manager->end(); ++it) {
    607       fetch_data.AddExtension(it->first, "1.0.0.0",
    608                               kNeverPingedData,
    609                               kEmptyUpdateUrlData);
    610       AddParseResult(it->first,
    611                      "1.1", "http://localhost/e1_1.1.crx", &updates);
    612     }
    613     std::vector<int> updateable =
    614         updater.DetermineUpdates(fetch_data, updates);
    615     // All the apps should be updateable.
    616     EXPECT_EQ(3u, updateable.size());
    617     for (std::vector<int>::size_type i = 0; i < updateable.size(); ++i) {
    618       EXPECT_EQ(static_cast<int>(i), updateable[i]);
    619     }
    620   }
    621 
    622   static void TestMultipleManifestDownloading() {
    623     MessageLoop ui_loop;
    624     BrowserThread ui_thread(BrowserThread::UI, &ui_loop);
    625     BrowserThread file_thread(BrowserThread::FILE);
    626     file_thread.Start();
    627     BrowserThread io_thread(BrowserThread::IO);
    628     io_thread.Start();
    629 
    630     TestURLFetcherFactory factory;
    631     TestURLFetcher* fetcher = NULL;
    632     URLFetcher::set_factory(&factory);
    633     scoped_ptr<ServiceForDownloadTests> service(new ServiceForDownloadTests);
    634     ExtensionUpdater updater(service.get(), service->extension_prefs(),
    635                              service->pref_service(),
    636                              service->profile(),
    637                              kUpdateFrequencySecs);
    638     updater.Start();
    639 
    640     GURL url1("http://localhost/manifest1");
    641     GURL url2("http://localhost/manifest2");
    642 
    643     // Request 2 update checks - the first should begin immediately and the
    644     // second one should be queued up.
    645     ManifestFetchData* fetch1 = new ManifestFetchData(url1);
    646     ManifestFetchData* fetch2 = new ManifestFetchData(url2);
    647     ManifestFetchData::PingData zeroDays(0, 0);
    648     fetch1->AddExtension("1111", "1.0", zeroDays, kEmptyUpdateUrlData);
    649     fetch2->AddExtension("12345", "2.0", kNeverPingedData,
    650                          kEmptyUpdateUrlData);
    651     updater.StartUpdateCheck(fetch1);
    652     updater.StartUpdateCheck(fetch2);
    653 
    654     std::string invalid_xml = "invalid xml";
    655     fetcher = factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId);
    656     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    657     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
    658     fetcher->delegate()->OnURLFetchComplete(
    659         fetcher, url1, net::URLRequestStatus(), 200, ResponseCookies(),
    660         invalid_xml);
    661 
    662     // Now that the first request is complete, make sure the second one has
    663     // been started.
    664     const std::string kValidXml =
    665         "<?xml version='1.0' encoding='UTF-8'?>"
    666         "<gupdate xmlns='http://www.google.com/update2/response'"
    667         "                protocol='2.0'>"
    668         " <app appid='12345'>"
    669         "  <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'"
    670         "               version='1.2.3.4' prodversionmin='2.0.143.0' />"
    671         " </app>"
    672         "</gupdate>";
    673     fetcher = factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId);
    674     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    675     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
    676     fetcher->delegate()->OnURLFetchComplete(
    677         fetcher, url2, net::URLRequestStatus(), 200, ResponseCookies(),
    678         kValidXml);
    679 
    680     // This should run the manifest parsing, then we want to make sure that our
    681     // service was called with GetExtensionById with the matching id from
    682     // kValidXml.
    683     file_thread.Stop();
    684     io_thread.Stop();
    685     ui_loop.RunAllPending();
    686     EXPECT_EQ("12345", service->last_inquired_extension_id());
    687     xmlCleanupGlobals();
    688 
    689     // The FILE thread is needed for |service|'s cleanup,
    690     // because of ImportantFileWriter.
    691     file_thread.Start();
    692     service.reset();
    693   }
    694 
    695   static void TestSingleExtensionDownloading(bool pending) {
    696     MessageLoop ui_loop;
    697     BrowserThread ui_thread(BrowserThread::UI, &ui_loop);
    698     BrowserThread file_thread(BrowserThread::FILE);
    699     file_thread.Start();
    700     BrowserThread io_thread(BrowserThread::IO);
    701     io_thread.Start();
    702 
    703     TestURLFetcherFactory factory;
    704     TestURLFetcher* fetcher = NULL;
    705     URLFetcher::set_factory(&factory);
    706     scoped_ptr<ServiceForDownloadTests> service(new ServiceForDownloadTests);
    707     ExtensionUpdater updater(service.get(), service->extension_prefs(),
    708                              service->pref_service(),
    709                              service->profile(),
    710                              kUpdateFrequencySecs);
    711     updater.Start();
    712 
    713     GURL test_url("http://localhost/extension.crx");
    714 
    715     std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    716     std::string hash = "";
    717     scoped_ptr<Version> version(Version::GetVersionFromString("0.0.1"));
    718     ASSERT_TRUE(version.get());
    719     updater.FetchUpdatedExtension(id, test_url, hash, version->GetString());
    720 
    721     if (pending) {
    722       const bool kIsFromSync = true;
    723       const bool kInstallSilently = true;
    724       const Extension::State kInitialState = Extension::ENABLED;
    725       const bool kInitialIncognitoEnabled = false;
    726       PendingExtensionManager* pending_extension_manager =
    727           service->pending_extension_manager();
    728       pending_extension_manager->AddForTesting(
    729           id,
    730           PendingExtensionInfo(test_url, &ShouldAlwaysInstall, kIsFromSync,
    731                                kInstallSilently, kInitialState,
    732                                kInitialIncognitoEnabled, Extension::INTERNAL));
    733     }
    734 
    735     // Call back the ExtensionUpdater with a 200 response and some test data
    736     std::string extension_data("whatever");
    737     fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId);
    738     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    739     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
    740     fetcher->delegate()->OnURLFetchComplete(
    741         fetcher, test_url, net::URLRequestStatus(), 200, ResponseCookies(),
    742         extension_data);
    743 
    744     file_thread.Stop();
    745     ui_loop.RunAllPending();
    746 
    747     // Expect that ExtensionUpdater asked the mock extensions service to install
    748     // a file with the test data for the right id.
    749     EXPECT_EQ(id, service->extension_id());
    750     FilePath tmpfile_path = service->install_path();
    751     EXPECT_FALSE(tmpfile_path.empty());
    752     EXPECT_EQ(test_url, service->download_url());
    753     std::string file_contents;
    754     EXPECT_TRUE(file_util::ReadFileToString(tmpfile_path, &file_contents));
    755     EXPECT_TRUE(extension_data == file_contents);
    756 
    757     // The FILE thread is needed for |service|'s cleanup,
    758     // because of ImportantFileWriter.
    759     file_thread.Start();
    760     service.reset();
    761 
    762     file_util::Delete(tmpfile_path, false);
    763     URLFetcher::set_factory(NULL);
    764   }
    765 
    766   static void TestBlacklistDownloading() {
    767     MessageLoop message_loop;
    768     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
    769     BrowserThread file_thread(BrowserThread::FILE, &message_loop);
    770     BrowserThread io_thread(BrowserThread::IO);
    771     io_thread.Start();
    772 
    773     TestURLFetcherFactory factory;
    774     TestURLFetcher* fetcher = NULL;
    775     URLFetcher::set_factory(&factory);
    776     ServiceForBlacklistTests service;
    777     ExtensionUpdater updater(
    778         &service, service.extension_prefs(), service.pref_service(),
    779         service.profile(), kUpdateFrequencySecs);
    780     updater.Start();
    781     GURL test_url("http://localhost/extension.crx");
    782 
    783     std::string id = "com.google.crx.blacklist";
    784 
    785     std::string hash =
    786       "2CE109E9D0FAF820B2434E166297934E6177B65AB9951DBC3E204CAD4689B39C";
    787 
    788     std::string version = "0.0.1";
    789     updater.FetchUpdatedExtension(id, test_url, hash, version);
    790 
    791     // Call back the ExtensionUpdater with a 200 response and some test data
    792     std::string extension_data("aaabbb");
    793     fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId);
    794     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    795     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
    796     fetcher->delegate()->OnURLFetchComplete(
    797         fetcher, test_url, net::URLRequestStatus(), 200, ResponseCookies(),
    798         extension_data);
    799 
    800     message_loop.RunAllPending();
    801 
    802     // The updater should have called extension service to process the
    803     // blacklist.
    804     EXPECT_TRUE(service.processed_blacklist());
    805 
    806     EXPECT_EQ(version, service.pref_service()->
    807       GetString(prefs::kExtensionBlacklistUpdateVersion));
    808 
    809     URLFetcher::set_factory(NULL);
    810   }
    811 
    812   static void TestMultipleExtensionDownloading() {
    813     MessageLoopForUI message_loop;
    814     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
    815     BrowserThread file_thread(BrowserThread::FILE, &message_loop);
    816     BrowserThread io_thread(BrowserThread::IO);
    817     io_thread.Start();
    818 
    819     TestURLFetcherFactory factory;
    820     TestURLFetcher* fetcher = NULL;
    821     URLFetcher::set_factory(&factory);
    822     ServiceForDownloadTests service;
    823     ExtensionUpdater updater(
    824         &service, service.extension_prefs(), service.pref_service(),
    825         service.profile(), kUpdateFrequencySecs);
    826     updater.Start();
    827 
    828     GURL url1("http://localhost/extension1.crx");
    829     GURL url2("http://localhost/extension2.crx");
    830 
    831     std::string id1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    832     std::string id2 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
    833 
    834     std::string hash1 = "";
    835     std::string hash2 = "";
    836 
    837     std::string version1 = "0.1";
    838     std::string version2 = "0.1";
    839     // Start two fetches
    840     updater.FetchUpdatedExtension(id1, url1, hash1, version1);
    841     updater.FetchUpdatedExtension(id2, url2, hash2, version2);
    842 
    843     // Make the first fetch complete.
    844     std::string extension_data1("whatever");
    845     fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId);
    846     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    847     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
    848     fetcher->delegate()->OnURLFetchComplete(
    849         fetcher, url1, net::URLRequestStatus(), 200, ResponseCookies(),
    850         extension_data1);
    851     message_loop.RunAllPending();
    852 
    853     // Expect that the service was asked to do an install with the right data.
    854     FilePath tmpfile_path = service.install_path();
    855     EXPECT_FALSE(tmpfile_path.empty());
    856     EXPECT_EQ(id1, service.extension_id());
    857     EXPECT_EQ(url1, service.download_url());
    858     message_loop.RunAllPending();
    859     file_util::Delete(tmpfile_path, false);
    860 
    861     // Make sure the second fetch finished and asked the service to do an
    862     // update.
    863     std::string extension_data2("whatever2");
    864     fetcher = factory.GetFetcherByID(ExtensionUpdater::kExtensionFetcherId);
    865     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    866     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
    867     fetcher->delegate()->OnURLFetchComplete(
    868         fetcher, url2, net::URLRequestStatus(), 200, ResponseCookies(),
    869         extension_data2);
    870     message_loop.RunAllPending();
    871     EXPECT_EQ(id2, service.extension_id());
    872     EXPECT_EQ(url2, service.download_url());
    873     EXPECT_FALSE(service.install_path().empty());
    874 
    875     // Make sure the correct crx contents were passed for the update call.
    876     std::string file_contents;
    877     EXPECT_TRUE(file_util::ReadFileToString(service.install_path(),
    878                                             &file_contents));
    879     EXPECT_TRUE(extension_data2 == file_contents);
    880     file_util::Delete(service.install_path(), false);
    881   }
    882 
    883   // Test requests to both a Google server and a non-google server. This allows
    884   // us to test various combinations of installed (ie roll call) and active
    885   // (ie app launch) ping scenarios. The invariant is that each type of ping
    886   // value should be present at most once per day, and can be calculated based
    887   // on the delta between now and the last ping time (or in the case of active
    888   // pings, that delta plus whether the app has been active).
    889   static void TestGalleryRequests(int rollcall_ping_days,
    890                                   int active_ping_days,
    891                                   bool active_bit) {
    892     MessageLoop message_loop;
    893     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
    894     BrowserThread file_thread(BrowserThread::FILE, &message_loop);
    895 
    896     TestURLFetcherFactory factory;
    897     URLFetcher::set_factory(&factory);
    898 
    899     // Set up 2 mock extensions, one with a google.com update url and one
    900     // without.
    901     ServiceForManifestTests service;
    902     ExtensionList tmp;
    903     GURL url1("http://clients2.google.com/service/update2/crx");
    904     GURL url2("http://www.somewebsite.com");
    905     service.CreateTestExtensions(1, 1, &tmp, &url1.possibly_invalid_spec(),
    906                                  Extension::INTERNAL);
    907     service.CreateTestExtensions(2, 1, &tmp, &url2.possibly_invalid_spec(),
    908                                  Extension::INTERNAL);
    909     EXPECT_EQ(2u, tmp.size());
    910     service.set_extensions(tmp);
    911 
    912     ExtensionPrefs* prefs = service.extension_prefs();
    913     const std::string& id = tmp[0]->id();
    914     Time now = Time::Now();
    915     if (rollcall_ping_days == 0) {
    916       prefs->SetLastPingDay(id, now - TimeDelta::FromSeconds(15));
    917     } else if (rollcall_ping_days > 0) {
    918       Time last_ping_day = now -
    919                            TimeDelta::FromDays(rollcall_ping_days) -
    920                            TimeDelta::FromSeconds(15);
    921       prefs->SetLastPingDay(id, last_ping_day);
    922     }
    923 
    924     // Store a value for the last day we sent an active ping.
    925     if (active_ping_days == 0) {
    926       prefs->SetLastActivePingDay(id, now - TimeDelta::FromSeconds(15));
    927     } else if (active_ping_days > 0) {
    928       Time last_active_ping_day = now -
    929                                   TimeDelta::FromDays(active_ping_days) -
    930                                   TimeDelta::FromSeconds(15);
    931       prefs->SetLastActivePingDay(id, last_active_ping_day);
    932     }
    933     if (active_bit)
    934       prefs->SetActiveBit(id, true);
    935 
    936     ExtensionUpdater updater(
    937         &service, service.extension_prefs(), service.pref_service(),
    938         service.profile(), kUpdateFrequencySecs);
    939     updater.Start();
    940     updater.set_blacklist_checks_enabled(false);
    941 
    942     // Make the updater do manifest fetching, and note the urls it tries to
    943     // fetch.
    944     std::vector<GURL> fetched_urls;
    945     updater.CheckNow();
    946     TestURLFetcher* fetcher =
    947       factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId);
    948     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
    949     fetched_urls.push_back(fetcher->original_url());
    950     fetcher->delegate()->OnURLFetchComplete(
    951       fetcher, fetched_urls[0], net::URLRequestStatus(), 500,
    952       ResponseCookies(), "");
    953     fetcher =
    954       factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId);
    955     fetched_urls.push_back(fetcher->original_url());
    956 
    957     // The urls could have been fetched in either order, so use the host to
    958     // tell them apart and note the query each used.
    959     std::string url1_query;
    960     std::string url2_query;
    961     if (fetched_urls[0].host() == url1.host()) {
    962       url1_query = fetched_urls[0].query();
    963       url2_query = fetched_urls[1].query();
    964     } else if (fetched_urls[0].host() == url2.host()) {
    965       url1_query = fetched_urls[1].query();
    966       url2_query = fetched_urls[0].query();
    967     } else {
    968       NOTREACHED();
    969     }
    970 
    971     // First make sure the non-google query had no ping parameter.
    972     std::string search_string = "ping%3D";
    973     EXPECT_TRUE(url2_query.find(search_string) == std::string::npos);
    974 
    975     // Now make sure the google query had the correct ping parameter.
    976     bool ping_expected = false;
    977     bool did_rollcall = false;
    978     if (rollcall_ping_days != 0) {
    979       search_string += "r%253D" + base::IntToString(rollcall_ping_days);
    980       did_rollcall = true;
    981       ping_expected = true;
    982     }
    983     if (active_bit && active_ping_days != 0) {
    984       if (did_rollcall)
    985         search_string += "%2526";
    986       search_string += "a%253D" + base::IntToString(active_ping_days);
    987       ping_expected = true;
    988     }
    989     bool ping_found = url1_query.find(search_string) != std::string::npos;
    990     EXPECT_EQ(ping_expected, ping_found) << "query was: " << url1_query
    991         << " was looking for " << search_string;
    992   }
    993 
    994   // This makes sure that the extension updater properly stores the results
    995   // of a <daystart> tag from a manifest fetch in one of two cases: 1) This is
    996   // the first time we fetched the extension, or 2) We sent a ping value of
    997   // >= 1 day for the extension.
    998   static void TestHandleManifestResults() {
    999     ServiceForManifestTests service;
   1000     MessageLoop message_loop;
   1001     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
   1002     ExtensionUpdater updater(
   1003         &service, service.extension_prefs(), service.pref_service(),
   1004         service.profile(), kUpdateFrequencySecs);
   1005     updater.Start();
   1006 
   1007     GURL update_url("http://www.google.com/manifest");
   1008     ExtensionList tmp;
   1009     service.CreateTestExtensions(1, 1, &tmp, &update_url.spec(),
   1010                                  Extension::INTERNAL);
   1011     service.set_extensions(tmp);
   1012 
   1013     ManifestFetchData fetch_data(update_url);
   1014     const Extension* extension = tmp[0];
   1015     fetch_data.AddExtension(extension->id(), extension->VersionString(),
   1016                             kNeverPingedData,
   1017                             kEmptyUpdateUrlData);
   1018     UpdateManifest::Results results;
   1019     results.daystart_elapsed_seconds = 750;
   1020 
   1021     updater.HandleManifestResults(fetch_data, &results);
   1022     Time last_ping_day =
   1023         service.extension_prefs()->LastPingDay(extension->id());
   1024     EXPECT_FALSE(last_ping_day.is_null());
   1025     int64 seconds_diff = (Time::Now() - last_ping_day).InSeconds();
   1026     EXPECT_LT(seconds_diff - results.daystart_elapsed_seconds, 5);
   1027   }
   1028 };
   1029 
   1030 // Because we test some private methods of ExtensionUpdater, it's easer for the
   1031 // actual test code to live in ExtenionUpdaterTest methods instead of TEST_F
   1032 // subclasses where friendship with ExtenionUpdater is not inherited.
   1033 
   1034 TEST(ExtensionUpdaterTest, TestExtensionUpdateCheckRequests) {
   1035   ExtensionUpdaterTest::TestExtensionUpdateCheckRequests(false);
   1036 }
   1037 
   1038 TEST(ExtensionUpdaterTest, TestExtensionUpdateCheckRequestsPending) {
   1039   ExtensionUpdaterTest::TestExtensionUpdateCheckRequests(true);
   1040 }
   1041 
   1042 // This test is disabled on Mac, see http://crbug.com/26035.
   1043 TEST(ExtensionUpdaterTest, TestBlacklistUpdateCheckRequests) {
   1044   ExtensionUpdaterTest::TestBlacklistUpdateCheckRequests();
   1045 }
   1046 
   1047 TEST(ExtensionUpdaterTest, TestUpdateUrlData) {
   1048   MessageLoop message_loop;
   1049   BrowserThread file_thread(BrowserThread::FILE, &message_loop);
   1050 
   1051   ExtensionUpdaterTest::TestUpdateUrlDataEmpty();
   1052   ExtensionUpdaterTest::TestUpdateUrlDataSimple();
   1053   ExtensionUpdaterTest::TestUpdateUrlDataCompound();
   1054   ExtensionUpdaterTest::TestUpdateUrlDataFromGallery(
   1055       Extension::GalleryUpdateUrl(false).spec());
   1056   ExtensionUpdaterTest::TestUpdateUrlDataFromGallery(
   1057       Extension::GalleryUpdateUrl(true).spec());
   1058 }
   1059 
   1060 TEST(ExtensionUpdaterTest, TestDetermineUpdates) {
   1061   ExtensionUpdaterTest::TestDetermineUpdates();
   1062 }
   1063 
   1064 TEST(ExtensionUpdaterTest, TestDetermineUpdatesPending) {
   1065   ExtensionUpdaterTest::TestDetermineUpdatesPending();
   1066 }
   1067 
   1068 TEST(ExtensionUpdaterTest, TestMultipleManifestDownloading) {
   1069   ExtensionUpdaterTest::TestMultipleManifestDownloading();
   1070 }
   1071 
   1072 TEST(ExtensionUpdaterTest, TestSingleExtensionDownloading) {
   1073   ExtensionUpdaterTest::TestSingleExtensionDownloading(false);
   1074 }
   1075 
   1076 TEST(ExtensionUpdaterTest, TestSingleExtensionDownloadingPending) {
   1077   ExtensionUpdaterTest::TestSingleExtensionDownloading(true);
   1078 }
   1079 
   1080 // This test is disabled on Mac, see http://crbug.com/26035.
   1081 TEST(ExtensionUpdaterTest, TestBlacklistDownloading) {
   1082   ExtensionUpdaterTest::TestBlacklistDownloading();
   1083 }
   1084 
   1085 TEST(ExtensionUpdaterTest, TestMultipleExtensionDownloading) {
   1086   ExtensionUpdaterTest::TestMultipleExtensionDownloading();
   1087 }
   1088 
   1089 TEST(ExtensionUpdaterTest, TestGalleryRequests) {
   1090   // We want to test a variety of combinations of expected ping conditions for
   1091   // rollcall and active pings.
   1092   int ping_cases[] = { ManifestFetchData::kNeverPinged, 0, 1, 5 };
   1093 
   1094   for (size_t i = 0; i < arraysize(ping_cases); i++) {
   1095     for (size_t j = 0; j < arraysize(ping_cases); j++) {
   1096       for (size_t k = 0; k < 2; k++) {
   1097         int rollcall_ping_days = ping_cases[i];
   1098         int active_ping_days = ping_cases[j];
   1099         // Skip cases where rollcall_ping_days == -1, but active_ping_days > 0,
   1100         // because rollcall_ping_days == -1 means the app was just installed and
   1101         // this is the first update check after installation.
   1102         if (rollcall_ping_days == ManifestFetchData::kNeverPinged &&
   1103             active_ping_days > 0)
   1104           continue;
   1105 
   1106         bool active_bit = k > 0;
   1107         ExtensionUpdaterTest::TestGalleryRequests(
   1108             rollcall_ping_days, active_ping_days, active_bit);
   1109         ASSERT_FALSE(HasFailure()) <<
   1110           " rollcall_ping_days=" << ping_cases[i] <<
   1111           " active_ping_days=" << ping_cases[j] <<
   1112           " active_bit=" << active_bit;
   1113       }
   1114     }
   1115   }
   1116 }
   1117 
   1118 TEST(ExtensionUpdaterTest, TestHandleManifestResults) {
   1119   ExtensionUpdaterTest::TestHandleManifestResults();
   1120 }
   1121 
   1122 TEST(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) {
   1123   MessageLoop message_loop;
   1124   BrowserThread file_thread(BrowserThread::FILE, &message_loop);
   1125 
   1126   MockService service;
   1127   ManifestFetchesBuilder builder(&service, service.extension_prefs());
   1128 
   1129   // Non-internal non-external extensions should be rejected.
   1130   {
   1131     ExtensionList extensions;
   1132     service.CreateTestExtensions(1, 1, &extensions, NULL, Extension::INVALID);
   1133     ASSERT_FALSE(extensions.empty());
   1134     builder.AddExtension(*extensions[0]);
   1135     EXPECT_TRUE(builder.GetFetches().empty());
   1136   }
   1137 
   1138   // Extensions with invalid update URLs should be rejected.
   1139   builder.AddPendingExtension(
   1140       GenerateId("foo"), PendingExtensionInfo(GURL("http:google.com:foo"),
   1141                                               &ShouldInstallExtensionsOnly,
   1142                                               false, false, true, false,
   1143                                               Extension::INTERNAL));
   1144   EXPECT_TRUE(builder.GetFetches().empty());
   1145 
   1146   // Extensions with empty IDs should be rejected.
   1147   builder.AddPendingExtension(
   1148       "", PendingExtensionInfo(GURL(), &ShouldInstallExtensionsOnly,
   1149                                false, false, true, false,
   1150                                Extension::INTERNAL));
   1151   EXPECT_TRUE(builder.GetFetches().empty());
   1152 
   1153   // TODO(akalin): Test that extensions with empty update URLs
   1154   // converted from user scripts are rejected.
   1155 
   1156   // Extensions with empty update URLs should have a default one
   1157   // filled in.
   1158   builder.AddPendingExtension(
   1159       GenerateId("foo"), PendingExtensionInfo(GURL(),
   1160                                               &ShouldInstallExtensionsOnly,
   1161                                               false, false, true, false,
   1162                                               Extension::INTERNAL));
   1163   std::vector<ManifestFetchData*> fetches = builder.GetFetches();
   1164   ASSERT_EQ(1u, fetches.size());
   1165   scoped_ptr<ManifestFetchData> fetch(fetches[0]);
   1166   fetches.clear();
   1167   EXPECT_FALSE(fetch->base_url().is_empty());
   1168   EXPECT_FALSE(fetch->full_url().is_empty());
   1169 }
   1170 
   1171 TEST(ExtensionUpdaterTest, TestStartUpdateCheckMemory) {
   1172     MessageLoop message_loop;
   1173     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
   1174     BrowserThread file_thread(BrowserThread::FILE, &message_loop);
   1175 
   1176     ServiceForManifestTests service;
   1177     TestURLFetcherFactory factory;
   1178     URLFetcher::set_factory(&factory);
   1179     ExtensionUpdater updater(
   1180         &service, service.extension_prefs(), service.pref_service(),
   1181         service.profile(), kUpdateFrequencySecs);
   1182     updater.Start();
   1183     updater.StartUpdateCheck(new ManifestFetchData(GURL()));
   1184     // This should delete the newly-created ManifestFetchData.
   1185     updater.StartUpdateCheck(new ManifestFetchData(GURL()));
   1186     // This should add into |manifests_pending_|.
   1187     updater.StartUpdateCheck(new ManifestFetchData(
   1188         GURL("http://www.google.com")));
   1189     // This should clear out |manifests_pending_|.
   1190     updater.Stop();
   1191 }
   1192 
   1193 TEST(ExtensionUpdaterTest, TestCheckSoon) {
   1194     MessageLoop message_loop;
   1195     BrowserThread ui_thread(BrowserThread::UI, &message_loop);
   1196     BrowserThread file_thread(BrowserThread::FILE, &message_loop);
   1197 
   1198     ServiceForManifestTests service;
   1199     TestURLFetcherFactory factory;
   1200     URLFetcher::set_factory(&factory);
   1201     ExtensionUpdater updater(
   1202         &service, service.extension_prefs(), service.pref_service(),
   1203         service.profile(), kUpdateFrequencySecs);
   1204     EXPECT_FALSE(updater.WillCheckSoon());
   1205     updater.Start();
   1206     EXPECT_FALSE(updater.WillCheckSoon());
   1207     updater.CheckSoon();
   1208     EXPECT_TRUE(updater.WillCheckSoon());
   1209     updater.CheckSoon();
   1210     EXPECT_TRUE(updater.WillCheckSoon());
   1211     ExtensionUpdaterTest::SimulateCheckSoon(updater, &message_loop);
   1212     EXPECT_FALSE(updater.WillCheckSoon());
   1213     updater.CheckSoon();
   1214     EXPECT_TRUE(updater.WillCheckSoon());
   1215     updater.Stop();
   1216     EXPECT_FALSE(updater.WillCheckSoon());
   1217 }
   1218 
   1219 // TODO(asargent) - (http://crbug.com/12780) add tests for:
   1220 // -prodversionmin (shouldn't update if browser version too old)
   1221 // -manifests & updates arriving out of order / interleaved
   1222 // -malformed update url (empty, file://, has query, has a # fragment, etc.)
   1223 // -An extension gets uninstalled while updates are in progress (so it doesn't
   1224 //  "come back from the dead")
   1225 // -An extension gets manually updated to v3 while we're downloading v2 (ie
   1226 //  you don't get downgraded accidentally)
   1227 // -An update manifest mentions multiple updates
   1228