Remove per-component URL Sources, and add the ability to pass the URL
source as a flag. This flag is necessary for testing differential
updates.

BUG=245318

Review URL: https://chromiumcodereview.appspot.com/17893016

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209307 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/component_updater/component_updater_configurator.cc b/chrome/browser/component_updater/component_updater_configurator.cc
index 43e90725..d211e5e 100644
--- a/chrome/browser/component_updater/component_updater_configurator.cc
+++ b/chrome/browser/component_updater/component_updater_configurator.cc
@@ -29,7 +29,7 @@
 const int kDelayOneMinute = 60;
 const int kDelayOneHour = kDelayOneMinute * 60;
 
-// Debug values you can pass to --component-updater-debug=value1,value2.
+// Debug values you can pass to --component-updater=value1,value2.
 // Speed up component checking.
 const char kSwitchFastUpdate[] = "fast-update";
 // Force out-of-process-xml parsing.
@@ -38,20 +38,42 @@
 const char kSwitchRequestParam[] = "test-request";
 // Disables differential updates.
 const char kSwitchDisableDeltaUpdates[] = "disable-delta-updates";
+// Sets the URL for updates.
+const char kSwitchUrlSource[] = "url-source";
 
-// The urls from which an update manifest can be fetched.
-const char* kUrlSources[] = {
-  "http://clients2.google.com/service/update2/crx",       // BANDAID
-  "http://omaha.google.com/service/update2/crx",          // CWS_PUBLIC
-  "http://omaha.sandbox.google.com/service/update2/crx",   // CWS_SANDBOX
-};
+// The default url from which an update manifest can be fetched. Can be
+// overridden with --component-updater=url-source=someurl.
+const char kDefaultUrlSource[] =
+    "http://clients2.google.com/service/update2/crx";
 
+// Returns true if and only if |test| is contained in |vec|.
 bool HasSwitchValue(const std::vector<std::string>& vec, const char* test) {
   if (vec.empty())
     return 0;
   return (std::find(vec.begin(), vec.end(), test) != vec.end());
 }
 
+// If there is an element of |vec| of the form |test|=.*, returns the right-
+// hand side of that assignment. Otherwise, returns an empty string.
+// The right-hand side may contain additional '=' characters, allowing for
+// further nesting of switch arguments.
+std::string GetSwitchArgument(const std::vector<std::string>& vec,
+                              const char* test) {
+  if (vec.empty())
+    return std::string();
+  for (std::vector<std::string>::const_iterator it = vec.begin();
+      it != vec.end();
+      ++it) {
+    const std::size_t found = it->find("=");
+    if (found != std::string::npos) {
+      if (it->substr(0, found) == test) {
+        return it->substr(found + 1);
+      }
+    }
+  }
+  return std::string();
+}
+
 }  // namespace
 
 class ChromeConfigurator : public ComponentUpdateService::Configurator {
@@ -66,7 +88,7 @@
   virtual int StepDelay() OVERRIDE;
   virtual int MinimumReCheckWait() OVERRIDE;
   virtual int OnDemandDelay() OVERRIDE;
-  virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE;
+  virtual GURL UpdateUrl() OVERRIDE;
   virtual const char* ExtraRequestParams() OVERRIDE;
   virtual size_t UrlSizeLimit() OVERRIDE;
   virtual net::URLRequestContextGetter* RequestContext() OVERRIDE;
@@ -78,6 +100,7 @@
  private:
   net::URLRequestContextGetter* url_request_getter_;
   std::string extra_info_;
+  std::string url_source_;
   bool fast_update_;
   bool out_of_process_;
   bool deltas_enabled_;
@@ -103,6 +126,11 @@
   deltas_enabled_ = false;
 #endif
 
+  url_source_ = GetSwitchArgument(switch_values, kSwitchUrlSource);
+  if (url_source_.empty()) {
+    url_source_ = kDefaultUrlSource;
+  }
+
   // Make the extra request params, they are necessary so omaha does
   // not deliver components that are going to be rejected at install time.
 #if defined(OS_WIN)
@@ -134,8 +162,8 @@
   return fast_update_ ? 2 : (30 * kDelayOneMinute);
 }
 
