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, ¶ms);
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, ¶ms);
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