• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MockService()53   MockService()
54       : pending_extension_manager_(ALLOW_THIS_IN_INITIALIZER_LIST(*this)) {}
~MockService()55   virtual ~MockService() {}
56 
extensions() const57   virtual const ExtensionList* extensions() const {
58     ADD_FAILURE();
59     return NULL;
60   }
61 
disabled_extensions() const62   virtual const ExtensionList* disabled_extensions() const {
63     ADD_FAILURE();
64     return NULL;
65   }
66 
UpdateExtension(const std::string & id,const FilePath & path,const GURL & download_url)67   virtual void UpdateExtension(const std::string& id,
68                                const FilePath& path,
69                                const GURL& download_url) {
70     FAIL();
71   }
72 
GetExtensionById(const std::string & id,bool include_disabled) const73   virtual const Extension* GetExtensionById(const std::string& id,
74                                             bool include_disabled) const {
75     ADD_FAILURE();
76     return NULL;
77   }
78 
UninstallExtension(const std::string & extension_id,bool external_uninstall,std::string * error)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 
IsExtensionEnabled(const std::string & extension_id) const86   virtual bool IsExtensionEnabled(const std::string& extension_id) const {
87     ADD_FAILURE();
88     return false;
89   }
90 
IsExternalExtensionUninstalled(const std::string & extension_id) const91   virtual bool IsExternalExtensionUninstalled(
92       const std::string& extension_id) const {
93     ADD_FAILURE();
94     return false;
95   }
96 
EnableExtension(const std::string & extension_id)97   virtual void EnableExtension(const std::string& extension_id) {
98     FAIL();
99   }
100 
DisableExtension(const std::string & extension_id)101   virtual void DisableExtension(const std::string& extension_id) {
102     FAIL();
103   }
104 
105 
UpdateExtensionBlacklist(const std::vector<std::string> & blacklist)106   virtual void UpdateExtensionBlacklist(
107       const std::vector<std::string>& blacklist) {
108     FAIL();
109   }
110 
CheckAdminBlacklist()111   virtual void CheckAdminBlacklist() {
112     FAIL();
113   }
114 
IsIncognitoEnabled(const std::string & id) const115   virtual bool IsIncognitoEnabled(const std::string& id) const {
116     ADD_FAILURE();
117     return false;
118   }
119 
SetIsIncognitoEnabled(const std::string & id,bool enabled)120   virtual void SetIsIncognitoEnabled(const std::string& id,
121                                      bool enabled) {
122     FAIL();
123   }
124 
CheckForUpdatesSoon()125   virtual void CheckForUpdatesSoon() {
126     FAIL();
127   }
128 
pending_extension_manager()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 
ProcessSyncData(const ExtensionSyncData & extension_sync_data,PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install)135   virtual void ProcessSyncData(
136       const ExtensionSyncData& extension_sync_data,
137       PendingExtensionInfo::ShouldAllowInstallPredicate
138           should_allow_install) {
139     FAIL();
140   }
141 
profile()142   Profile* profile() { return &profile_; }
143 
extension_prefs()144   ExtensionPrefs* extension_prefs() { return prefs_.prefs(); }
145 
pref_service()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.
CreateTestExtensions(int id,int count,ExtensionList * list,const std::string * update_url,Extension::Location location)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 
GenerateId(std::string input)181 std::string GenerateId(std::string input) {
182   std::string result;
183   EXPECT_TRUE(Extension::GenerateId(input, &result));
184   return result;
185 }
186 
ShouldInstallExtensionsOnly(const Extension & extension)187 bool ShouldInstallExtensionsOnly(const Extension& extension) {
188   return extension.GetType() == Extension::TYPE_EXTENSION;
189 }
190 
ShouldInstallThemesOnly(const Extension & extension)191 bool ShouldInstallThemesOnly(const Extension& extension) {
192   return extension.is_theme();
193 }
194 
ShouldAlwaysInstall(const Extension & extension)195 bool ShouldAlwaysInstall(const Extension& extension) {
196   return true;
197 }
198 
199 // Loads some pending extension records into a pending extension manager.
SetupPendingExtensionManagerForTest(int count,const GURL & update_url,PendingExtensionManager * 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:
ServiceForManifestTests()227   ServiceForManifestTests() {}
228 
~ServiceForManifestTests()229   virtual ~ServiceForManifestTests() {}
230 
GetExtensionById(const std::string & id,bool include_disabled) const231   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 
extensions() const242   virtual const ExtensionList* extensions() const { return &extensions_; }
243 
pending_extension_manager()244   virtual PendingExtensionManager* pending_extension_manager() {
245     return &pending_extension_manager_;
246   }
247 
set_extensions(ExtensionList extensions)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:
UpdateExtension(const std::string & id,const FilePath & extension_path,const GURL & download_url)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 
pending_extension_manager()266   virtual PendingExtensionManager* pending_extension_manager() {
267     return &pending_extension_manager_;
268   }
269 
GetExtensionById(const std::string & id,bool) const270   virtual const Extension* GetExtensionById(const std::string& id, bool) const {
271     last_inquired_extension_id_ = id;
272     return NULL;
273   }
274 
extension_id() const275   const std::string& extension_id() const { return extension_id_; }
install_path() const276   const FilePath& install_path() const { return install_path_; }
download_url() const277   const GURL& download_url() const { return download_url_; }
last_inquired_extension_id() const278   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:
ServiceForBlacklistTests()296   ServiceForBlacklistTests()
297      : MockService(),
298        processed_blacklist_(false) {
299   }
UpdateExtensionBlacklist(const std::vector<std::string> & blacklist)300   virtual void UpdateExtensionBlacklist(
301     const std::vector<std::string>& blacklist) {
302     processed_blacklist_ = true;
303     return;
304   }
processed_blacklist()305   bool processed_blacklist() { return processed_blacklist_; }
extension_id()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 "".
ExtractParameters(const std::string & params,std::map<std::string,std::string> * result)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:
SimulateTimerFired(ExtensionUpdater * updater)341   static void SimulateTimerFired(ExtensionUpdater* updater) {
342     EXPECT_TRUE(updater->timer_.IsRunning());
343     updater->timer_.Stop();
344     updater->TimerFired();
345   }
346 
SimulateCheckSoon(const ExtensionUpdater & updater,MessageLoop * message_loop)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.
AddParseResult(const std::string & id,const std::string & version,const std::string & url,UpdateManifest::Results * 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 
TestExtensionUpdateCheckRequests(bool pending)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 
TestBlacklistUpdateCheckRequests()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 
TestUpdateUrlDataEmpty()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 
TestUpdateUrlDataSimple()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 
TestUpdateUrlDataCompound()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 
TestUpdateUrlDataFromGallery(const std::string & gallery_url)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 
TestDetermineUpdates()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 
TestDetermineUpdatesPending()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 
TestMultipleManifestDownloading()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 
TestSingleExtensionDownloading(bool pending)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 
TestBlacklistDownloading()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 
TestMultipleExtensionDownloading()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).
TestGalleryRequests(int rollcall_ping_days,int active_ping_days,bool active_bit)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.
TestHandleManifestResults()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 
TEST(ExtensionUpdaterTest,TestExtensionUpdateCheckRequests)1034 TEST(ExtensionUpdaterTest, TestExtensionUpdateCheckRequests) {
1035   ExtensionUpdaterTest::TestExtensionUpdateCheckRequests(false);
1036 }
1037 
TEST(ExtensionUpdaterTest,TestExtensionUpdateCheckRequestsPending)1038 TEST(ExtensionUpdaterTest, TestExtensionUpdateCheckRequestsPending) {
1039   ExtensionUpdaterTest::TestExtensionUpdateCheckRequests(true);
1040 }
1041 
1042 // This test is disabled on Mac, see http://crbug.com/26035.
TEST(ExtensionUpdaterTest,TestBlacklistUpdateCheckRequests)1043 TEST(ExtensionUpdaterTest, TestBlacklistUpdateCheckRequests) {
1044   ExtensionUpdaterTest::TestBlacklistUpdateCheckRequests();
1045 }
1046 
TEST(ExtensionUpdaterTest,TestUpdateUrlData)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 
TEST(ExtensionUpdaterTest,TestDetermineUpdates)1060 TEST(ExtensionUpdaterTest, TestDetermineUpdates) {
1061   ExtensionUpdaterTest::TestDetermineUpdates();
1062 }
1063 
TEST(ExtensionUpdaterTest,TestDetermineUpdatesPending)1064 TEST(ExtensionUpdaterTest, TestDetermineUpdatesPending) {
1065   ExtensionUpdaterTest::TestDetermineUpdatesPending();
1066 }
1067 
TEST(ExtensionUpdaterTest,TestMultipleManifestDownloading)1068 TEST(ExtensionUpdaterTest, TestMultipleManifestDownloading) {
1069   ExtensionUpdaterTest::TestMultipleManifestDownloading();
1070 }
1071 
TEST(ExtensionUpdaterTest,TestSingleExtensionDownloading)1072 TEST(ExtensionUpdaterTest, TestSingleExtensionDownloading) {
1073   ExtensionUpdaterTest::TestSingleExtensionDownloading(false);
1074 }
1075 
TEST(ExtensionUpdaterTest,TestSingleExtensionDownloadingPending)1076 TEST(ExtensionUpdaterTest, TestSingleExtensionDownloadingPending) {
1077   ExtensionUpdaterTest::TestSingleExtensionDownloading(true);
1078 }
1079 
1080 // This test is disabled on Mac, see http://crbug.com/26035.
TEST(ExtensionUpdaterTest,TestBlacklistDownloading)1081 TEST(ExtensionUpdaterTest, TestBlacklistDownloading) {
1082   ExtensionUpdaterTest::TestBlacklistDownloading();
1083 }
1084 
TEST(ExtensionUpdaterTest,TestMultipleExtensionDownloading)1085 TEST(ExtensionUpdaterTest, TestMultipleExtensionDownloading) {
1086   ExtensionUpdaterTest::TestMultipleExtensionDownloading();
1087 }
1088 
TEST(ExtensionUpdaterTest,TestGalleryRequests)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 
TEST(ExtensionUpdaterTest,TestHandleManifestResults)1118 TEST(ExtensionUpdaterTest, TestHandleManifestResults) {
1119   ExtensionUpdaterTest::TestHandleManifestResults();
1120 }
1121 
TEST(ExtensionUpdaterTest,TestManifestFetchesBuilderAddExtension)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 
TEST(ExtensionUpdaterTest,TestStartUpdateCheckMemory)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 
TEST(ExtensionUpdaterTest,TestCheckSoon)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