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