-GURL ChromeConfigurator::UpdateUrl(CrxComponent::UrlSource source) {
-  return GURL(kUrlSources[source]);
+GURL ChromeConfigurator::UpdateUrl() {
+  return GURL(url_source_);
 }
 
 const char* ChromeConfigurator::ExtraRequestParams() {
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index 19e94fa7..6ceb452 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -51,13 +51,6 @@
 
 namespace {
 
-// Manifest sources, from most important to least important.
-const CrxComponent::UrlSource kManifestSources[] = {
-  CrxComponent::BANDAID,
-  CrxComponent::CWS_PUBLIC,
-  CrxComponent::CWS_SANDBOX,
-};
-
 // Extends an omaha compatible update check url |query| string. Does
 // not mutate the string if it would be longer than |limit| chars.
 bool AddQueryString(const std::string& id,
@@ -288,8 +281,7 @@
 }  // namespace.
 
 CrxComponent::CrxComponent()
-    : installer(NULL),
-      source(BANDAID) {
+    : installer(NULL) {
 }
 
 CrxComponent::~CrxComponent() {
@@ -686,73 +678,61 @@
     return;
   }
 
-  for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) {
-    const CrxComponent::UrlSource manifest_source = kManifestSources[ix];
-
-    std::string query;
-    // If no pending upgrades, we check if there are new components we have not
-    // checked against the server. We can batch some in a single url request.
-    for (UpdateItems::const_iterator it = work_items_.begin();
-         it != work_items_.end(); ++it) {
-      CrxUpdateItem* item = *it;
-      if (item->status != CrxUpdateItem::kNew)
-        continue;
-      if (item->component.source != manifest_source)
-        continue;
-      if (!AddItemToUpdateCheck(item, &query))
-        break;
-      // Requested work items may speed up the update cycle up until
-      // the point that we start an update check. I.e., transition
-      // from kNew -> kChecking.  Since the service doesn't guarantee that
-      // the requested items make it any further than kChecking,
-      // forget them now.
-      requested_work_items_.erase(item);
-    }
-
-    // Next we can go back to components we already checked, here
-    // we can also batch them in a single url request, as long as
-    // we have not checked them recently.
-    const base::TimeDelta min_delta_time =
-        base::TimeDelta::FromSeconds(config_->MinimumReCheckWait());
-
-    for (UpdateItems::const_iterator it = work_items_.begin();
-         it != work_items_.end(); ++it) {
-      CrxUpdateItem* item = *it;
-      if ((item->status != CrxUpdateItem::kNoUpdate) &&
-          (item->status != CrxUpdateItem::kUpToDate))
-        continue;
-      if (item->component.source != manifest_source)
-        continue;
-      base::TimeDelta delta = base::Time::Now() - item->last_check;
-      if (delta < min_delta_time)
-        continue;
-      if (!AddItemToUpdateCheck(item, &query))
-        break;
-    }
-
-    // Finally, we check components that we already updated as long as
-    // we have not checked them recently.
-    for (UpdateItems::const_iterator it = work_items_.begin();
-         it != work_items_.end(); ++it) {
-      CrxUpdateItem* item = *it;
-      if (item->status != CrxUpdateItem::kUpdated)
-        continue;
-      if (item->component.source != manifest_source)
-        continue;
-      base::TimeDelta delta = base::Time::Now() - item->last_check;
-      if (delta < min_delta_time)
-        continue;
-      if (!AddItemToUpdateCheck(item, &query))
-        break;
-    }
-
-    // If no components to update we move down to the next source.
-    if (query.empty())
+  std::string query;
+  // If no pending upgrades, we check if there are new components we have not
+  // checked against the server. We can batch some in a single url request.
+  for (UpdateItems::const_iterator it = work_items_.begin();
+       it != work_items_.end(); ++it) {
+    CrxUpdateItem* item = *it;
+    if (item->status != CrxUpdateItem::kNew)
       continue;
+    if (!AddItemToUpdateCheck(item, &query))
+      break;
+    // Requested work items may speed up the update cycle up until
+    // the point that we start an update check. I.e., transition
+    // from kNew -> kChecking.  Since the service doesn't guarantee that
+    // the requested items make it any further than kChecking,
+    // forget them now.
+    requested_work_items_.erase(item);
+  }
 
+  // Next we can go back to components we already checked, here
+  // we can also batch them in a single url request, as long as
+  // we have not checked them recently.
+  const base::TimeDelta min_delta_time =
+      base::TimeDelta::FromSeconds(config_->MinimumReCheckWait());
+
+  for (UpdateItems::const_iterator it = work_items_.begin();
+       it != work_items_.end(); ++it) {
+    CrxUpdateItem* item = *it;
+    if ((item->status != CrxUpdateItem::kNoUpdate) &&
+        (item->status != CrxUpdateItem::kUpToDate))
+      continue;
+    base::TimeDelta delta = base::Time::Now() - item->last_check;
+    if (delta < min_delta_time)
+      continue;
+    if (!AddItemToUpdateCheck(item, &query))
+      break;
+  }
+
+  // Finally, we check components that we already updated as long as
+  // we have not checked them recently.
+  for (UpdateItems::const_iterator it = work_items_.begin();
+       it != work_items_.end(); ++it) {
+    CrxUpdateItem* item = *it;
+    if (item->status != CrxUpdateItem::kUpdated)
+      continue;
+    base::TimeDelta delta = base::Time::Now() - item->last_check;
+    if (delta < min_delta_time)
+      continue;
+    if (!AddItemToUpdateCheck(item, &query))
+      break;
+  }
+
+  if (!query.empty()) {
     // We got components to check. Start the url request and exit.
     const std::string full_query =
-        MakeFinalQuery(config_->UpdateUrl(manifest_source).spec(),
+        MakeFinalQuery(config_->UpdateUrl().spec(),
                        query,
                        config_->ExtraRequestParams());
 
diff --git a/chrome/browser/component_updater/component_updater_service.h b/chrome/browser/component_updater/component_updater_service.h
index bf011eb4..c097545 100644
--- a/chrome/browser/component_updater/component_updater_service.h
+++ b/chrome/browser/component_updater/component_updater_service.h
@@ -55,24 +55,12 @@
 // |pk_hash| is the SHA256 hash of the component's public key. If the component
 // is to be installed then version should be "0" or "0.0", else it should be
 // the current version. |fingerprint| and |name| are optional.
-// |source| is by default pointing to BANDAID but if needed it can be made
-// to point to the webstore (CWS_PUBLIC) or to the webstore sandbox. It is
-// important to note that the BANDAID source if active throught the day
-// can pre-empt updates from the other sources down the list.
 struct CrxComponent {
-  // Specifies the source url for manifest check.
-  enum UrlSource {
-    BANDAID,
-    CWS_PUBLIC,
-    CWS_SANDBOX,
-  };
-
   std::vector<uint8> pk_hash;
   ComponentInstaller* installer;
   Version version;
   std::string fingerprint;
   std::string name;
-  UrlSource source;
   CrxComponent();
   ~CrxComponent();
 };
@@ -125,7 +113,7 @@
     // for the same component.
     virtual int OnDemandDelay() = 0;
     // The url that is going to be used update checks over Omaha protocol.
-    virtual GURL UpdateUrl(CrxComponent::UrlSource source) = 0;
+    virtual GURL UpdateUrl() = 0;
     // Parameters added to each url request. It can be null if none are needed.
     virtual const char* ExtraRequestParams() = 0;
     // How big each update request can be. Don't go above 2000.
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.cc b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
index 8ca7080..37de921 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -82,15 +82,8 @@
   return ondemand_time_;
 }
 
-GURL TestConfigurator::UpdateUrl(CrxComponent::UrlSource source) {
-  switch (source) {
-    case CrxComponent::BANDAID:
-      return GURL("http://localhost/upd");
-    case CrxComponent::CWS_PUBLIC:
-      return GURL("http://localhost/cws");
-    default:
-      return GURL("http://wronghost/bad");
-  };
+GURL TestConfigurator::UpdateUrl() {
+  return GURL("http://localhost/upd");
 }
 
 const char* TestConfigurator::ExtraRequestParams() { return "extra=foo"; }
@@ -375,80 +368,6 @@
   component_updater()->Stop();
 }
 
-// This test is like the above InstallCrx but the second component
-// has a different source. In this case there would be two manifest
-// checks to different urls, each only containing one component.
-TEST_F(ComponentUpdaterTest, InstallCrxTwoSources) {
-  base::MessageLoop message_loop;
-  content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
-  content::TestBrowserThread file_thread(BrowserThread::FILE);
-  content::TestBrowserThread io_thread(BrowserThread::IO);
-
-  io_thread.StartIOThread();
-  file_thread.Start();
-
-  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
-
-  TestInstaller installer1;
-  CrxComponent com1;
-  RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
-  TestInstaller installer2;
-  CrxComponent com2;
-  com2.source = CrxComponent::CWS_PUBLIC;
-  RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
-
-  const GURL expected_update_url_1(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
-
-  const GURL expected_update_url_2(
-      "http://localhost/cws?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
-
-  interceptor.SetResponse(expected_update_url_1,
-                          test_file("updatecheck_reply_3.xml"));
-  interceptor.SetResponse(expected_update_url_2,
-                          test_file("updatecheck_reply_1.xml"));
-  interceptor.SetResponse(GURL(expected_crx_url),
-                          test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
-
-  test_configurator()->SetLoopCount(3);
-
-  // We have to set SetRecheckTime to something bigger than 0 or else the
-  // component updater will keep re-checking the 'abag' component because
-  // the default source pre-empts the other sources.
-  test_configurator()->SetRecheckTime(60*60);
-
-  component_updater()->Start();
-  message_loop.Run();
-
-  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
-  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
-  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
-  EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count());
-
-  EXPECT_EQ(3, interceptor.GetHitCount());
-
-  ASSERT_EQ(6ul, notification_tracker().size());
-
-  TestNotificationTracker::Event ev0 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev0.type);
-
-  TestNotificationTracker::Event ev1 = notification_tracker().at(2);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
-
-  TestNotificationTracker::Event ev2 = notification_tracker().at(3);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
-
-  TestNotificationTracker::Event ev3 = notification_tracker().at(4);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
-
-  TestNotificationTracker::Event ev4 = notification_tracker().at(5);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
-  component_updater()->Stop();
-}
-
 // This test checks that the "prodversionmin" value is handled correctly. In
 // particular there should not be an install because the minimum product
 // version is much higher than of chrome.
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.h b/chrome/browser/component_updater/test/component_updater_service_unittest.h
index 4d7cd184..ba98102 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.h
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.h
@@ -57,7 +57,7 @@
 
   virtual int OnDemandDelay() OVERRIDE;
 
-  virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE;
+  virtual GURL UpdateUrl() OVERRIDE;
 
   virtual const char* ExtraRequestParams() OVERRIDE;