Merge from Chromium at DEPS revision r213780

This commit was generated by merge_to_master.py.

Change-Id: I9cf93efc460166e8ae27c76302af9095b402a90e
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index b5c1fc7..ca42870 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -106,7 +106,4 @@
   "+third_party/WebKit/public/web/WebScreenInfo.h",
   "+third_party/WebKit/public/web/WebTextDirection.h",
   "+third_party/WebKit/public/web/WebWindowFeatures.h",
-
-  # These should be burned down. http://crbug.com/237267
-  "!third_party/WebKit/public/web/WebView.h",
 ]
diff --git a/chrome/browser/OWNERS b/chrome/browser/OWNERS
index f9db9bc..b614afe 100644
--- a/chrome/browser/OWNERS
+++ b/chrome/browser/OWNERS
@@ -4,6 +4,7 @@
 
 per-file chrome_content_browser_client.cc=*
 per-file chrome_content_browser_client.h=*
+per-file chrome_content_browser_client_browsertest.cc=*
 
 per-file chrome_browser_field_trials*=asvitkine@chromium.org
 per-file chrome_browser_field_trials*=stevet@chromium.org
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 9879d13..9e5a15e 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1228,14 +1228,16 @@
     IDS_FLAGS_ASH_ENABLE_NEW_AUDIO_HANDLER_NAME,
     IDS_FLAGS_ASH_ENABLE_NEW_AUDIO_HANDLER_DESCRIPTION,
     kOsCrOS,
-    ENABLE_DISABLE_VALUE_TYPE("", ash::switches::kAshDisableNewAudioHandler)
+    ENABLE_DISABLE_VALUE_TYPE(ash::switches::kAshEnableNewAudioHandler,
+                              ash::switches::kAshDisableNewAudioHandler)
   },
   {
     "ash-audio-device-menu",
     IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_NAME,
     IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_DESCRIPTION,
     kOsCrOS,
-    ENABLE_DISABLE_VALUE_TYPE("", ash::switches::kAshDisableAudioDeviceMenu)
+    ENABLE_DISABLE_VALUE_TYPE(ash::switches::kAshEnableAudioDeviceMenu,
+                              ash::switches::kAshDisableAudioDeviceMenu)
   },
   {
     "enable-carrier-switching",
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index 1eb406a..15b8959 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -849,10 +849,8 @@
 void BrowsingDataRemover::ClearShaderCacheOnUIThread() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  BrowserContext::GetDefaultStoragePartition(profile_)->ClearDataForRange(
-      content::StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE,
-      content::StoragePartition::kAllStorage,
-      delete_begin_, delete_end_,
+  BrowserContext::GetDefaultStoragePartition(profile_)->AsyncClearDataBetween(
+      content::StoragePartition::kShaderStorage, delete_begin_, delete_end_,
       base::Bind(&BrowsingDataRemover::ClearedShaderCache,
                  base::Unretained(this)));
 }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index a166d59..a47541a 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2195,6 +2195,11 @@
   // actually handle them.
   handler->AddHandlerPair(&WillHandleBrowserAboutURL,
                           BrowserURLHandler::null_handler());
+
+  // Handler to rewrite chrome://newtab for InstantExtended.
+  handler->AddHandlerPair(&chrome::HandleNewTabURLRewrite,
+                          &chrome::HandleNewTabURLReverseRewrite);
+
   // chrome: & friends.
   handler->AddHandlerPair(&HandleWebUI, &HandleWebUIReverse);
 }
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc
index de24691..9d4b494 100644
--- a/chrome/browser/chrome_content_browser_client_browsertest.cc
+++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/navigation_controller.h"
@@ -75,6 +77,37 @@
   EXPECT_EQ(url, entry->GetVirtualURL());
 }
 
+IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientBrowserTest,
+                       UberURLHandler_InstantExtendedNewTabPage) {
+  const GURL url_original("chrome://newtab");
+  const GURL url_rewritten("http://example.com/newtab");
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kInstantNewTabURL, url_rewritten.spec());
+  chrome::EnableInstantExtendedAPIForTesting();
+
+  ui_test_utils::NavigateToURL(browser(), url_original);
+  NavigationEntry* entry = GetLastCommittedEntry();
+
+  ASSERT_TRUE(entry != NULL);
+  EXPECT_EQ(url_rewritten, entry->GetURL());
+  EXPECT_EQ(url_original, entry->GetVirtualURL());
+}
+
+IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientBrowserTest,
+                       UberURLHandler_InstantExtendedNewTabPageDisabled) {
+  const GURL url_original("chrome://newtab");
+  const GURL url_rewritten("http://example.com/newtab");
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kInstantNewTabURL, url_rewritten.spec());
+
+  ui_test_utils::NavigateToURL(browser(), url_original);
+  NavigationEntry* entry = GetLastCommittedEntry();
+
+  ASSERT_TRUE(entry != NULL);
+  EXPECT_EQ(url_original, entry->GetURL());
+  EXPECT_EQ(url_original, entry->GetVirtualURL());
+}
+
 // Test that a basic navigation works in --site-per-process mode.  This prevents
 // regressions when that mode calls out into the ChromeContentBrowserClient,
 // such as http://crbug.com/164223.
diff --git a/chrome/browser/chrome_page_zoom.cc b/chrome/browser/chrome_page_zoom.cc
index acca565..ae596ce 100644
--- a/chrome/browser/chrome_page_zoom.cc
+++ b/chrome/browser/chrome_page_zoom.cc
@@ -14,8 +14,8 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/page_zoom.h"
 #include "content/public/common/renderer_preferences.h"
-#include "third_party/WebKit/public/web/WebView.h"
 
 using content::UserMetricsAction;
 
@@ -36,7 +36,7 @@
   for (size_t i = 0; i < kPresetZoomFactorsSize; i++) {
     double zoom_value = kPresetZoomFactors[i];
     if (value_type == PAGE_ZOOM_VALUE_TYPE_LEVEL)
-      zoom_value = WebKit::WebView::zoomFactorToZoomLevel(zoom_value);
+      zoom_value = content::ZoomFactorToZoomLevel(zoom_value);
     if (content::ZoomValuesEqual(zoom_value, custom_value))
       found_custom = true;
     zoom_values.push_back(zoom_value);
@@ -44,10 +44,10 @@
   // If the preset array did not contain the custom value, append it to the
   // vector and then sort.
   double min = value_type == PAGE_ZOOM_VALUE_TYPE_LEVEL ?
-      WebKit::WebView::zoomFactorToZoomLevel(content::kMinimumZoomFactor) :
+      content::ZoomFactorToZoomLevel(content::kMinimumZoomFactor) :
       content::kMinimumZoomFactor;
   double max = value_type == PAGE_ZOOM_VALUE_TYPE_LEVEL ?
-      WebKit::WebView::zoomFactorToZoomLevel(content::kMaximumZoomFactor) :
+      content::ZoomFactorToZoomLevel(content::kMaximumZoomFactor) :
       content::kMaximumZoomFactor;
   if (!found_custom && custom_value > min && custom_value < max) {
     zoom_values.push_back(custom_value);
diff --git a/chrome/browser/chromeos/drive/change_list_loader_unittest.cc b/chrome/browser/chromeos/drive/change_list_loader_unittest.cc
index d774a64..7605e61 100644
--- a/chrome/browser/chromeos/drive/change_list_loader_unittest.cc
+++ b/chrome/browser/chromeos/drive/change_list_loader_unittest.cc
@@ -66,6 +66,35 @@
   DISALLOW_COPY_AND_ASSIGN(TestChangeListLoaderObserver);
 };
 
+class TestDriveService : public FakeDriveService {
+ public:
+  TestDriveService() : never_return_all_resource_list_(false),
+                       blocked_call_count_(0) {}
+
+  void set_never_return_all_resource_list(bool value) {
+    never_return_all_resource_list_ = value;
+  }
+
+  int blocked_call_count() const { return blocked_call_count_; }
+
+  // FakeDriveService override.
+  virtual google_apis::CancelCallback GetAllResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE {
+    if (never_return_all_resource_list_) {
+      ++blocked_call_count_;
+      return google_apis::CancelCallback();
+    }
+    return FakeDriveService::GetAllResourceList(callback);
+  }
+
+ private:
+  // GetAllResourceList never returns result when this is set to true.
+  // Used to emulate the real server's slowness.
+  bool never_return_all_resource_list_;
+
+  int blocked_call_count_;  // Number of blocked method calls.
+};
+
 class ChangeListLoaderTest : public testing::Test {
  protected:
   virtual void SetUp() OVERRIDE {
@@ -73,7 +102,7 @@
     pref_service_.reset(new TestingPrefServiceSimple);
     test_util::RegisterDrivePrefs(pref_service_->registry());
 
-    drive_service_.reset(new FakeDriveService);
+    drive_service_.reset(new TestDriveService);
     ASSERT_TRUE(drive_service_->LoadResourceListForWapi(
         "gdata/root_feed.json"));
     ASSERT_TRUE(drive_service_->LoadAccountMetadataForWapi(
@@ -121,7 +150,7 @@
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
   scoped_ptr<TestingPrefServiceSimple> pref_service_;
-  scoped_ptr<FakeDriveService> drive_service_;
+  scoped_ptr<TestDriveService> drive_service_;
   scoped_ptr<JobScheduler> scheduler_;
   scoped_ptr<ResourceMetadataStorage,
              test_util::DestroyHelperForTests> metadata_storage_;
@@ -224,6 +253,112 @@
             metadata_->GetResourceEntryByPath(file_path, &entry));
 }
 
+TEST_F(ChangeListLoaderTest, LoadIfNeeded_MyDrive) {
+  // Emulate the slowness of GetAllResourceList().
+  drive_service_->set_never_return_all_resource_list(true);
+
+  // Load grand root.
+  FileError error = FILE_ERROR_FAILED;
+  change_list_loader_->LoadIfNeeded(
+      DirectoryFetchInfo(util::kDriveGrandRootSpecialResourceId, 0),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // GetAllResourceList() was called.
+  EXPECT_EQ(1, drive_service_->blocked_call_count());
+
+  // My Drive is present in the local metadata, but its child is not.
+  ResourceEntry entry;
+  EXPECT_EQ(FILE_ERROR_OK,
+            metadata_->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
+                                              &entry));
+  const int64 mydrive_changestamp =
+      entry.directory_specific_info().changestamp();
+
+  base::FilePath file_path =
+      util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
+  EXPECT_EQ(FILE_ERROR_NOT_FOUND,
+            metadata_->GetResourceEntryByPath(file_path, &entry));
+
+  // Load My Drive.
+  change_list_loader_->LoadIfNeeded(
+      DirectoryFetchInfo(drive_service_->GetRootResourceId(),
+                         mydrive_changestamp),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // Now the file is present.
+  EXPECT_EQ(FILE_ERROR_OK,
+            metadata_->GetResourceEntryByPath(file_path, &entry));
+}
+
+TEST_F(ChangeListLoaderTest, LoadIfNeeded_NewDirectories) {
+  // Make local metadata up to date.
+  FileError error = FILE_ERROR_FAILED;
+  change_list_loader_->LoadIfNeeded(
+      DirectoryFetchInfo(),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // Add a new file.
+  scoped_ptr<google_apis::ResourceEntry> file = AddNewFile("New File");
+  ASSERT_TRUE(file);
+
+  // Emulate the slowness of GetAllResourceList().
+  drive_service_->set_never_return_all_resource_list(true);
+
+  // Enter refreshing state.
+  FileError check_for_updates_error = FILE_ERROR_FAILED;
+  change_list_loader_->CheckForUpdates(
+      google_apis::test_util::CreateCopyResultCallback(
+          &check_for_updates_error));
+  EXPECT_TRUE(change_list_loader_->IsRefreshing());
+
+  // Load My Drive.
+  change_list_loader_->LoadIfNeeded(
+      DirectoryFetchInfo(drive_service_->GetRootResourceId(),
+                         metadata_->GetLargestChangestamp()),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // The new file is present in the local metadata.
+  base::FilePath file_path =
+      util::GetDriveMyDriveRootPath().AppendASCII(file->title());
+  ResourceEntry entry;
+  EXPECT_EQ(FILE_ERROR_OK,
+            metadata_->GetResourceEntryByPath(file_path, &entry));
+}
+
+TEST_F(ChangeListLoaderTest, LoadIfNeeded_MultipleCalls) {
+  TestChangeListLoaderObserver observer(change_list_loader_.get());
+
+  // Load grand root.
+  FileError error = FILE_ERROR_FAILED;
+  change_list_loader_->LoadIfNeeded(
+      DirectoryFetchInfo(util::kDriveGrandRootSpecialResourceId, 0),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+
+  // Load grand root again without waiting for the result.
+  FileError error2 = FILE_ERROR_FAILED;
+  change_list_loader_->LoadIfNeeded(
+      DirectoryFetchInfo(util::kDriveGrandRootSpecialResourceId, 0),
+      google_apis::test_util::CreateCopyResultCallback(&error2));
+  base::RunLoop().RunUntilIdle();
+
+  // Callback is called for each method call.
+  EXPECT_EQ(FILE_ERROR_OK, error);
+  EXPECT_EQ(FILE_ERROR_OK, error2);
+
+  // No duplicated resource list load and observer events.
+  EXPECT_EQ(1, drive_service_->resource_list_load_count());
+  EXPECT_EQ(1, observer.initial_load_complete_count());
+  EXPECT_EQ(1, observer.load_from_server_complete_count());
+}
+
 TEST_F(ChangeListLoaderTest, CheckForUpdates) {
   // CheckForUpdates() results in no-op before load.
   FileError check_for_updates_error = FILE_ERROR_FAILED;
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 1af4edc..139292c 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -232,6 +232,13 @@
     drive_notification_manager->RemoveObserver(this);
 
   RemoveDriveMountPoint();
+  debug_info_collector_.reset();

+  download_handler_.reset();

+  file_write_helper_.reset();

+  file_system_.reset();

+  drive_app_registry_.reset();

+  scheduler_.reset();
+  drive_service_.reset();
 }
 
 void DriveIntegrationService::AddObserver(
diff --git a/chrome/browser/chromeos/drive/file_cache.cc b/chrome/browser/chromeos/drive/file_cache.cc
index 1b1ef5e..8ef2ab7 100644
--- a/chrome/browser/chromeos/drive/file_cache.cc
+++ b/chrome/browser/chromeos/drive/file_cache.cc
@@ -238,7 +238,6 @@
 }
 
 void FileCache::GetFileOnUIThread(const std::string& resource_id,
-                                  const std::string& md5,
                                   const GetFileFromCacheCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
@@ -249,7 +248,6 @@
                                    base::Bind(&FileCache::GetFile,
                                               base::Unretained(this),
                                               resource_id,
-                                              md5,
                                               cache_file_path),
                                    base::Bind(&RunGetFileFromCacheCallback,
                                               callback,
@@ -257,13 +255,12 @@
 }
 
 FileError FileCache::GetFile(const std::string& resource_id,
-                             const std::string& md5,
                              base::FilePath* cache_file_path) {
   AssertOnSequencedWorkerPool();
   DCHECK(cache_file_path);
 
   FileCacheEntry cache_entry;
-  if (!GetCacheEntry(resource_id, md5, &cache_entry) ||
+  if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
       !cache_entry.is_present())
     return FILE_ERROR_NOT_FOUND;
 
@@ -417,7 +414,6 @@
   if (cache_entry.is_dirty())
     return FILE_ERROR_OK;
 
-  // Now that file operations have completed, update metadata.
   cache_entry.set_is_dirty(true);
   return storage_->PutCacheEntry(resource_id, cache_entry) ?
       FILE_ERROR_OK : FILE_ERROR_FAILED;
@@ -427,30 +423,24 @@
                                 const std::string& md5) {
   AssertOnSequencedWorkerPool();
 
-  // |md5| is the new .<md5> extension to rename the file to.
-  // So, search for entry in cache without comparing md5.
-  FileCacheEntry cache_entry;
-
   // Clearing a dirty file means its entry and actual file blob must exist in
   // cache.
+  FileCacheEntry cache_entry;
   if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
       !cache_entry.is_present()) {
     LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: "
-                 << "res_id=" << resource_id
-                 << ", md5=" << md5;
+                 << resource_id;
     return FILE_ERROR_NOT_FOUND;
   }
 
   // If a file is not dirty (it should have been marked dirty via
   // MarkDirtyInCache), clearing its dirty state is an invalid operation.
   if (!cache_entry.is_dirty()) {
-    LOG(WARNING) << "Can't clear dirty state of a non-dirty file: res_id="
-                 << resource_id
-                 << ", md5=" << md5;
+    LOG(WARNING) << "Can't clear dirty state of a non-dirty file: "
+                 << resource_id;
     return FILE_ERROR_INVALID_OPERATION;
   }
 
-  // Now that file operations have completed, update metadata.
   cache_entry.set_md5(md5);
   cache_entry.set_is_dirty(false);
   return storage_->PutCacheEntry(resource_id, cache_entry) ?
diff --git a/chrome/browser/chromeos/drive/file_cache.h b/chrome/browser/chromeos/drive/file_cache.h
index c576b7b..405341b 100644
--- a/chrome/browser/chromeos/drive/file_cache.h
+++ b/chrome/browser/chromeos/drive/file_cache.h
@@ -134,15 +134,12 @@
   // |callback| must not be null.
   // Must be called on the UI thread.
   void GetFileOnUIThread(const std::string& resource_id,
-                         const std::string& md5,
                          const GetFileFromCacheCallback& callback);
 
-  // Checks if file corresponding to |resource_id| and |md5| exists in cache,
-  // and returns FILE_ERROR_OK with |cache_file_path| storing the path to
-  // the file.
+  // Checks if file corresponding to |resource_id| exists in cache, and returns
+  // FILE_ERROR_OK with |cache_file_path| storing the path to the file.
   // |cache_file_path| must not be null.
   FileError GetFile(const std::string& resource_id,
-                    const std::string& md5,
                     base::FilePath* cache_file_path);
 
   // Runs Store() on |blocking_task_runner_|, and calls |callback| with
@@ -205,7 +202,7 @@
   // Marks the specified entry dirty.
   FileError MarkDirty(const std::string& resource_id);
 
-  // Clears dirty state of the specified entry.
+  // Clears dirty state of the specified entry and updates its MD5.
   FileError ClearDirty(const std::string& resource_id,
                        const std::string& md5);
 
diff --git a/chrome/browser/chromeos/drive/file_cache_unittest.cc b/chrome/browser/chromeos/drive/file_cache_unittest.cc
index f18830a..7db6e0a 100644
--- a/chrome/browser/chromeos/drive/file_cache_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_cache_unittest.cc
@@ -106,14 +106,11 @@
     ASSERT_TRUE(success);
   }
 
-  void TestGetFileFromCacheByResourceIdAndMd5(
-      const std::string& resource_id,
-      const std::string& md5,
-      FileError expected_error,
-      const std::string& expected_file_extension) {
+  void TestGetFile(const std::string& resource_id,
+                   FileError expected_error) {
     FileError error = FILE_ERROR_OK;
     base::FilePath cache_file_path;
-    cache_->GetFileOnUIThread(resource_id, md5,
+    cache_->GetFileOnUIThread(resource_id,
                               google_apis::test_util::CreateCopyResultCallback(
                                   &error, &cache_file_path));
     test_util::RunBlockingPoolTask();
@@ -217,7 +214,7 @@
     if (error == FILE_ERROR_OK) {
       base::FilePath cache_file_path;
       cache_->GetFileOnUIThread(
-          resource_id, std::string(),
+          resource_id,
           google_apis::test_util::CreateCopyResultCallback(
               &error, &cache_file_path));
       test_util::RunBlockingPoolTask();
@@ -271,7 +268,6 @@
   }
 
   void TestMarkAsUnmounted(const std::string& resource_id,
-                           const std::string& md5,
                            const base::FilePath& file_path,
                            FileError expected_error,
                            int expected_cache_state) {
@@ -286,7 +282,7 @@
 
     base::FilePath cache_file_path;
     cache_->GetFileOnUIThread(
-        resource_id, md5,
+        resource_id,
         google_apis::test_util::CreateCopyResultCallback(
             &error, &cache_file_path));
     test_util::RunBlockingPoolTask();
@@ -411,19 +407,11 @@
                    FILE_ERROR_OK, TEST_CACHE_STATE_PRESENT);
 
   // Then try to get the existing file from cache.
-  TestGetFileFromCacheByResourceIdAndMd5(
-      resource_id, md5, FILE_ERROR_OK, md5);
+  TestGetFile(resource_id, FILE_ERROR_OK);
 
-  // Get file from cache with same resource id as existing file but different
-  // md5.
-  TestGetFileFromCacheByResourceIdAndMd5(
-      resource_id, "9999", FILE_ERROR_NOT_FOUND, md5);
-
-  // Get file from cache with different resource id from existing file but same
-  // md5.
+  // Get file from cache with different resource id.
   resource_id = "document:1a2b";
-  TestGetFileFromCacheByResourceIdAndMd5(
-      resource_id, md5, FILE_ERROR_NOT_FOUND, md5);
+  TestGetFile(resource_id, FILE_ERROR_NOT_FOUND);
 }
 
 TEST_F(FileCacheTestOnUIThread, RemoveFromCacheSimple) {
@@ -506,16 +494,14 @@
   TestPin(resource_id, FILE_ERROR_OK, TEST_CACHE_STATE_PINNED);
 
   // Get the non-existent pinned file from cache.
-  TestGetFileFromCacheByResourceIdAndMd5(
-      resource_id, md5, FILE_ERROR_NOT_FOUND, md5);
+  TestGetFile(resource_id, FILE_ERROR_NOT_FOUND);
 
   // Store an existing file to the previously pinned non-existent file.
   TestStoreToCache(resource_id, md5, dummy_file_path_, FILE_ERROR_OK,
                    TEST_CACHE_STATE_PRESENT | TEST_CACHE_STATE_PINNED);
 
   // Get the previously pinned and stored file from cache.
-  TestGetFileFromCacheByResourceIdAndMd5(
-      resource_id, md5, FILE_ERROR_OK, md5);
+  TestGetFile(resource_id, FILE_ERROR_OK);
 }
 
 TEST_F(FileCacheTestOnUIThread, RemoveFromCachePinned) {
@@ -595,7 +581,7 @@
   base::FilePath dirty_path;
   FileError error = FILE_ERROR_FAILED;
   cache_->GetFileOnUIThread(
-      resource_id, md5,
+      resource_id,
       google_apis::test_util::CreateCopyResultCallback(&error, &dirty_path));
   test_util::RunBlockingPoolTask();
   EXPECT_EQ(FILE_ERROR_OK, error);
@@ -710,12 +696,12 @@
   base::FilePath file_path;
   FileError error = FILE_ERROR_FAILED;
   cache_->GetFileOnUIThread(
-      resource_id, md5,
+      resource_id,
       google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
   test_util::RunBlockingPoolTask();
   EXPECT_EQ(FILE_ERROR_OK, error);
 
-  TestMarkAsUnmounted(resource_id, md5, file_path, FILE_ERROR_OK,
+  TestMarkAsUnmounted(resource_id, file_path, FILE_ERROR_OK,
                       TEST_CACHE_STATE_PRESENT);
   EXPECT_TRUE(CacheEntryExists(resource_id, md5));
 
@@ -895,8 +881,7 @@
             cache_->Store(resource_id_tmp, md5_tmp, src_file,
                           FileCache::FILE_OPERATION_COPY));
   base::FilePath tmp_path;
-  ASSERT_EQ(FILE_ERROR_OK,
-            cache_->GetFile(resource_id_tmp, md5_tmp, &tmp_path));
+  ASSERT_EQ(FILE_ERROR_OK, cache_->GetFile(resource_id_tmp, &tmp_path));
 
   // Store a file as a pinned file and remember the path.
   const std::string resource_id_pinned = "id_pinned", md5_pinned = "md5_pinned";
@@ -905,8 +890,7 @@
                           FileCache::FILE_OPERATION_COPY));
   ASSERT_EQ(FILE_ERROR_OK, cache_->Pin(resource_id_pinned));
   base::FilePath pinned_path;
-  ASSERT_EQ(FILE_ERROR_OK,
-            cache_->GetFile(resource_id_pinned, md5_pinned, &pinned_path));
+  ASSERT_EQ(FILE_ERROR_OK, cache_->GetFile(resource_id_pinned, &pinned_path));
 
   // Call FreeDiskSpaceIfNeededFor().
   fake_free_disk_space_getter_->set_default_value(test_util::kLotsOfSpace);
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index 674dbc4..0962967 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -756,7 +756,6 @@
 
   drive::internal::SearchMetadata(blocking_task_runner_,
                                   resource_metadata_,
-                                  cache_,
                                   query,
                                   options,
                                   at_most_num_matches,
@@ -949,10 +948,8 @@
 
   // Gets the cache file path.
   const std::string& resource_id = entry->resource_id();
-  const std::string& md5 = entry->file_specific_info().md5();
   cache_->GetFileOnUIThread(
       resource_id,
-      md5,
       base::Bind(
           &FileSystem::CheckLocalModificationAndRunAfterGetCacheFile,
           weak_ptr_factory_.GetWeakPtr(),
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
index d9643e5..aee7007 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
@@ -125,7 +125,6 @@
   // The content is "x"s of the file size.
   base::FilePath cache_path;
   cache()->GetFileOnUIThread(entry.resource_id(),
-                             entry.file_specific_info().md5(),
                              google_apis::test_util::CreateCopyResultCallback(
                                  &error, &cache_path));
   test_util::RunBlockingPoolTask();
diff --git a/chrome/browser/chromeos/drive/file_system/download_operation.cc b/chrome/browser/chromeos/drive/file_system/download_operation.cc
index a391986..0e01200 100644
--- a/chrome/browser/chromeos/drive/file_system/download_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/download_operation.cc
@@ -66,29 +66,36 @@
     return FILE_ERROR_OK;
   }
 
-  // Get the cache file path if available.
-  cache->GetFile(entry->resource_id(),
-                 entry->file_specific_info().md5(),
-                 cache_file_path);
+  // Leave |cache_file_path| empty when no cache entry is found.
+  FileCacheEntry cache_entry;
+  if (!cache->GetCacheEntry(entry->resource_id(),
+                            entry->file_specific_info().md5(),
+                            &cache_entry))
+    return FILE_ERROR_OK;
 
-  // If the cache file is available and dirty, the modified file info needs to
-  // be stored in |entry|.
+  // Leave |cache_file_path| empty when the stored file is obsolete and has no
+  // local modification.
+  if (!cache_entry.is_dirty() &&
+      entry->file_specific_info().md5() != cache_entry.md5())
+    return FILE_ERROR_OK;
+
+  // Fill |cache_file_path| with the path to the cached file.
+  FileError error = cache->GetFile(entry->resource_id(), cache_file_path);
+  if (error != FILE_ERROR_OK)
+    return error;
+
+  // If the cache file is dirty, the modified file info needs to be stored in
+  // |entry|.
   // TODO(kinaba): crbug.com/246469. The logic below is a duplicate of that in
   // drive::FileSystem::CheckLocalModificationAndRun. We should merge them once
   // the drive::FS side is also converted to run fully on blocking pool.
-  if (!cache_file_path->empty()) {
-    FileCacheEntry cache_entry;
-    if (cache->GetCacheEntry(entry->resource_id(),
-                             entry->file_specific_info().md5(),
-                             &cache_entry) &&
-        cache_entry.is_dirty()) {
-      base::PlatformFileInfo file_info;
-      if (file_util::GetFileInfo(*cache_file_path, &file_info)) {
-        PlatformFileInfoProto entry_file_info;
-        util::ConvertPlatformFileInfoToResourceEntry(file_info,
-                                                     &entry_file_info);
-        *entry->mutable_file_info() = entry_file_info;
-      }
+  if (cache_entry.is_dirty()) {
+    base::PlatformFileInfo file_info;
+    if (file_util::GetFileInfo(*cache_file_path, &file_info)) {
+      PlatformFileInfoProto entry_file_info;
+      util::ConvertPlatformFileInfoToResourceEntry(file_info,
+                                                   &entry_file_info);
+      *entry->mutable_file_info() = entry_file_info;
     }
   }
 
@@ -194,7 +201,7 @@
     return error;
   }
 
-  return cache->GetFile(resource_id, md5, cache_file_path);
+  return cache->GetFile(resource_id, cache_file_path);
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/drive/file_system/open_file_operation.cc b/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
index d23c488..7743c06 100644
--- a/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
@@ -26,13 +26,12 @@
 
 FileError UpdateFileLocalState(internal::FileCache* cache,
                                const std::string& resource_id,
-                               const std::string& md5,
                                base::FilePath* local_file_path) {
   FileError error = cache->MarkDirty(resource_id);
   if (error != FILE_ERROR_OK)
     return error;
 
-  return cache->GetFile(resource_id, md5, local_file_path);
+  return cache->GetFile(resource_id, local_file_path);
 }
 
 }  // namespace
@@ -140,7 +139,6 @@
       base::Bind(&UpdateFileLocalState,
                  cache_,
                  entry->resource_id(),
-                 entry->file_specific_info().md5(),
                  new_local_file_path),
       base::Bind(&OpenFileOperation::OpenFileAfterUpdateLocalState,
                  weak_ptr_factory_.GetWeakPtr(),
diff --git a/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
index 32ff259..e2c8575 100644
--- a/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
@@ -48,7 +48,7 @@
   base::FilePath local_path;
   error = FILE_ERROR_FAILED;
   cache()->GetFileOnUIThread(
-      src_entry.resource_id(), src_entry.file_specific_info().md5(),
+      src_entry.resource_id(),
       google_apis::test_util::CreateCopyResultCallback(&error, &local_path));
   test_util::RunBlockingPoolTask();
   ASSERT_EQ(FILE_ERROR_OK, error);
@@ -107,7 +107,7 @@
   base::FilePath local_path;
   error = FILE_ERROR_FAILED;
   cache()->GetFileOnUIThread(
-      src_entry.resource_id(), src_entry.file_specific_info().md5(),
+      src_entry.resource_id(),
       google_apis::test_util::CreateCopyResultCallback(&error, &local_path));
   test_util::RunBlockingPoolTask();
   ASSERT_EQ(FILE_ERROR_OK, error);
diff --git a/chrome/browser/chromeos/drive/file_system/update_operation.cc b/chrome/browser/chromeos/drive/file_system/update_operation.cc
index 7bc4255..324fcda 100644
--- a/chrome/browser/chromeos/drive/file_system/update_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/update_operation.cc
@@ -40,8 +40,7 @@
   if (drive_file_path->empty())
     return FILE_ERROR_NOT_FOUND;
 
-  error = cache->GetFile(
-      resource_id, entry->file_specific_info().md5(), cache_file_path);
+  error = cache->GetFile(resource_id, cache_file_path);
   if (error != FILE_ERROR_OK)
     return error;
 
diff --git a/chrome/browser/chromeos/drive/file_system_unittest.cc b/chrome/browser/chromeos/drive/file_system_unittest.cc
index 95bfd1b..68d79c2 100644
--- a/chrome/browser/chromeos/drive/file_system_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system_unittest.cc
@@ -772,8 +772,7 @@
   EXPECT_TRUE(cache_entry.is_dirty());
 
   base::FilePath cache_file_path;
-  EXPECT_EQ(FILE_ERROR_OK,
-            cache_->GetFile(file_resource_id, md5, &cache_file_path));
+  EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(file_resource_id, &cache_file_path));
   EXPECT_EQ(cache_file_path, opened_file_path);
 
   // Write a new content.
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.cc b/chrome/browser/chromeos/drive/resource_metadata_storage.cc
index 6f7c74d..56a6bc9 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.cc
@@ -121,6 +121,28 @@
   return entry_;
 }
 
+bool ResourceMetadataStorage::Iterator::GetCacheEntry(
+    FileCacheEntry* cache_entry) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!IsAtEnd());
+
+  // Try to seek to the cache entry.
+  std::string current_key = it_->key().ToString();
+  std::string cache_entry_key = GetCacheEntryKey(current_key);
+  it_->Seek(leveldb::Slice(cache_entry_key));
+
+  bool success = it_->Valid() &&
+      it_->key().compare(cache_entry_key) == 0 &&
+      cache_entry->ParseFromArray(it_->value().data(), it_->value().size());
+
+  // Seek back to the original position.
+  it_->Seek(leveldb::Slice(current_key));
+  DCHECK(!IsAtEnd());
+  DCHECK_EQ(current_key, it_->key().ToString());
+
+  return success;
+}
+
 void ResourceMetadataStorage::Iterator::Advance() {
   base::ThreadRestrictions::AssertIOAllowed();
   DCHECK(!IsAtEnd());
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.h b/chrome/browser/chromeos/drive/resource_metadata_storage.h
index adac420..0ad61ef 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.h
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.h
@@ -51,6 +51,9 @@
     // Returns the entry currently pointed by this object.
     const ResourceEntry& Get() const;
 
+    // Gets the cache entry which corresponds to |entry_| if available.
+    bool GetCacheEntry(FileCacheEntry* cache_entry);
+
     // Advances to the next entry.
     void Advance();
 
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc b/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
index a1f31ad..667f920 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
@@ -151,24 +151,39 @@
   for (size_t i = 0; i < entries.size(); ++i)
     EXPECT_TRUE(storage_->PutEntry(entries[i]));
 
-  // Insert some dummy cache entries.
-  FileCacheEntry cache_entry;
-  EXPECT_TRUE(storage_->PutCacheEntry(entries[0].resource_id(), cache_entry));
-  EXPECT_TRUE(storage_->PutCacheEntry(entries[1].resource_id(), cache_entry));
+  // Insert some cache entries.
+  std::map<std::string, FileCacheEntry> cache_entries;
+  cache_entries[entries[0].resource_id()].set_md5("aaaaaa");
+  cache_entries[entries[1].resource_id()].set_md5("bbbbbb");
+  for (std::map<std::string, FileCacheEntry>::iterator it =
+           cache_entries.begin(); it != cache_entries.end(); ++it)
+    EXPECT_TRUE(storage_->PutCacheEntry(it->first, it->second));
 
   // Iterate and check the result.
-  std::map<std::string, ResourceEntry> result;
+  std::map<std::string, ResourceEntry> found_entries;
+  std::map<std::string, FileCacheEntry> found_cache_entries;
   scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator();
   ASSERT_TRUE(it);
   for (; !it->IsAtEnd(); it->Advance()) {
     const ResourceEntry& entry = it->Get();
-    result[entry.resource_id()] = entry;
+    found_entries[entry.resource_id()] = entry;
+
+    FileCacheEntry cache_entry;
+    if (it->GetCacheEntry(&cache_entry))
+      found_cache_entries[entry.resource_id()] = cache_entry;
   }
   EXPECT_FALSE(it->HasError());
 
-  EXPECT_EQ(entries.size(), result.size());
+  EXPECT_EQ(entries.size(), found_entries.size());
   for (size_t i = 0; i < entries.size(); ++i)
-    EXPECT_EQ(1U, result.count(entries[i].resource_id()));
+    EXPECT_EQ(1U, found_entries.count(entries[i].resource_id()));
+
+  EXPECT_EQ(cache_entries.size(), found_cache_entries.size());
+  for (std::map<std::string, FileCacheEntry>::iterator it =
+           cache_entries.begin(); it != cache_entries.end(); ++it) {
+    ASSERT_EQ(1U, found_cache_entries.count(it->first));
+    EXPECT_EQ(it->second.md5(), found_cache_entries[it->first].md5());
+  }
 }
 
 TEST_F(ResourceMetadataStorageTest, PutCacheEntry) {
diff --git a/chrome/browser/chromeos/drive/search_metadata.cc b/chrome/browser/chromeos/drive/search_metadata.cc
index 9e5b30c..a167830 100644
--- a/chrome/browser/chromeos/drive/search_metadata.cc
+++ b/chrome/browser/chromeos/drive/search_metadata.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/i18n/string_search.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/drive/file_cache.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/escape.h"
@@ -83,7 +82,7 @@
 // SEARCH_METADATA_OFFLINE is requested, only hosted documents and cached files
 // match with the query. This option can not be used with other options.
 bool IsEligibleEntry(const ResourceEntry& entry,
-                     internal::FileCache* cache,
+                     ResourceMetadata::Iterator* it,
                      int options) {
   if ((options & SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS) &&
       entry.file_specific_info().is_hosted_document())
@@ -100,9 +99,7 @@
     if (entry.file_specific_info().is_hosted_document())
       return true;
     FileCacheEntry cache_entry;
-    cache->GetCacheEntry(entry.resource_id(),
-                         std::string(),
-                         &cache_entry);
+    it->GetCacheEntry(&cache_entry);
     return cache_entry.is_present();
   }
 
@@ -121,15 +118,16 @@
 // the query.
 void MaybeAddEntryToResult(
     ResourceMetadata* resource_metadata,
-    FileCache* cache,
+    ResourceMetadata::Iterator* it,
     base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents* query,
     int options,
     size_t at_most_num_matches,
     ScopedPriorityQueue<MetadataSearchResult,
-                        MetadataSearchResultComparator>* result_candidates,
-    const ResourceEntry& entry) {
+                        MetadataSearchResultComparator>* result_candidates) {
   DCHECK_GE(at_most_num_matches, result_candidates->size());
 
+  const ResourceEntry& entry = it->Get();
+
   // If the candidate set is already full, and this |entry| is old, do nothing.
   // We perform this check first in order to avoid the costly find-and-highlight
   // or FilePath lookup as much as possible.
@@ -141,7 +139,7 @@
   // |options| and matches the query. The base name of the entry must
   // contain |query| to match the query.
   std::string highlighted;
-  if (!IsEligibleEntry(entry, cache, options) ||
+  if (!IsEligibleEntry(entry, it, options) ||
       (query && !FindAndHighlight(entry.base_name(), query, &highlighted)))
     return;
 
@@ -153,7 +151,6 @@
 
 // Implements SearchMetadata().
 FileError SearchMetadataOnBlockingPool(ResourceMetadata* resource_metadata,
-                                       FileCache* cache,
                                        const std::string& query_text,
                                        int options,
                                        int at_most_num_matches,
@@ -168,10 +165,10 @@
   // Iterate over entries.
   scoped_ptr<ResourceMetadata::Iterator> it = resource_metadata->GetIterator();
   for (; !it->IsAtEnd(); it->Advance()) {
-    MaybeAddEntryToResult(resource_metadata, cache,
+    MaybeAddEntryToResult(resource_metadata, it.get(),
                           query_text.empty() ? NULL : &query,
                           options,
-                          at_most_num_matches, &result_candidates, it->Get());
+                          at_most_num_matches, &result_candidates);
   }
 
   // Prepare the result.
@@ -207,7 +204,6 @@
 void SearchMetadata(
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
     ResourceMetadata* resource_metadata,
-    FileCache* cache,
     const std::string& query,
     int options,
     int at_most_num_matches,
@@ -223,7 +219,6 @@
                                    FROM_HERE,
                                    base::Bind(&SearchMetadataOnBlockingPool,
                                               resource_metadata,
-                                              cache,
                                               query,
                                               options,
                                               at_most_num_matches,
diff --git a/chrome/browser/chromeos/drive/search_metadata.h b/chrome/browser/chromeos/drive/search_metadata.h
index d4e0e6f..e4f140d 100644
--- a/chrome/browser/chromeos/drive/search_metadata.h
+++ b/chrome/browser/chromeos/drive/search_metadata.h
@@ -18,7 +18,6 @@
 namespace drive {
 namespace internal {
 
-class FileCache;
 class ResourceMetadata;
 
 // Searches the local resource metadata, and returns the entries
@@ -31,7 +30,6 @@
 void SearchMetadata(
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
     ResourceMetadata* resource_metadata,
-    FileCache* cache,
     const std::string& query,
     int search_options,
     int at_most_num_matches,
diff --git a/chrome/browser/chromeos/drive/search_metadata_unittest.cc b/chrome/browser/chromeos/drive/search_metadata_unittest.cc
index 1c9c3d4..9e1ff21 100644
--- a/chrome/browser/chromeos/drive/search_metadata_unittest.cc
+++ b/chrome/browser/chromeos/drive/search_metadata_unittest.cc
@@ -218,7 +218,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "NonExistent",
                  SEARCH_METADATA_ALL,
                  kDefaultAtMostNumMatches,
@@ -236,7 +235,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "SubDirectory File 1.txt",
                  SEARCH_METADATA_ALL,
                  kDefaultAtMostNumMatches,
@@ -259,7 +257,6 @@
   // The query is all in lower case.
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "subdirectory file 1.txt",
                  SEARCH_METADATA_ALL,
                  kDefaultAtMostNumMatches,
@@ -279,7 +276,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "SubDir",
                  SEARCH_METADATA_ALL,
                  kDefaultAtMostNumMatches,
@@ -309,7 +305,6 @@
   // returned.
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "SubDir",
                  SEARCH_METADATA_ALL,
                  1,  // at_most_num_matches
@@ -329,7 +324,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "Directory 1",
                  SEARCH_METADATA_ALL,
                  kDefaultAtMostNumMatches,
@@ -348,7 +342,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "Document",
                  SEARCH_METADATA_ALL,
                  kDefaultAtMostNumMatches,
@@ -369,7 +362,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "Document",
                  SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS,
                  kDefaultAtMostNumMatches,
@@ -387,7 +379,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "",
                  SEARCH_METADATA_SHARED_WITH_ME,
                  kDefaultAtMostNumMatches,
@@ -407,7 +398,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "excludeDir-test",
                  SEARCH_METADATA_ALL,
                  kDefaultAtMostNumMatches,
@@ -431,7 +421,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "excludeDir-test",
                  SEARCH_METADATA_EXCLUDE_DIRECTORIES,
                  kDefaultAtMostNumMatches,
@@ -457,7 +446,6 @@
     const std::string query = kQueries[i];
     SearchMetadata(base::MessageLoopProxy::current(),
                    resource_metadata_.get(),
-                   cache_.get(),
                    query,
                    SEARCH_METADATA_ALL,
                    kDefaultAtMostNumMatches,
@@ -485,7 +473,6 @@
 
   SearchMetadata(base::MessageLoopProxy::current(),
                  resource_metadata_.get(),
-                 cache_.get(),
                  "",
                  SEARCH_METADATA_OFFLINE,
                  kDefaultAtMostNumMatches,
diff --git a/chrome/browser/chromeos/drive/sync_client_unittest.cc b/chrome/browser/chromeos/drive/sync_client_unittest.cc
index c209643..6c0c8d6 100644
--- a/chrome/browser/chromeos/drive/sync_client_unittest.cc
+++ b/chrome/browser/chromeos/drive/sync_client_unittest.cc
@@ -293,13 +293,13 @@
   base::FilePath cache_file;
   std::string content;
   EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(resource_ids_["fetched"],
-                                           std::string(), &cache_file));
+                                           &cache_file));
   EXPECT_TRUE(file_util::ReadFileToString(cache_file, &content));
   EXPECT_EQ(kRemoteContent, content);
   content.clear();
 
   EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(resource_ids_["dirty"],
-                                           std::string(), &cache_file));
+                                           &cache_file));
   EXPECT_TRUE(file_util::ReadFileToString(cache_file, &content));
   EXPECT_EQ(kLocalContent, content);
 }
diff --git a/chrome/browser/chromeos/extensions/external_cache.cc b/chrome/browser/chromeos/extensions/external_cache.cc
new file mode 100644
index 0000000..3e19c65
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/external_cache.cc
@@ -0,0 +1,440 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/extensions/external_cache.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/file_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/location.h"
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/external_provider_impl.h"
+#include "chrome/browser/extensions/updater/extension_downloader.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+
+namespace chromeos {
+
+namespace {
+
+// File name extension for CRX files (not case sensitive).
+const char kCRXFileExtension[] = ".crx";
+
+}  // namespace
+
+ExternalCache::ExternalCache(const std::string& cache_dir,
+                             net::URLRequestContextGetter* request_context,
+                             Delegate* delegate)
+    : cache_dir_(cache_dir),
+      request_context_(request_context),
+      delegate_(delegate),
+      cached_extensions_(new base::DictionaryValue()),
+      weak_ptr_factory_(this),
+      worker_pool_token_(
+          content::BrowserThread::GetBlockingPool()->GetSequenceToken()) {
+  notification_registrar_.Add(
+      this,
+      chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
+      content::NotificationService::AllBrowserContextsAndSources());
+}
+
+ExternalCache::~ExternalCache() {
+}
+
+void ExternalCache::UpdateExtensionsList(
+    scoped_ptr<base::DictionaryValue> prefs) {
+  extensions_ = prefs.Pass();
+  CheckCacheNow();
+}
+
+void ExternalCache::OnDamagedFileDetected(const base::FilePath& path) {
+  for (base::DictionaryValue::Iterator it(*cached_extensions_.get());
+       !it.IsAtEnd(); it.Advance()) {
+    const base::DictionaryValue* entry = NULL;
+    if (it.value().GetAsDictionary(&entry)) {
+      NOTREACHED() << "ExternalCache found bad entry with type "
+                   << it.value().GetType();
+      continue;
+    }
+
+    std::string external_crx;
+    if (entry->GetString(extensions::ExternalProviderImpl::kExternalCrx,
+                         &external_crx) &&
+        external_crx == path.value()) {
+
+      LOG(ERROR) << "ExternalCache extension at " << path.value()
+                 << " failed to install, deleting it.";
+      cached_extensions_->Remove(it.key(), NULL);
+      UpdateExtensionLoader();
+
+      // The file will be downloaded again on the next restart.
+      content::BrowserThread::PostTask(
+          content::BrowserThread::FILE, FROM_HERE,
+          base::Bind(base::IgnoreResult(base::DeleteFile), path, true));
+
+      // Don't try to DownloadMissingExtensions() from here,
+      // since it can cause a fail/retry loop.
+      return;
+    }
+  }
+  LOG(ERROR) << "ExternalCache cannot find external_crx " << path.value();
+}
+
+void ExternalCache::Observe(int type,
+                            const content::NotificationSource& source,
+                            const content::NotificationDetails& details) {
+  switch (type) {
+    case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
+      extensions::CrxInstaller* installer =
+          content::Source<extensions::CrxInstaller>(source).ptr();
+      OnDamagedFileDetected(installer->source_file());
+      break;
+    }
+
+    default:
+      NOTREACHED();
+  }
+}
+
+void ExternalCache::OnExtensionDownloadFailed(
+    const std::string& id,
+    extensions::ExtensionDownloaderDelegate::Error error,
+    const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
+    const std::set<int>& request_ids) {
+  if (error == NO_UPDATE_AVAILABLE) {
+    if (!cached_extensions_->HasKey(id)) {
+      LOG(ERROR) << "ExternalCache extension " << id
+                 << " not found on update server";
+    }
+  } else {
+    LOG(ERROR) << "ExternalCache failed to download extension " << id
+               << ", error " << error;
+  }
+}
+
+void ExternalCache::OnExtensionDownloadFinished(
+    const std::string& id,
+    const base::FilePath& path,
+    const GURL& download_url,
+    const std::string& version,
+    const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
+    const std::set<int>& request_ids) {
+  // The explicit copy ctors are to make sure that Bind() binds a copy and not
+  // a reference to the arguments.
+  PostBlockingTask(FROM_HERE,
+                   base::Bind(&ExternalCache::BlockingInstallCacheEntry,
+                              weak_ptr_factory_.GetWeakPtr(),
+                              std::string(cache_dir_),
+                              std::string(id),
+                              base::FilePath(path),
+                              std::string(version)));
+}
+
+void ExternalCache::OnBlacklistDownloadFinished(
+    const std::string& data,
+    const std::string& package_hash,
+    const std::string& version,
+    const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
+    const std::set<int>& request_ids) {
+  NOTREACHED();
+}
+
+bool ExternalCache::IsExtensionPending(const std::string& id) {
+  // Pending means that there is no installed version yet.
+  return extensions_->HasKey(id) && !cached_extensions_->HasKey(id);
+}
+
+bool ExternalCache::GetExtensionExistingVersion(const std::string& id,
+                                                std::string* version) {
+  DictionaryValue* extension_dictionary = NULL;
+  if (cached_extensions_->GetDictionary(id, &extension_dictionary)) {
+    return extension_dictionary->GetString(
+        extensions::ExternalProviderImpl::kExternalVersion,
+        version);
+  }
+  return false;
+}
+
+void ExternalCache::CheckCacheNow() {
+  scoped_ptr<DictionaryValue> prefs(extensions_->DeepCopy());
+  PostBlockingTask(FROM_HERE,
+                   base::Bind(&ExternalCache::BlockingCheckCache,
+                              weak_ptr_factory_.GetWeakPtr(),
+                              std::string(cache_dir_),
+                              base::Passed(&prefs)));
+}
+
+void ExternalCache::UpdateExtensionLoader() {
+  VLOG(1) << "Notify ExternalCache delegate about cache update";
+  if (delegate_)
+    delegate_->OnExtensionListsUpdated(cached_extensions_.get());
+}
+
+// static
+void ExternalCache::BlockingCheckCache(
+    base::WeakPtr<ExternalCache> external_cache,
+    const std::string& cache_dir,
+    scoped_ptr<base::DictionaryValue> prefs) {
+  BlockingCheckCacheInternal(cache_dir, prefs.get());
+  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+                          base::Bind(&ExternalCache::OnCacheUpdated,
+                                     external_cache,
+                                     base::Passed(&prefs)));
+}
+
+// static
+void ExternalCache::BlockingCheckCacheInternal(const std::string& cache_dir,
+                                               base::DictionaryValue* prefs) {
+  // Start by verifying that the cache dir exists.
+  base::FilePath dir(cache_dir);
+  if (!base::DirectoryExists(dir)) {
+    // Create it now.
+    if (!file_util::CreateDirectory(dir)) {
+      LOG(ERROR) << "Failed to create ExternalCache directory at "
+                 << dir.value();
+
+      // Nothing else to do. Cache won't be used.
+      return;
+    }
+  }
+
+  // Enumerate all the files in the cache |dir|, including directories
+  // and symlinks. Each unrecognized file will be erased.
+  int types = base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES |
+      base::FileEnumerator::SHOW_SYM_LINKS;
+  base::FileEnumerator enumerator(dir, false /* recursive */, types);
+  for (base::FilePath path = enumerator.Next();
+       !path.empty(); path = enumerator.Next()) {
+    base::FileEnumerator::FileInfo info = enumerator.GetInfo();
+    std::string basename = path.BaseName().value();
+
+    if (info.IsDirectory() || file_util::IsLink(info.GetName())) {
+      LOG(ERROR) << "Erasing bad file in ExternalCache directory: " << basename;
+      base::DeleteFile(path, true /* recursive */);
+      continue;
+    }
+
+    // crx files in the cache are named <extension-id>-<version>.crx.
+    std::string id;
+    std::string version;
+    if (EndsWith(basename, kCRXFileExtension, false /* case-sensitive */)) {
+      size_t n = basename.find('-');
+      if (n != std::string::npos && n + 1 < basename.size() - 4) {
+        id = basename.substr(0, n);
+        // Size of |version| = total size - "<id>" - "-" - ".crx"
+        version = basename.substr(n + 1, basename.size() - 5 - id.size());
+      }
+    }
+
+    base::DictionaryValue* entry = NULL;
+    if (!extensions::Extension::IdIsValid(id)) {
+      LOG(ERROR) << "Bad extension id in ExternalCache: " << id;
+      id.clear();
+    } else if (!prefs->GetDictionary(id, &entry)) {
+      LOG(WARNING) << basename << " is in the cache but is not configured by "
+                   << "the ExternalCache source, and will be erased.";
+      id.clear();
+    }
+
+    if (!Version(version).IsValid()) {
+      LOG(ERROR) << "Bad extension version in ExternalCache: " << version;
+      version.clear();
+    }
+
+    if (id.empty() || version.empty()) {
+      LOG(ERROR) << "Invalid file in ExternalCache, erasing: " << basename;
+      base::DeleteFile(path, true /* recursive */);
+      continue;
+    }
+
+    // Enforce a lower-case id.
+    id = StringToLowerASCII(id);
+
+    std::string update_url;
+    std::string prev_version_string;
+    std::string prev_crx;
+    if (entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
+                         &update_url)) {
+      VLOG(1) << "ExternalCache found cached version " << version
+              << " for extension id: " << id;
+      entry->Remove(extensions::ExternalProviderImpl::kExternalUpdateUrl, NULL);
+      entry->SetString(extensions::ExternalProviderImpl::kExternalVersion,
+                       version);
+      entry->SetString(extensions::ExternalProviderImpl::kExternalCrx,
+                        path.value());
+      if (extension_urls::IsWebstoreUpdateUrl(GURL(update_url))) {
+        entry->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore,
+                         true);
+      }
+    } else if (
+        entry->GetString(extensions::ExternalProviderImpl::kExternalVersion,
+                         &prev_version_string) &&
+        entry->GetString(extensions::ExternalProviderImpl::kExternalCrx,
+                         &prev_crx)) {
+      LOG(ERROR) << "Found two ExternalCache files for the same extension, "
+                    "will erase the oldest version";
+      Version prev_version(prev_version_string);
+      Version curr_version(version);
+      DCHECK(prev_version.IsValid());
+      DCHECK(curr_version.IsValid());
+      if (prev_version.CompareTo(curr_version) < 0) {
+        base::DeleteFile(base::FilePath(prev_crx), true /* recursive */);
+        entry->SetString(extensions::ExternalProviderImpl::kExternalCrx,
+                         path.value());
+      } else {
+        base::DeleteFile(path, true /* recursive */);
+      }
+    } else {
+      NOTREACHED() << "ExternalCache found bad entry for extension id: " << id
+                   << " file path: " << path.value();
+    }
+  }
+}
+
+void ExternalCache::OnCacheUpdated(scoped_ptr<base::DictionaryValue> prefs) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  // If request_context_ is missing we can't download anything.
+  if (!downloader_ && request_context_) {
+    downloader_.reset(
+        new extensions::ExtensionDownloader(this, request_context_));
+  }
+
+  cached_extensions_->Clear();
+  for (base::DictionaryValue::Iterator it(*extensions_.get());
+       !it.IsAtEnd(); it.Advance()) {
+    const base::DictionaryValue* entry = NULL;
+    if (!it.value().GetAsDictionary(&entry)) {
+      LOG(ERROR) << "ExternalCache found bad entry with type "
+                 << it.value().GetType();
+      continue;
+    }
+
+    // Check for updates for all extensions configured except for extensions
+    // marked as keep_if_present.
+    std::string update_url;
+    if (downloader_ &&
+        !entry->HasKey(extensions::ExternalProviderImpl::kKeepIfPresent) &&
+        entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
+                         &update_url)) {
+      downloader_->AddPendingExtension(it.key(), GURL(update_url), 0);
+    }
+
+    base::DictionaryValue* cached_entry = NULL;
+    if (prefs->GetDictionary(it.key(), &cached_entry)) {
+      std::string crx_path;
+      if (!downloader_ ||
+          cached_entry->GetString(
+              extensions::ExternalProviderImpl::kExternalCrx, &crx_path) ||
+          cached_entry->HasKey(
+              extensions::ExternalProviderImpl::kKeepIfPresent)) {
+        base::Value* value = NULL;
+        prefs->Remove(it.key(), &value);
+        cached_extensions_->Set(it.key(), value);
+      }
+    }
+  }
+  if (downloader_)
+    downloader_->StartAllPending();
+
+  VLOG(1) << "Updated ExternalCache, there are "
+          << cached_extensions_->size() << " extensions cached";
+
+  UpdateExtensionLoader();
+}
+
+// static
+void ExternalCache::BlockingInstallCacheEntry(
+    base::WeakPtr<ExternalCache> external_cache,
+    const std::string& app_cache_dir,
+    const std::string& id,
+    const base::FilePath& path,
+    const std::string& version) {
+  Version version_validator(version);
+  if (!version_validator.IsValid()) {
+    LOG(ERROR) << "ExternalCache downloaded extension " << id << " but got bad "
+               << "version: " << version;
+    base::DeleteFile(path, true /* recursive */);
+    return;
+  }
+
+  std::string basename = id + "-" + version + kCRXFileExtension;
+  base::FilePath cache_dir(app_cache_dir);
+  base::FilePath cached_crx_path = cache_dir.Append(basename);
+
+  if (base::PathExists(cached_crx_path)) {
+    LOG(WARNING) << "AppPack downloaded a crx whose filename will overwrite "
+                 << "an existing cached crx.";
+    base::DeleteFile(cached_crx_path, true /* recursive */);
+  }
+
+  if (!base::DirectoryExists(cache_dir)) {
+    LOG(ERROR) << "AppPack cache directory does not exist, creating now: "
+               << cache_dir.value();
+    if (!file_util::CreateDirectory(cache_dir)) {
+      LOG(ERROR) << "Failed to create the AppPack cache dir!";
+      base::DeleteFile(path, true /* recursive */);
+      return;
+    }
+  }
+
+  if (!base::Move(path, cached_crx_path)) {
+    LOG(ERROR) << "Failed to move AppPack crx from " << path.value()
+               << " to " << cached_crx_path.value();
+    base::DeleteFile(path, true /* recursive */);
+    return;
+  }
+
+  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+                          base::Bind(&ExternalCache::OnCacheEntryInstalled,
+                                     external_cache,
+                                     std::string(id),
+                                     cached_crx_path.value(),
+                                     std::string(version)));
+}
+
+void ExternalCache::OnCacheEntryInstalled(const std::string& id,
+                                          const std::string& path,
+                                          const std::string& version) {
+  VLOG(1) << "AppPack installed a new extension in the cache: " << path;
+
+  base::DictionaryValue* entry = NULL;
+  std::string update_url;
+  if (!extensions_->GetDictionary(id, &entry) ||
+      !entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
+                        &update_url)) {
+    LOG(ERROR) << "ExternalCache cannot find entry for extension " << id;
+    return;
+  }
+
+  // Copy entry to don't modify it inside extensions_.
+  entry = entry->DeepCopy();
+  entry->Remove(extensions::ExternalProviderImpl::kExternalUpdateUrl, NULL);
+  entry->SetString(extensions::ExternalProviderImpl::kExternalVersion, version);
+  entry->SetString(extensions::ExternalProviderImpl::kExternalCrx, path);
+  if (extension_urls::IsWebstoreUpdateUrl(GURL(update_url)))
+    entry->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore, true);
+
+  cached_extensions_->Set(id, entry);
+  UpdateExtensionLoader();
+}
+
+void ExternalCache::PostBlockingTask(const tracked_objects::Location& location,
+                                     const base::Closure& task) {
+  content::BrowserThread::GetBlockingPool()->
+      PostSequencedWorkerTaskWithShutdownBehavior(
+          worker_pool_token_, location, task,
+          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/external_cache.h b/chrome/browser/chromeos/extensions/external_cache.h
new file mode 100644
index 0000000..e9415b5
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/external_cache.h
@@ -0,0 +1,172 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_CACHE_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_CACHE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/extensions/updater/extension_downloader_delegate.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace extensions {
+class ExtensionDownloader;
+}
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace tracked_objects {
+class Location;
+}
+
+namespace chromeos {
+
+// The ExternalCache manages cache for external extensions.
+class ExternalCache : public content::NotificationObserver,
+                      public extensions::ExtensionDownloaderDelegate {
+ public:
+  class Delegate {
+   public:
+    virtual ~Delegate() {}
+    // Caller owns |prefs|.
+    virtual void OnExtensionListsUpdated(
+        const base::DictionaryValue* prefs) = 0;
+  };
+
+  // The |request_context| is used for the update checks.
+  ExternalCache(const std::string& cache_dir,
+                net::URLRequestContextGetter* request_context,
+                Delegate* delegate);
+  virtual ~ExternalCache();
+
+  // Update list of extensions in cache and force update check for them.
+  // ExternalCache gets ownership of |prefs|.
+  void UpdateExtensionsList(scoped_ptr<base::DictionaryValue> prefs);
+
+  // If a user of one of the ExternalCache's extensions detects that
+  // the extension is damaged then this method can be used to remove it from
+  // the cache and retry to download it after a restart.
+  void OnDamagedFileDetected(const base::FilePath& path);
+
+ protected:
+  // Implementation of content::NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // Implementation of ExtensionDownloaderDelegate:
+  virtual void OnExtensionDownloadFailed(
+      const std::string& id,
+      Error error,
+      const PingResult& ping_result,
+      const std::set<int>& request_ids) OVERRIDE;
+
+  virtual void OnExtensionDownloadFinished(
+      const std::string& id,
+      const base::FilePath& path,
+      const GURL& download_url,
+      const std::string& version,
+      const PingResult& ping_result,
+      const std::set<int>& request_ids) OVERRIDE;
+
+  virtual void OnBlacklistDownloadFinished(
+      const std::string& data,
+      const std::string& package_hash,
+      const std::string& version,
+      const PingResult& ping_result,
+      const std::set<int>& request_ids) OVERRIDE;
+
+  virtual bool IsExtensionPending(const std::string& id) OVERRIDE;
+
+  virtual bool GetExtensionExistingVersion(const std::string& id,
+                                           std::string* version) OVERRIDE;
+
+  // Starts a cache update check immediately.
+  void CheckCacheNow();
+
+  // Notifies the that the cache has been updated, providing
+  // extensions loader with an updated list of extensions.
+  void UpdateExtensionLoader();
+
+  // Performs a cache update check on the blocking pool. |external_cache| is
+  // used to reply in the UI thread. |prefs| contains the list extensions
+  // anything else is invalid, and should be removed from the cache.
+  // Ownership of |prefs| is transferred to this function.
+  static void BlockingCheckCache(
+      base::WeakPtr<ExternalCache> external_cache,
+      const std::string& app_cache_dir,
+      scoped_ptr<base::DictionaryValue> prefs);
+
+  // Helper for BlockingCheckCache(), updates |prefs|.
+  static void BlockingCheckCacheInternal(
+      const std::string& app_cache_dir,
+      base::DictionaryValue* prefs);
+
+  // Invoked when the cache has been updated. |prefs| contains all the currently
+  // valid crx files in the cache, ownerships is transfered to this function.
+  void OnCacheUpdated(scoped_ptr<base::DictionaryValue> prefs);
+
+  // Invoked to install the downloaded crx file at |path| in the cache.
+  static void BlockingInstallCacheEntry(
+      base::WeakPtr<ExternalCache> external_cache,
+      const std::string& app_cache_dir,
+      const std::string& id,
+      const base::FilePath& path,
+      const std::string& version);
+
+  // Invoked on the UI thread when a new entry has been installed in the cache.
+  void OnCacheEntryInstalled(const std::string& id,
+                             const std::string& path,
+                             const std::string& version);
+
+  // Helper to post blocking IO tasks to the blocking pool.
+  void PostBlockingTask(const tracked_objects::Location& from_here,
+                        const base::Closure& task);
+
+  // Path to the dir where apps cache is stored.
+  std::string cache_dir_;
+
+  // Request context used by the |downloader_|.
+  net::URLRequestContextGetter* request_context_;
+
+  // Delegate that would like to get notifications about cache updates.
+  Delegate* delegate_;
+
+  // This is the list of extensions currently configured.
+  scoped_ptr<base::DictionaryValue> extensions_;
+
+  // This contains extensions that are both currently configured
+  // and that have a valid crx in the cache.
+  scoped_ptr<base::DictionaryValue> cached_extensions_;
+
+  // Used to download the extensions and to check for updates.
+  scoped_ptr<extensions::ExtensionDownloader> downloader_;
+
+  base::WeakPtrFactory<ExternalCache> weak_ptr_factory_;
+
+  // Observes failures to install CRX files.
+  content::NotificationRegistrar notification_registrar_;
+
+  // Unique sequence token so that tasks posted by the ExternalCache are
+  // executed sequentially in the blocking pool.
+  base::SequencedWorkerPool::SequenceToken worker_pool_token_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalCache);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_CACHE_H_
diff --git a/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
new file mode 100644
index 0000000..cd02dae
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
@@ -0,0 +1,47 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/extensions/external_pref_cache_loader.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/singleton.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace chromeos {
+
+namespace {
+
+// Directory where the extensions are cached.
+const char kPreinstalledAppsCacheDir[] = "/var/cache/external_cache";
+
+}  // namespace
+
+ExternalPrefCacheLoader::ExternalPrefCacheLoader(int base_path_id,
+                                                 Options options)
+  : ExternalPrefLoader(base_path_id, options) {
+}
+
+ExternalPrefCacheLoader::~ExternalPrefCacheLoader() {
+}
+
+void ExternalPrefCacheLoader::OnExtensionListsUpdated(
+    const base::DictionaryValue* prefs) {
+  prefs_.reset(prefs->DeepCopy());
+  ExternalPrefLoader::LoadFinished();
+}
+
+void ExternalPrefCacheLoader::LoadFinished() {
+  if (!external_cache_.get()) {
+    external_cache_.reset(new ExternalCache(kPreinstalledAppsCacheDir,
+        g_browser_process->system_request_context(),
+        this));
+  }
+
+  external_cache_->UpdateExtensionsList(prefs_.Pass());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/external_pref_cache_loader.h b/chrome/browser/chromeos/extensions/external_pref_cache_loader.h
new file mode 100644
index 0000000..f886f85
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/external_pref_cache_loader.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_PREF_CACHE_LOADER_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_PREF_CACHE_LOADER_H_
+
+#include "chrome/browser/chromeos/extensions/external_cache.h"
+#include "chrome/browser/extensions/external_pref_loader.h"
+
+namespace chromeos {
+
+// A specialization of the ExternalPrefCacheLoader that caches crx files for
+// external extensions with update URL in common place for all users on the
+// machine.
+class ExternalPrefCacheLoader : public extensions::ExternalPrefLoader,
+                                public ExternalCache::Delegate {
+ public:
+  ExternalPrefCacheLoader(int base_path_id, Options options);
+
+  // Implementation of ExternalCache::Delegate:
+  virtual void OnExtensionListsUpdated(
+      const base::DictionaryValue* prefs) OVERRIDE;
+
+ protected:
+  virtual ~ExternalPrefCacheLoader();
+
+  virtual void LoadFinished() OVERRIDE;
+
+ private:
+  friend class base::RefCountedThreadSafe<ExternalLoader>;
+
+  scoped_ptr<ExternalCache> external_cache_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalPrefCacheLoader);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_PREF_CACHE_LOADER_H_
diff --git a/chrome/browser/chromeos/fileapi/remote_file_system_operation.cc b/chrome/browser/chromeos/fileapi/remote_file_system_operation.cc
deleted file mode 100644
index e51e568..0000000
--- a/chrome/browser/chromeos/fileapi/remote_file_system_operation.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/fileapi/remote_file_system_operation.h"
-
-#include "base/bind.h"
-#include "base/platform_file.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "net/url_request/url_request.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/file_writer_delegate.h"
-
-using fileapi::FileSystemURL;
-
-namespace chromeos {
-
-RemoteFileSystemOperation::RemoteFileSystemOperation(
-    scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy)
-      : remote_proxy_(remote_proxy),
-        pending_operation_(kOperationNone) {
-}
-
-RemoteFileSystemOperation::~RemoteFileSystemOperation() {
-}
-
-void RemoteFileSystemOperation::GetMetadata(const FileSystemURL& url,
-    const GetMetadataCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationGetMetadata));
-  remote_proxy_->GetFileInfo(url, callback);
-}
-
-void RemoteFileSystemOperation::DirectoryExists(const FileSystemURL& url,
-    const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationDirectoryExists));
-  remote_proxy_->GetFileInfo(url,
-      base::Bind(&RemoteFileSystemOperation::DidDirectoryExists,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::FileExists(const FileSystemURL& url,
-    const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationFileExists));
-  remote_proxy_->GetFileInfo(url,
-      base::Bind(base::Bind(&RemoteFileSystemOperation::DidFileExists,
-                            AsWeakPtr(), callback)));
-}
-
-void RemoteFileSystemOperation::ReadDirectory(const FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationReadDirectory));
-  remote_proxy_->ReadDirectory(url, callback);
-}
-
-void RemoteFileSystemOperation::Remove(const FileSystemURL& url, bool recursive,
-                                       const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationRemove));
-  remote_proxy_->Remove(url, recursive,
-      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
-                 AsWeakPtr(), callback));
-}
-
-
-void RemoteFileSystemOperation::CreateDirectory(
-    const FileSystemURL& url, bool exclusive, bool recursive,
-    const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationCreateDirectory));
-  remote_proxy_->CreateDirectory(url, exclusive, recursive,
-      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::CreateFile(const FileSystemURL& url,
-                                           bool exclusive,
-                                           const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationCreateFile));
-  remote_proxy_->CreateFile(url, exclusive,
-      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::Copy(const FileSystemURL& src_url,
-                                     const FileSystemURL& dest_url,
-                                     const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationCopy));
-
-  remote_proxy_->Copy(src_url, dest_url,
-      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::Move(const FileSystemURL& src_url,
-                                     const FileSystemURL& dest_url,
-                                     const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationMove));
-
-  remote_proxy_->Move(src_url, dest_url,
-      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::Write(
-    const FileSystemURL& url,
-    scoped_ptr<fileapi::FileWriterDelegate> writer_delegate,
-    scoped_ptr<net::URLRequest> blob_request,
-    const WriteCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationWrite));
-  file_writer_delegate_ = writer_delegate.Pass();
-  file_writer_delegate_->Start(
-      blob_request.Pass(),
-      base::Bind(&RemoteFileSystemOperation::DidWrite, AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::Truncate(const FileSystemURL& url,
-                                         int64 length,
-                                         const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationTruncate));
-
-  remote_proxy_->Truncate(url, length,
-      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::Cancel(const StatusCallback& cancel_callback) {
-  DCHECK(cancel_callback_.is_null());
-  cancel_callback_ = cancel_callback;
-
-  if (file_writer_delegate_) {
-    DCHECK_EQ(kOperationWrite, pending_operation_);
-    // This will call DidWrite() with ABORT status code.
-    file_writer_delegate_->Cancel();
-  } else {
-    // For truncate we have no way to cancel the inflight operation (for now).
-    // Let it just run and dispatch cancel callback later.
-    DCHECK_EQ(kOperationTruncate, pending_operation_);
-  }
-}
-
-void RemoteFileSystemOperation::TouchFile(const FileSystemURL& url,
-                                          const base::Time& last_access_time,
-                                          const base::Time& last_modified_time,
-                                          const StatusCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationTouchFile));
-  remote_proxy_->TouchFile(
-      url,
-      last_access_time,
-      last_modified_time,
-      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteFileSystemOperation::OpenFile(const FileSystemURL& url,
-                                         int file_flags,
-                                         base::ProcessHandle peer_handle,
-                                         const OpenFileCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationOpenFile));
-  remote_proxy_->OpenFile(
-      url,
-      file_flags,
-      peer_handle,
-      base::Bind(&RemoteFileSystemOperation::DidOpenFile,
-                 AsWeakPtr(), url, callback));
-}
-
-fileapi::LocalFileSystemOperation*
-RemoteFileSystemOperation::AsLocalFileSystemOperation() {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-void RemoteFileSystemOperation::CreateSnapshotFile(
-    const FileSystemURL& url,
-    const SnapshotFileCallback& callback) {
-  DCHECK(SetPendingOperationType(kOperationCreateSnapshotFile));
-  remote_proxy_->CreateSnapshotFile(url, callback);
-}
-
-bool RemoteFileSystemOperation::SetPendingOperationType(OperationType type) {
-  if (pending_operation_ != kOperationNone)
-    return false;
-  pending_operation_ = type;
-  return true;
-}
-
-void RemoteFileSystemOperation::DidDirectoryExists(
-    const StatusCallback& callback,
-    base::PlatformFileError rv,
-    const base::PlatformFileInfo& file_info) {
-  if (rv == base::PLATFORM_FILE_OK && !file_info.is_directory)
-    rv = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
-  callback.Run(rv);
-}
-
-void RemoteFileSystemOperation::DidFileExists(
-    const StatusCallback& callback,
-    base::PlatformFileError rv,
-    const base::PlatformFileInfo& file_info) {
-  if (rv == base::PLATFORM_FILE_OK && file_info.is_directory)
-    rv = base::PLATFORM_FILE_ERROR_NOT_A_FILE;
-  callback.Run(rv);
-}
-
-void RemoteFileSystemOperation::DidWrite(
-    const WriteCallback& write_callback,
-    base::PlatformFileError rv,
-    int64 bytes,
-    FileWriterDelegate::WriteProgressStatus write_status) {
-  bool complete = (write_status != FileWriterDelegate::SUCCESS_IO_PENDING);
-  StatusCallback cancel_callback = cancel_callback_;
-  write_callback.Run(rv, bytes, complete);
-  if (!cancel_callback.is_null())
-    cancel_callback.Run(base::PLATFORM_FILE_OK);
-}
-
-void RemoteFileSystemOperation::DidFinishFileOperation(
-    const StatusCallback& callback,
-    base::PlatformFileError rv) {
-  if (!cancel_callback_.is_null()) {
-    DCHECK_EQ(kOperationTruncate, pending_operation_);
-
-    StatusCallback cancel_callback = cancel_callback_;
-    callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
-    cancel_callback.Run(base::PLATFORM_FILE_OK);
-  } else {
-    callback.Run(rv);
-  }
-}
-
-void RemoteFileSystemOperation::DidOpenFile(
-    const fileapi::FileSystemURL& url,
-    const OpenFileCallback& callback,
-    base::PlatformFileError result,
-    base::PlatformFile file,
-    base::ProcessHandle peer_handle) {
-  callback.Run(
-      result, file,
-      base::Bind(&fileapi::RemoteFileSystemProxyInterface::NotifyCloseFile,
-                 remote_proxy_, url),
-      peer_handle);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/remote_file_system_operation.h b/chrome/browser/chromeos/fileapi/remote_file_system_operation.h
deleted file mode 100644
index a467368..0000000
--- a/chrome/browser/chromeos/fileapi/remote_file_system_operation.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
-#define CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
-
-#include "base/basictypes.h"
-#include "base/memory/weak_ptr.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_writer_delegate.h"
-#include "webkit/browser/fileapi/remote_file_system_proxy.h"
-
-namespace base {
-class Value;
-}
-
-namespace fileapi {
-class FileWriterDelegate;
-class LocalFileSystemOperation;
-}
-
-namespace chromeos {
-
-// FileSystemOperation implementation for local file systems.
-class RemoteFileSystemOperation
-    : public fileapi::FileSystemOperation,
-      public base::SupportsWeakPtr<RemoteFileSystemOperation> {
- public:
-  typedef fileapi::FileWriterDelegate FileWriterDelegate;
-
-  explicit RemoteFileSystemOperation(
-      scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy);
-
-  virtual ~RemoteFileSystemOperation();
-
-  // FileSystemOperation overrides.
-  virtual void CreateFile(const fileapi::FileSystemURL& url,
-                          bool exclusive,
-                          const StatusCallback& callback) OVERRIDE;
-  virtual void CreateDirectory(const fileapi::FileSystemURL& url,
-                               bool exclusive,
-                               bool recursive,
-                               const StatusCallback& callback) OVERRIDE;
-  virtual void Copy(const fileapi::FileSystemURL& src_url,
-                    const fileapi::FileSystemURL& dest_url,
-                    const StatusCallback& callback) OVERRIDE;
-  virtual void Move(const fileapi::FileSystemURL& src_url,
-                    const fileapi::FileSystemURL& dest_url,
-                    const StatusCallback& callback) OVERRIDE;
-  virtual void DirectoryExists(const fileapi::FileSystemURL& url,
-                               const StatusCallback& callback) OVERRIDE;
-  virtual void FileExists(const fileapi::FileSystemURL& url,
-                          const StatusCallback& callback) OVERRIDE;
-  virtual void GetMetadata(const fileapi::FileSystemURL& url,
-                           const GetMetadataCallback& callback) OVERRIDE;
-  virtual void ReadDirectory(const fileapi::FileSystemURL& url,
-                             const ReadDirectoryCallback& callback) OVERRIDE;
-  virtual void Remove(const fileapi::FileSystemURL& url, bool recursive,
-                      const StatusCallback& callback) OVERRIDE;
-  virtual void Write(const fileapi::FileSystemURL& url,
-                     scoped_ptr<fileapi::FileWriterDelegate> writer_delegate,
-                     scoped_ptr<net::URLRequest> blob_request,
-                     const WriteCallback& callback) OVERRIDE;
-  virtual void Truncate(const fileapi::FileSystemURL& url, int64 length,
-                        const StatusCallback& callback) OVERRIDE;
-  virtual void Cancel(const StatusCallback& cancel_callback) OVERRIDE;
-  virtual void TouchFile(const fileapi::FileSystemURL& url,
-                         const base::Time& last_access_time,
-                         const base::Time& last_modified_time,
-                         const StatusCallback& callback) OVERRIDE;
-  virtual void OpenFile(
-      const fileapi::FileSystemURL& url,
-      int file_flags,
-      base::ProcessHandle peer_handle,
-      const OpenFileCallback& callback) OVERRIDE;
-  virtual fileapi::LocalFileSystemOperation*
-      AsLocalFileSystemOperation() OVERRIDE;
-  virtual void CreateSnapshotFile(
-      const fileapi::FileSystemURL& url,
-      const SnapshotFileCallback& callback) OVERRIDE;
-
- private:
-  // Used only for internal assertions.
-  // Returns false if there's another inflight pending operation.
-  bool SetPendingOperationType(OperationType type);
-
-  // Generic callback that translates platform errors to WebKit error codes.
-  void DidDirectoryExists(const StatusCallback& callback,
-                          base::PlatformFileError rv,
-                          const base::PlatformFileInfo& file_info);
-  void DidFileExists(const StatusCallback& callback,
-                     base::PlatformFileError rv,
-                     const base::PlatformFileInfo& file_info);
-  void DidWrite(const WriteCallback& write_callback,
-                base::PlatformFileError result,
-                int64 bytes,
-                FileWriterDelegate::WriteProgressStatus write_status);
-  void DidFinishFileOperation(const StatusCallback& callback,
-                              base::PlatformFileError rv);
-  void DidOpenFile(
-      const fileapi::FileSystemURL& url,
-      const OpenFileCallback& callback,
-      base::PlatformFileError result,
-      base::PlatformFile file,
-      base::ProcessHandle peer_handle);
-
-  scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy_;
-  // A flag to make sure we call operation only once per instance.
-  OperationType pending_operation_;
-  scoped_ptr<fileapi::FileWriterDelegate> file_writer_delegate_;
-
-  StatusCallback cancel_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(RemoteFileSystemOperation);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
diff --git a/chrome/browser/chromeos/policy/app_pack_updater.h b/chrome/browser/chromeos/policy/app_pack_updater.h
index 390de7e..9f256b8 100644
--- a/chrome/browser/chromeos/policy/app_pack_updater.h
+++ b/chrome/browser/chromeos/policy/app_pack_updater.h
@@ -22,7 +22,6 @@
 class GURL;
 
 namespace extensions {
-class CrxInstaller;
 class ExtensionDownloader;
 class ExternalLoader;
 }
@@ -164,10 +163,6 @@
                              const std::string& path,
                              const std::string& version);
 
-  // Handles failure to install CRX files. The file is deleted if it came from
-  // the cache.
-  void OnCrxInstallFailed(extensions::CrxInstaller* installer);
-
   // Helper to post blocking IO tasks to the blocking pool.
   void PostBlockingTask(const tracked_objects::Location& from_here,
                         const base::Closure& task);
diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
index a7f7ed9..96f6f9d 100644
--- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
+++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
@@ -679,8 +679,10 @@
 
   virtual void ConnectToBluetoothDevice(const std::string& address) OVERRIDE {
     device::BluetoothDevice* device = bluetooth_adapter_->GetDevice(address);
-    if (!device || device->IsConnecting() || device->IsConnected())
+    if (!device || device->IsConnecting() ||
+        (device->IsConnected() && device->IsPaired())) {
       return;
+    }
     if (device->IsPaired() && !device->IsConnectable())
       return;
     if (device->IsPaired() || !device->IsPairable()) {
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
index 60ba329..feb1d8f 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
@@ -23,6 +23,7 @@
 const char kRoutesKeyName[] = "routes";
 const char kNetworkStatusKeyName[] = "network-status";
 const char kModemStatusKeyName[] = "modem-status";
+const char kWiMaxStatusKeyName[] = "wimax-status";
 const char kUserLogFileKeyName[] = "user_log_files";
 
 namespace chromeos {
@@ -53,6 +54,9 @@
   client->GetModemStatus(base::Bind(&DebugDaemonLogSource::OnGetModemStatus,
                                     weak_ptr_factory_.GetWeakPtr()));
   ++num_pending_requests_;
+  client->GetWiMaxStatus(base::Bind(&DebugDaemonLogSource::OnGetWiMaxStatus,
+                                    weak_ptr_factory_.GetWeakPtr()));
+  ++num_pending_requests_;
   client->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
                                 weak_ptr_factory_.GetWeakPtr()));
   ++num_pending_requests_;
@@ -94,6 +98,17 @@
   RequestCompleted();
 }
 
+void DebugDaemonLogSource::OnGetWiMaxStatus(bool succeeded,
+                                            const std::string& status) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  if (succeeded)
+    (*response_)[kWiMaxStatusKeyName] = status;
+  else
+    (*response_)[kWiMaxStatusKeyName] = kNotAvailable;
+  RequestCompleted();
+}
+
 void DebugDaemonLogSource::OnGetLogs(bool /* succeeded */,
                                      const KeyValueMap& logs) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
index aea030f..8d1626c 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
@@ -33,6 +33,7 @@
   void OnGetRoutes(bool succeeded, const std::vector<std::string>& routes);
   void OnGetNetworkStatus(bool succeeded, const std::string& status);
   void OnGetModemStatus(bool succeeded, const std::string& status);
+  void OnGetWiMaxStatus(bool succeeded, const std::string& status);
   void OnGetLogs(bool succeeded,
                  const KeyValueMap& logs);
   void OnGetUserLogFiles(bool succeeded,
diff --git a/chrome/browser/drive/drive_uploader.cc b/chrome/browser/drive/drive_uploader.cc
index 0d4866a..493a763 100644
--- a/chrome/browser/drive/drive_uploader.cc
+++ b/chrome/browser/drive/drive_uploader.cc
@@ -34,6 +34,15 @@
 
 namespace drive {
 
+namespace {
+// Upload data is split to multiple HTTP request each conveying kUploadChunkSize
+// bytes (except the request for uploading the last chunk of data).
+// The value must be a multiple of 512KB according to the spec of GData WAPI and
+// Drive API v2. It is set to a smaller value than 2^31 for working around
+// server side error (crbug.com/264089).
+const int64 kUploadChunkSize = (1LL << 30);  // 1GB
+}  // namespace
+
 // Structure containing current upload information of file, passed between
 // DriveServiceInterface methods and callbacks.
 struct DriveUploader::UploadFileInfo {
@@ -316,11 +325,15 @@
     return;
   }
 
+  // Limit the size of data uploaded per each request by kUploadChunkSize.
+  const int64 end_position = std::min(upload_file_info->content_length,
+                                      start_position + kUploadChunkSize);
+
   UploadFileInfo* info_ptr = upload_file_info.get();
   info_ptr->cancel_callback = drive_service_->ResumeUpload(
       info_ptr->upload_location,
       start_position,
-      info_ptr->content_length,
+      end_position,
       info_ptr->content_length,
       info_ptr->content_type,
       info_ptr->file_path,
diff --git a/chrome/browser/extensions/ad_view_browsertest.cc b/chrome/browser/extensions/ad_view_browsertest.cc
index 045293e..4982cb2 100644
--- a/chrome/browser/extensions/ad_view_browsertest.cc
+++ b/chrome/browser/extensions/ad_view_browsertest.cc
@@ -65,7 +65,15 @@
 
 // This test checks that <adview> attributes are also exposed as properties
 // (with the same name and value).
-IN_PROC_BROWSER_TEST_F(AdViewTest, PropertiesAreInSyncWithAttributes) {
+#if defined(OS_WIN)
+// Flaky on Win XP. (http://crbug.com/264362)
+#define MAYBE_PropertiesAreInSyncWithAttributes \
+    DISABLED_PropertiesAreInSyncWithAttributes
+#else
+#define MAYBE_PropertiesAreInSyncWithAttributes \
+    PropertiesAreInSyncWithAttributes
+#endif
+IN_PROC_BROWSER_TEST_F(AdViewTest, MAYBE_PropertiesAreInSyncWithAttributes) {
   ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 03d6613..7de85f4 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -808,11 +808,7 @@
   EXTENSION_FUNCTION_VALIDATE(params.get());
   const extensions::api::downloads::DownloadOptions& options = params->options;
   GURL download_url(options.url);
-  if (!download_url.is_valid() ||
-      (!download_url.SchemeIs("data") &&
-       download_url.GetOrigin() != GetExtension()->url().GetOrigin() &&
-       !extensions::PermissionsData::HasHostPermission(GetExtension(),
-                                                       download_url))) {
+  if (!download_url.is_valid()) {
     error_ = download_extension_errors::kInvalidURLError;
     return false;
   }
@@ -1109,7 +1105,9 @@
   EXTENSION_FUNCTION_VALIDATE(params.get());
   DownloadItem* download_item = GetDownload(
       profile(), include_incognito(), params->download_id);
-  if (!download_item || download_item->GetState() != DownloadItem::COMPLETE) {
+  if (!download_item || download_item->GetState() != DownloadItem::COMPLETE ||
+      !GetExtension()->HasAPIPermission(
+          extensions::APIPermission::kDownloadsOpen)) {
     error_ = download_extension_errors::kInvalidOperationError;
     return false;
   }
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc b/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
index 26450b6..93a40f2 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
@@ -1736,17 +1736,25 @@
     "http://",
     "#frag",
     "foo/bar.html#frag",
-    "javascript:document.write(\\\"hello\\\");",
-    "javascript:return false;",
-    "ftp://example.com/example.txt",
   };
 
   for (size_t index = 0; index < arraysize(kInvalidURLs); ++index) {
     EXPECT_STREQ(download_extension_errors::kInvalidURLError,
                   RunFunctionAndReturnError(new DownloadsDownloadFunction(),
                                             base::StringPrintf(
-        "[{\"url\": \"%s\"}]", kInvalidURLs[index])).c_str());
+        "[{\"url\": \"%s\"}]", kInvalidURLs[index])).c_str())
+      << kInvalidURLs[index];
   }
+
+  EXPECT_STREQ("net::ERR_ACCESS_DENIED", RunFunctionAndReturnError(
+      new DownloadsDownloadFunction(),
+      "[{\"url\": \"javascript:document.write(\\\"hello\\\");\"}]").c_str());
+  EXPECT_STREQ("net::ERR_ACCESS_DENIED", RunFunctionAndReturnError(
+      new DownloadsDownloadFunction(),
+      "[{\"url\": \"javascript:return false;\"}]").c_str());
+  EXPECT_STREQ("net::ERR_NOT_IMPLEMENTED", RunFunctionAndReturnError(
+      new DownloadsDownloadFunction(),
+      "[{\"url\": \"ftp://example.com/example.txt\"}]").c_str());
 }
 
 // TODO(benjhayden): Set up a test ftp server, add ftp://localhost* to
diff --git a/chrome/browser/chromeos/extensions/networking_private_api.h b/chrome/browser/extensions/api/networking_private/networking_private_api.h
similarity index 96%
rename from chrome/browser/chromeos/extensions/networking_private_api.h
rename to chrome/browser/extensions/api/networking_private/networking_private_api.h
index d7232a3..cab006d 100644
--- a/chrome/browser/chromeos/extensions/networking_private_api.h
+++ b/chrome/browser/extensions/api/networking_private/networking_private_api.h
@@ -1,12 +1,12 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 // These classes implement the chrome.networkingPrivate JavaScript extension
 // API.
 
-#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_API_H_
-#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_API_H_
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_API_H_
 
 #include <string>
 
@@ -250,4 +250,5 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateVerifyAndEncryptDataFunction);
 };
 
-#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_API_H_
+#endif  // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_API_H_
+
diff --git a/chrome/browser/chromeos/extensions/networking_private_api.cc b/chrome/browser/extensions/api/networking_private/networking_private_api_chromeos.cc
similarity index 98%
rename from chrome/browser/chromeos/extensions/networking_private_api.cc
rename to chrome/browser/extensions/api/networking_private/networking_private_api_chromeos.cc
index 9708b8d..cdaf357 100644
--- a/chrome/browser/chromeos/extensions/networking_private_api.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_api_chromeos.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/extensions/networking_private_api.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_api.h"
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_api_nonchromeos.cc b/chrome/browser/extensions/api/networking_private/networking_private_api_nonchromeos.cc
new file mode 100644
index 0000000..55beff7
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_private/networking_private_api_nonchromeos.cc
@@ -0,0 +1,435 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/networking_private/networking_private_api.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/event_names.h"
+#include "chrome/browser/extensions/event_router.h"
+#include "chrome/browser/extensions/extension_function_registry.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/api/networking_private.h"
+
+using extensions::event_names::kOnNetworkListChanged;
+using extensions::event_names::kOnNetworksChanged;
+using extensions::EventRouter;
+using extensions::ExtensionSystem;
+namespace api = extensions::api::networking_private;
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateGetPropertiesFunction
+
+
+const char kNetworkingPrivateProperties[] = "NetworkingPrivateProperties";
+
+struct NetworkingPrivatePropertiesData : base::SupportsUserData::Data {
+  explicit NetworkingPrivatePropertiesData(const base::DictionaryValue* prop) :
+    properties_(prop->DeepCopy()) { }
+  scoped_ptr<base::DictionaryValue> properties_;
+};
+
+NetworkingPrivateGetPropertiesFunction::
+  ~NetworkingPrivateGetPropertiesFunction() {
+}
+
+bool NetworkingPrivateGetPropertiesFunction::RunImpl() {
+  scoped_ptr<api::GetProperties::Params> params =
+      api::GetProperties::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  // If there are properties set by SetProperties function, use those.
+  NetworkingPrivatePropertiesData* stored_properties =
+    static_cast<NetworkingPrivatePropertiesData*> (
+        profile()->GetUserData(kNetworkingPrivateProperties));
+  if (stored_properties != NULL) {
+    SetResult(stored_properties->properties_.release());
+    SendResponse(true);
+    return true;
+  }
+
+  const std::string network_properties =
+    "{\"ConnectionState\":\"NotConnected\","
+     "\"GUID\":\"stub_wifi2\","
+     "\"Name\":\"wifi2_PSK\","
+     "\"Type\":\"WiFi\","
+     "\"WiFi\":{"
+       "\"Frequency\":5000,"
+       "\"FrequencyList\":[2400,5000],"
+       "\"SSID\":\"stub_wifi2\","
+       "\"Security\":\"WPA-PSK\","
+       "\"SignalStrength\":80}}";
+
+  if (params->network_guid == "nonexistent_path") {
+    error_ = "Error.DBusFailed";
+    SendResponse(false);
+  } else {
+    SetResult(base::JSONReader::Read(network_properties));
+    SendResponse(true);
+  }
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateGetManagedPropertiesFunction
+
+NetworkingPrivateGetManagedPropertiesFunction::
+  ~NetworkingPrivateGetManagedPropertiesFunction() {
+}
+
+bool NetworkingPrivateGetManagedPropertiesFunction::RunImpl() {
+  scoped_ptr<api::GetManagedProperties::Params> params =
+      api::GetManagedProperties::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  const std::string network_properties =
+      "{"
+      "  \"ConnectionState\": {"
+      "    \"Active\": \"NotConnected\","
+      "    \"Effective\": \"Unmanaged\""
+      "  },"
+      "  \"GUID\": \"stub_wifi2\","
+      "  \"Name\": {"
+      "    \"Active\": \"wifi2_PSK\","
+      "    \"Effective\": \"UserPolicy\","
+      "    \"UserPolicy\": \"My WiFi Network\""
+      "  },"
+      "  \"Type\": {"
+      "    \"Active\": \"WiFi\","
+      "    \"Effective\": \"UserPolicy\","
+      "    \"UserPolicy\": \"WiFi\""
+      "  },"
+      "  \"WiFi\": {"
+      "    \"AutoConnect\": {"
+      "      \"Active\": false,"
+      "      \"UserEditable\": true"
+      "    },"
+      "    \"Frequency\" : {"
+      "      \"Active\": 5000,"
+      "      \"Effective\": \"Unmanaged\""
+      "    },"
+      "    \"FrequencyList\" : {"
+      "      \"Active\": [2400, 5000],"
+      "      \"Effective\": \"Unmanaged\""
+      "    },"
+      "    \"Passphrase\": {"
+      "      \"Effective\": \"UserSetting\","
+      "      \"UserEditable\": true,"
+      "      \"UserSetting\": \"FAKE_CREDENTIAL_VPaJDV9x\""
+      "    },"
+      "    \"SSID\": {"
+      "      \"Active\": \"stub_wifi2\","
+      "      \"Effective\": \"UserPolicy\","
+      "      \"UserPolicy\": \"stub_wifi2\""
+      "    },"
+      "    \"Security\": {"
+      "      \"Active\": \"WPA-PSK\","
+      "      \"Effective\": \"UserPolicy\","
+      "      \"UserPolicy\": \"WPA-PSK\""
+      "    },"
+      "    \"SignalStrength\": {"
+      "      \"Active\": 80,"
+      "      \"Effective\": \"Unmanaged\""
+      "    }"
+      "  }"
+      "}";
+
+  SetResult(base::JSONReader::Read(network_properties));
+  SendResponse(true);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateGetStateFunction
+
+NetworkingPrivateGetStateFunction::
+  ~NetworkingPrivateGetStateFunction() {
+}
+
+bool NetworkingPrivateGetStateFunction::RunImpl() {
+  scoped_ptr<api::GetState::Params> params =
+      api::GetState::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  const std::string network_state =
+      "{"
+      "  \"ConnectionState\": \"NotConnected\","
+      "  \"GUID\": \"stub_wifi2\","
+      "  \"Name\": \"wifi2_PSK\","
+      "  \"Type\": \"WiFi\","
+      "  \"WiFi\": {"
+      "    \"AutoConnect\": false,"
+      "    \"FrequencyList\": [2400, 5000],"
+      "    \"Security\": \"WPA-PSK\","
+      "    \"SignalStrength\": 80"
+      "  }"
+      "}";
+  SetResult(base::JSONReader::Read(network_state));
+  SendResponse(true);
+  return true;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateSetPropertiesFunction
+
+NetworkingPrivateSetPropertiesFunction::
+  ~NetworkingPrivateSetPropertiesFunction() {
+}
+
+bool NetworkingPrivateSetPropertiesFunction::RunImpl() {
+  scoped_ptr<api::SetProperties::Params> params =
+      api::SetProperties::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  scoped_ptr<base::DictionaryValue> properties_dict(
+      params->properties.ToValue());
+
+  // Store properties_dict in profile to return from GetProperties.
+  profile()->SetUserData(kNetworkingPrivateProperties,
+    new NetworkingPrivatePropertiesData(properties_dict.get()));
+  SendResponse(true);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateGetVisibleNetworksFunction
+
+NetworkingPrivateGetVisibleNetworksFunction::
+  ~NetworkingPrivateGetVisibleNetworksFunction() {
+}
+
+bool NetworkingPrivateGetVisibleNetworksFunction::RunImpl() {
+  scoped_ptr<api::GetVisibleNetworks::Params> params =
+      api::GetVisibleNetworks::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  const std::string networks_json =
+      "[{"
+      "    \"ConnectionState\": \"Connected\","
+      "    \"GUID\": \"stub_ethernet\","
+      "    \"Name\": \"eth0\","
+      "    \"Type\": \"Ethernet\""
+      "  },"
+      "  {"
+      "    \"ConnectionState\": \"Connected\","
+      "    \"GUID\": \"stub_wifi1\","
+      "    \"Name\": \"wifi1\","
+      "    \"Type\": \"WiFi\","
+      "    \"WiFi\": {"
+      "      \"AutoConnect\": false,"
+      "      \"FrequencyList\": [2400],"
+      "      \"Security\": \"WEP-PSK\","
+      "      \"SignalStrength\": 0"
+      "    }"
+      "  },"
+      "  {"
+      "    \"ConnectionState\": \"NotConnected\","
+      "    \"GUID\": \"stub_wifi2\","
+      "    \"Name\": \"wifi2_PSK\","
+      "    \"Type\": \"WiFi\","
+      "    \"WiFi\": {"
+      "      \"AutoConnect\": false,"
+      "      \"FrequencyList\": [2400, 5000],"
+      "      \"Security\": \"WPA-PSK\","
+      "      \"SignalStrength\": 80"
+      "    }"
+      "  },"
+      "  {"
+      "    \"Cellular\": {"
+      "      \"ActivateOverNonCellularNetwork\": false,"
+      "      \"ActivationState\": \"not-activated\","
+      "      \"NetworkTechnology\": \"GSM\","
+      "      \"RoamingState\": \"home\""
+      "    },"
+      "    \"ConnectionState\": \"NotConnected\","
+      "    \"GUID\": \"stub_cellular1\","
+      "    \"Name\": \"cellular1\","
+      "    \"Type\": \"Cellular\""
+      "  },"
+      "  {"
+      "    \"ConnectionState\": \"Connected\","
+      "    \"GUID\": \"stub_vpn1\","
+      "    \"Name\": \"vpn1\","
+      "    \"Type\": \"VPN\","
+      "    \"VPN\": {"
+      "      \"AutoConnect\": false"
+      "    }"
+      "  }]";
+  ListValue* visible_networks =
+      static_cast<ListValue*>(base::JSONReader::Read(networks_json));
+  // If caller only needs WiFi networks, then remove all other networks.
+  if (params->type == api::GetVisibleNetworks::Params::TYPE_WIFI) {
+    visible_networks->Remove(4, NULL);
+    visible_networks->Remove(3, NULL);
+    visible_networks->Remove(0, NULL);
+  }
+
+  SetResult(visible_networks);
+  SendResponse(true);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateRequestNetworkScanFunction
+
+NetworkingPrivateRequestNetworkScanFunction::
+  ~NetworkingPrivateRequestNetworkScanFunction() {
+}
+
+bool NetworkingPrivateRequestNetworkScanFunction::RunImpl() {
+  // Generate onNetworkListChanged event.
+  std::vector<std::string> changes;
+  changes.push_back("stub_ethernet");
+  changes.push_back("stub_wifi1");
+  changes.push_back("stub_wifi2");
+  changes.push_back("stub_cellular1");
+  changes.push_back("stub_vpn1");
+
+  EventRouter* event_router = ExtensionSystem::Get(profile_)->event_router();
+  scoped_ptr<base::ListValue> args(api::OnNetworkListChanged::Create(changes));
+  scoped_ptr<extensions::Event> extension_event(new extensions::Event(
+      kOnNetworkListChanged, args.Pass()));
+  event_router->BroadcastEvent(extension_event.Pass());
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateStartConnectFunction
+
+NetworkingPrivateStartConnectFunction::
+  ~NetworkingPrivateStartConnectFunction() {
+}
+
+bool NetworkingPrivateStartConnectFunction::RunImpl() {
+  scoped_ptr<api::StartConnect::Params> params =
+      api::StartConnect::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  if (params->network_guid == "nonexistent_path") {
+    error_ = "not-found";
+    SendResponse(false);
+  } else {
+    SendResponse(true);
+    // Set Properties to reflect connected state
+    const std::string network_properties =
+      "{\"ConnectionState\":\"Connected\","
+       "\"GUID\":\"stub_wifi2\","
+       "\"Name\":\"wifi2_PSK\","
+       "\"Type\":\"WiFi\","
+       "\"WiFi\":{"
+         "\"Frequency\":5000,"
+         "\"FrequencyList\":[2400,5000],"
+         "\"SSID\":\"stub_wifi2\","
+         "\"Security\":\"WPA-PSK\","
+         "\"SignalStrength\":80}}";
+
+    // Store network_properties in profile to return from GetProperties.
+    profile()->SetUserData(kNetworkingPrivateProperties,
+      new NetworkingPrivatePropertiesData(
+        static_cast<DictionaryValue*>(
+          base::JSONReader::Read(network_properties))));
+
+    // Broadcast NetworksChanged Event that network is connected
+    EventRouter* event_router = ExtensionSystem::Get(profile_)->event_router();
+    scoped_ptr<base::ListValue> args(api::OnNetworksChanged::Create(
+        std::vector<std::string>(1, params->network_guid)));
+    scoped_ptr<extensions::Event> netchanged_event(
+        new extensions::Event(kOnNetworksChanged, args.Pass()));
+    event_router->BroadcastEvent(netchanged_event.Pass());
+
+    // Generate NetworkListChanged event.
+    std::vector<std::string> list;
+    list.push_back("stub_wifi2");
+    list.push_back("stub_ethernet");
+    list.push_back("stub_wifi1");
+    list.push_back("stub_cellular1");
+    list.push_back("stub_vpn1");
+
+    scoped_ptr<base::ListValue> arg2(api::OnNetworkListChanged::Create(list));
+    scoped_ptr<extensions::Event> netlist_event(new extensions::Event(
+        kOnNetworkListChanged, arg2.Pass()));
+    event_router->BroadcastEvent(netlist_event.Pass());
+  }
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateStartDisconnectFunction
+
+NetworkingPrivateStartDisconnectFunction::
+  ~NetworkingPrivateStartDisconnectFunction() {
+}
+
+bool NetworkingPrivateStartDisconnectFunction::RunImpl() {
+  scoped_ptr<api::StartDisconnect::Params> params =
+      api::StartDisconnect::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  if (params->network_guid == "nonexistent_path") {
+    error_ = "not-found";
+    SendResponse(false);
+  } else {
+    SendResponse(true);
+
+    // Send Event that network is disconnected. Listener will use GetProperties.
+    EventRouter* event_router = ExtensionSystem::Get(profile_)->event_router();
+    scoped_ptr<base::ListValue> args(api::OnNetworksChanged::Create(
+        std::vector<std::string>(1, params->network_guid)));
+    scoped_ptr<extensions::Event> extension_event(
+        new extensions::Event(kOnNetworksChanged, args.Pass()));
+    event_router->BroadcastEvent(extension_event.Pass());
+  }
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateVerifyDestinationFunction
+
+NetworkingPrivateVerifyDestinationFunction::
+  ~NetworkingPrivateVerifyDestinationFunction() {
+}
+
+bool NetworkingPrivateVerifyDestinationFunction::RunImpl() {
+  scoped_ptr<api::VerifyDestination::Params> params =
+      api::VerifyDestination::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  SetResult(new base::FundamentalValue(true));
+  SendResponse(true);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateVerifyAndEncryptCredentialsFunction
+
+NetworkingPrivateVerifyAndEncryptCredentialsFunction::
+  ~NetworkingPrivateVerifyAndEncryptCredentialsFunction() {
+}
+
+bool NetworkingPrivateVerifyAndEncryptCredentialsFunction::RunImpl() {
+  scoped_ptr<api::VerifyAndEncryptCredentials::Params> params =
+      api::VerifyAndEncryptCredentials::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  SetResult(new base::StringValue("encrypted_credentials"));
+  SendResponse(true);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateVerifyAndEncryptDataFunction
+
+NetworkingPrivateVerifyAndEncryptDataFunction::
+  ~NetworkingPrivateVerifyAndEncryptDataFunction() {
+}
+
+bool NetworkingPrivateVerifyAndEncryptDataFunction::RunImpl() {
+  scoped_ptr<api::VerifyAndEncryptData::Params> params =
+      api::VerifyAndEncryptData::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  SetResult(new base::StringValue("encrypted_data"));
+  SendResponse(true);
+  return true;
+}
+
diff --git a/chrome/browser/chromeos/extensions/networking_private_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
similarity index 93%
rename from chrome/browser/chromeos/extensions/networking_private_apitest.cc
rename to chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
index fe7093c..5ab4ef5 100644
--- a/chrome/browser/chromeos/extensions/networking_private_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,6 +15,8 @@
 #include "chrome/browser/policy/policy_types.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
+
+#if defined(OS_CHROMEOS)
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -25,7 +27,7 @@
 #include "chromeos/network/onc/onc_utils.h"
 #include "policy/policy_constants.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
-
+#endif  // OS_CHROMEOS
 using testing::AnyNumber;
 using testing::Return;
 using testing::_;
@@ -37,19 +39,35 @@
 const char kUser1ProfilePath[] = "/profile/user1/shill";
 const char kUserIdStubHashSuffix[] = "-hash";
 
-void AssignString(std::string* out,
-                  DBusMethodCallStatus call_status,
-                  const std::string& result) {
-  CHECK_EQ(call_status, DBUS_METHOD_CALL_SUCCESS);
-  *out = result;
-}
-
 }  // namespace
 
 class ExtensionNetworkingPrivateApiTest :
     public ExtensionApiTest,
     public testing::WithParamInterface<bool> {
  public:
+  bool RunNetworkingSubtest(const std::string& subtest) {
+    return RunExtensionSubtest(
+        "networking", "main.html?" + subtest,
+        kFlagEnableFileAccess | kFlagLoadAsComponent);
+  }
+
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+    EXPECT_CALL(provider_, IsInitializationComplete(_))
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(provider_, RegisterPolicyDomain(_)).Times(AnyNumber());
+    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+
+    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
+  }
+
+#if defined(OS_CHROMEOS)
+  static void AssignString(std::string* out,
+                    DBusMethodCallStatus call_status,
+                    const std::string& result) {
+    CHECK_EQ(call_status, DBUS_METHOD_CALL_SUCCESS);
+    *out = result;
+  }
+
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     ExtensionApiTest::SetUpCommandLine(command_line);
     // Whitelist the extension ID of the test extension.
@@ -68,21 +86,6 @@
       command_line->AppendSwitch(::switches::kMultiProfiles);
   }
 
-  bool RunNetworkingSubtest(const std::string& subtest) {
-    return RunExtensionSubtest(
-        "networking", "main.html?" + subtest,
-        kFlagEnableFileAccess | kFlagLoadAsComponent);
-  }
-
-  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
-    EXPECT_CALL(provider_, IsInitializationComplete(_))
-        .WillRepeatedly(Return(true));
-    EXPECT_CALL(provider_, RegisterPolicyDomain(_)).Times(AnyNumber());
-    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
-
-    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
-  }
-
   void InitializeSanitizedUsername() {
     chromeos::UserManager* user_manager = chromeos::UserManager::Get();
     chromeos::User* user = user_manager->GetActiveUser();
@@ -189,6 +192,19 @@
 
     content::RunAllPendingInMessageLoop();
   }
+#else  // !defined(OS_CHROMEOS)
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    ExtensionApiTest::SetUpCommandLine(command_line);
+    // Whitelist the extension ID of the test extension.
+    command_line->AppendSwitchASCII(::switches::kWhitelistedExtensionID,
+                                    "epcifkihnkjgphfkloaaleeakhpmgdmn");
+  }
+
+  virtual void SetUpOnMainThread() OVERRIDE {
+    ExtensionApiTest::SetUpOnMainThread();
+    content::RunAllPendingInMessageLoop();
+  }
+#endif  // OS_CHROMEOS
 
  protected:
   policy::MockConfigurationPolicyProvider provider_;
@@ -250,6 +266,7 @@
   EXPECT_TRUE(RunNetworkingSubtest("setProperties")) << message_;
 }
 
+#if defined(OS_CHROMEOS)
 IN_PROC_BROWSER_TEST_P(ExtensionNetworkingPrivateApiTest,
                        GetManagedProperties) {
   ShillServiceClient::TestInterface* service_test =
@@ -302,6 +319,7 @@
 
   EXPECT_TRUE(RunNetworkingSubtest("getManagedProperties")) << message_;
 }
+#endif  // OS_CHROMEOS
 
 IN_PROC_BROWSER_TEST_P(ExtensionNetworkingPrivateApiTest,
                        OnNetworksChangedEventConnect) {
@@ -340,3 +358,4 @@
                         testing::Bool());
 
 }  // namespace chromeos
+
diff --git a/chrome/browser/chromeos/extensions/networking_private_event_router.h b/chrome/browser/extensions/api/networking_private/networking_private_event_router.h
similarity index 84%
rename from chrome/browser/chromeos/extensions/networking_private_event_router.h
rename to chrome/browser/extensions/api/networking_private/networking_private_event_router.h
index 9173c76..011c8dd 100644
--- a/chrome/browser/chromeos/extensions/networking_private_event_router.h
+++ b/chrome/browser/extensions/api/networking_private/networking_private_event_router.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_EVENT_ROUTER_H_
-#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_EVENT_ROUTER_H_
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_EVENT_ROUTER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_EVENT_ROUTER_H_
 
 #include "chrome/browser/extensions/event_router.h"
 #include "chromeos/network/network_state_handler_observer.h"
@@ -52,4 +52,5 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_EVENT_ROUTER_H_
+#endif  // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_EVENT_ROUTER_H_
+
diff --git a/chrome/browser/chromeos/extensions/networking_private_event_router.cc b/chrome/browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc
similarity index 95%
rename from chrome/browser/chromeos/extensions/networking_private_event_router.cc
rename to chrome/browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc
index 97b3b60..44d70eb 100644
--- a/chrome/browser/chromeos/extensions/networking_private_event_router.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/extensions/networking_private_event_router.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_event_router.h"
 
 #include "base/json/json_writer.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/extensions/networking_private_api.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_api.h"
 #include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/event_router_forwarder.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -139,3 +139,4 @@
 }
 
 }  // namespace chromeos
+
diff --git a/chrome/browser/chromeos/extensions/networking_private_event_router_factory.cc b/chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.cc
similarity index 83%
rename from chrome/browser/chromeos/extensions/networking_private_event_router_factory.cc
rename to chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.cc
index 1a88b74..6814ffe 100644
--- a/chrome/browser/chromeos/extensions/networking_private_event_router_factory.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/extensions/networking_private_event_router_factory.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.h"
 
-#include "chrome/browser/chromeos/extensions/networking_private_event_router.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_event_router.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
@@ -38,7 +38,11 @@
 BrowserContextKeyedService*
 NetworkingPrivateEventRouterFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
+#if defined(OS_CHROMEOS)
   return new NetworkingPrivateEventRouter(static_cast<Profile*>(profile));
+#else  // OS_CHROMEOS
+  return NULL;
+#endif  // OS_CHROMEOS
 }
 
 content::BrowserContext*
diff --git a/chrome/browser/chromeos/extensions/networking_private_event_router_factory.h b/chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.h
similarity index 81%
rename from chrome/browser/chromeos/extensions/networking_private_event_router_factory.h
rename to chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.h
index 0208904..bcd2eba 100644
--- a/chrome/browser/chromeos/extensions/networking_private_event_router_factory.h
+++ b/chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_EVENT_ROUTER_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_EVENT_ROUTER_FACTORY_H_
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_EVENT_ROUTER_FACTORY_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_EVENT_ROUTER_FACTORY_H_
 
 #include "base/memory/singleton.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
@@ -49,4 +49,5 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_EVENT_ROUTER_FACTORY_H_
+#endif  // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_EVENT_ROUTER_FACTORY_H_
+
diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc
index ee5a829..a1c30b5 100644
--- a/chrome/browser/extensions/app_process_apitest.cc
+++ b/chrome/browser/extensions/app_process_apitest.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/extensions/process_map.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
+#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -656,20 +657,28 @@
       LoadExtension(test_data_dir_.AppendASCII("app_process"));
   ASSERT_TRUE(app);
 
-  content::WindowedNotificationObserver blocker_observer(
-      chrome::NOTIFICATION_CONTENT_BLOCKED_STATE_CHANGED,
-      content::NotificationService::AllSources());
   ui_test_utils::NavigateToURL(
       browser(), GetTestBaseURL("app_process").Resolve("path3/container.html"));
 
-  blocker_observer.Wait();
-
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
   BlockedContentTabHelper* blocked_content_tab_helper =
       BlockedContentTabHelper::FromWebContents(tab);
-  std::vector<WebContents*> blocked_contents;
-  blocked_content_tab_helper->GetBlockedContents(&blocked_contents);
-  EXPECT_EQ(blocked_contents.size(), 1u);
+  PopupBlockerTabHelper* popup_blocker_tab_helper =
+      PopupBlockerTabHelper::FromWebContents(tab);
+  if (!blocked_content_tab_helper->GetBlockedContentsCount() &&
+      (!popup_blocker_tab_helper ||
+       !popup_blocker_tab_helper->GetBlockedPopupsCount())) {
+    content::WindowedNotificationObserver observer(
+        chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
+        content::NotificationService::AllSources());
+    observer.Wait();
+  }
+
+  EXPECT_EQ(1u,
+            blocked_content_tab_helper->GetBlockedContentsCount() +
+                (popup_blocker_tab_helper
+                     ? popup_blocker_tab_helper->GetBlockedPopupsCount()
+                     : 0));
 }
 
 // Tests that if an extension launches an app via chrome.tabs.create with an URL
diff --git a/chrome/browser/extensions/data_deleter.cc b/chrome/browser/extensions/data_deleter.cc
index 8c8fe4f..46518b0 100644
--- a/chrome/browser/extensions/data_deleter.cc
+++ b/chrome/browser/extensions/data_deleter.cc
@@ -41,19 +41,16 @@
     // preserve this code path without checking for isolation because it's
     // simpler than special casing.  This code should go away once we merge
     // the various URLRequestContexts (http://crbug.com/159193).
-    partition->ClearDataForOrigin(
-        content::StoragePartition::REMOVE_DATA_MASK_ALL,
+    partition->AsyncClearDataForOrigin(
         content::StoragePartition::kAllStorage,
         storage_origin,
         profile->GetRequestContextForExtensions());
   } else {
     // We don't need to worry about the media request context because that
     // shares the same cookie store as the main request context.
-    partition->ClearDataForOrigin(
-        content::StoragePartition::REMOVE_DATA_MASK_ALL,
-        content::StoragePartition::kAllStorage,
-        storage_origin,
-        partition->GetURLRequestContext());
+    partition->AsyncClearDataForOrigin(content::StoragePartition::kAllStorage,
+                                       storage_origin,
+                                       partition->GetURLRequestContext());
   }
 
   // Begin removal of the settings for the current extension.
diff --git a/chrome/browser/extensions/external_loader.h b/chrome/browser/extensions/external_loader.h
index 86ffee3..ecadda0 100644
--- a/chrome/browser/extensions/external_loader.h
+++ b/chrome/browser/extensions/external_loader.h
@@ -55,7 +55,7 @@
   virtual ~ExternalLoader();
 
   // Notifies the provider that the list of extensions has been loaded.
-  void LoadFinished();
+  virtual void LoadFinished();
 
   // Used for passing the list of extensions from the method that loads them
   // to |LoadFinished|. To ensure thread safety, the rules are the following:
diff --git a/chrome/browser/extensions/external_pref_loader.h b/chrome/browser/extensions/external_pref_loader.h
index 49b0ce9..c06dd35 100644
--- a/chrome/browser/extensions/external_pref_loader.h
+++ b/chrome/browser/extensions/external_pref_loader.h
@@ -38,6 +38,8 @@
   virtual const base::FilePath GetBaseCrxFilePath() OVERRIDE;
 
  protected:
+  virtual ~ExternalPrefLoader() {}
+
   virtual void StartLoading() OVERRIDE;
   bool IsOptionSet(Options option) {
     return (options_ & option) != 0;
@@ -46,8 +48,6 @@
  private:
   friend class base::RefCountedThreadSafe<ExternalLoader>;
 
-  virtual ~ExternalPrefLoader() {}
-
   // Actually searches for and loads candidate standalone extension preference
   // files in the path corresponding to |base_path_id|.
   // Must be called on the file thread.
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index b5f3dc5..677f447 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -39,6 +39,7 @@
 #endif
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/extensions/external_pref_cache_loader.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/policy/app_pack_updater.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
@@ -394,13 +395,19 @@
     external_apps_path_id = chrome::DIR_MANAGED_USERS_DEFAULT_APPS;
 #endif
 
+#if defined(OS_CHROMEOS)
+  typedef chromeos::ExternalPrefCacheLoader PrefLoader;
+#else
+  typedef ExternalPrefLoader PrefLoader;
+#endif
+
   if (!is_chromeos_demo_session) {
     provider_list->push_back(
         linked_ptr<ExternalProviderInterface>(
             new ExternalProviderImpl(
                 service,
-                new ExternalPrefLoader(external_apps_path_id,
-                                       check_admin_permissions_on_mac),
+                new PrefLoader(external_apps_path_id,
+                               check_admin_permissions_on_mac),
                 profile,
                 Manifest::EXTERNAL_PREF,
                 Manifest::EXTERNAL_PREF_DOWNLOAD,
diff --git a/chrome/browser/feedback/feedback_util.cc b/chrome/browser/feedback/feedback_util.cc
index 8095fad..738bf9e 100644
--- a/chrome/browser/feedback/feedback_util.cc
+++ b/chrome/browser/feedback/feedback_util.cc
@@ -38,17 +38,15 @@
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_status.h"
 #include "third_party/icu/source/common/unicode/locid.h"
+#include "third_party/zlib/google/zip.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
-#include "third_party/zlib/google/zip.h"
-#endif
-
 using content::WebContents;
 
 namespace {
-const char kLogsFilename[] = "system_logs.txt";
+const base::FilePath::CharType kLogsFilename[] =
+    FILE_PATH_LITERAL("system_logs.txt");
 }
 
 namespace chrome {
@@ -434,7 +432,6 @@
   screen_size = rect;
 }
 
-#if defined(OS_CHROMEOS)
 // static
 bool FeedbackUtil::ZipString(const std::string& logs,
                              std::string* compressed_logs) {
@@ -443,10 +440,10 @@
 
   // Create a temporary directory, put the logs into a file in it. Create
   // another temporary file to receive the zip file in.
-  if (!file_util::CreateNewTempDirectory("", &temp_path))
+  if (!file_util::CreateNewTempDirectory(FILE_PATH_LITERAL(""), &temp_path))
     return false;
-  if (file_util::WriteFile(
-      temp_path.Append(kLogsFilename), logs.c_str(), logs.size()) == -1)
+  if (file_util::WriteFile(temp_path.Append(kLogsFilename),
+                           logs.c_str(), logs.size()) == -1)
     return false;
   if (!file_util::CreateTemporaryFile(&zip_file))
     return false;
@@ -459,5 +456,3 @@
 
   return true;
 }
-#endif // OS_CHROMEOS
-
diff --git a/chrome/browser/feedback/feedback_util.h b/chrome/browser/feedback/feedback_util.h
index 163317d..7849186 100644
--- a/chrome/browser/feedback/feedback_util.h
+++ b/chrome/browser/feedback/feedback_util.h
@@ -76,9 +76,7 @@
   static void ClearScreenshotPng();
   static void SetScreenshotSize(const gfx::Rect& rect);
   static gfx::Rect& GetScreenshotSize();
-#if defined(OS_CHROMEOS)
   static bool ZipString(const std::string& logs, std::string* compressed_logs);
-#endif
 
   class PostCleanup;
 
diff --git a/chrome/browser/feedback/tracing_manager.cc b/chrome/browser/feedback/tracing_manager.cc
new file mode 100644
index 0000000..3ea14cf
--- /dev/null
+++ b/chrome/browser/feedback/tracing_manager.cc
@@ -0,0 +1,135 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/feedback/tracing_manager.h"
+
+#include "base/bind.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/feedback/feedback_util.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/trace_controller.h"
+
+namespace {
+// Only once trace manager can exist at a time.
+TracingManager* g_tracing_manager = NULL;
+// Trace IDs start at 1 and increase.
+int g_next_trace_id = 1;
+}
+
+TracingManager::TracingManager()
+    : current_trace_id_(0),
+      weak_ptr_factory_(this) {
+  DCHECK(!g_tracing_manager);
+  g_tracing_manager = this;
+  StartTracing();
+}
+
+TracingManager::~TracingManager() {
+  DCHECK(g_tracing_manager == this);
+  g_tracing_manager = NULL;
+}
+
+int TracingManager::RequestTrace() {
+  // Return the current trace if one is being collected.
+  if (current_trace_id_)
+    return current_trace_id_;
+
+  current_trace_id_ = g_next_trace_id;
+  ++g_next_trace_id;
+  content::TraceController::GetInstance()->EndTracingAsync(this);
+  return current_trace_id_;
+}
+
+bool TracingManager::GetTraceData(int id, const TraceDataCallback& callback) {
+  // If a trace is being collected currently, send it via callback when
+  // complete.
+  if (current_trace_id_) {
+    // Only allow one trace data request at a time.
+    if (trace_callback_.is_null()) {
+      trace_callback_ = callback;
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    std::map<int, scoped_refptr<base::RefCountedString> >::iterator data =
+        trace_data_.find(id);
+    if (data == trace_data_.end())
+      return false;
+
+    // Always return the data asychronously, so the behavior is consistant.
+    base::MessageLoopProxy::current()->PostTask(
+        FROM_HERE,
+        base::Bind(callback, data->second));
+    return true;
+  }
+}
+
+void TracingManager::DiscardTraceData(int id) {
+  trace_data_.erase(id);
+
+  // If the trace is discarded before it is complete, clean up the accumulators.
+  if (id == current_trace_id_) {
+    current_trace_id_ = 0;
+    data_ = "";
+
+    // If the trace has already been requested, provide an empty string.
+    if (!trace_callback_.is_null()) {
+      trace_callback_.Run(scoped_refptr<base::RefCountedString>());
+      trace_callback_.Reset();
+    }
+  }
+}
+
+void TracingManager::StartTracing() {
+  content::TraceController::GetInstance()->BeginTracing(
+      this, "-test_*",
+      base::debug::TraceLog::RECORD_CONTINUOUSLY);
+}
+
+void TracingManager::OnEndTracingComplete() {
+  if (!current_trace_id_)
+    return;
+
+  std::string output_val;
+  FeedbackUtil::ZipString(data_, &output_val);
+
+  scoped_refptr<base::RefCountedString> output;
+  output->TakeString(&output_val);
+
+  trace_data_[current_trace_id_] = output;
+
+  if (!trace_callback_.is_null()) {
+    trace_callback_.Run(output);
+    trace_callback_.Reset();
+  }
+
+  current_trace_id_ = 0;
+  data_ = "";
+
+  // Tracing has to be restarted asynchronous, so the TracingController can
+  // clean up.
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&TracingManager::StartTracing,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
+void TracingManager::OnTraceDataCollected(
+    const scoped_refptr<base::RefCountedString>& trace_fragment) {
+  if (current_trace_id_)
+    data_ += trace_fragment->data();
+}
+
+// static
+scoped_ptr<TracingManager> TracingManager::Create() {
+  if (g_tracing_manager)
+    return scoped_ptr<TracingManager>();
+  return scoped_ptr<TracingManager>(new TracingManager());
+}
+
+TracingManager* TracingManager::Get() {
+  return g_tracing_manager;
+}
diff --git a/chrome/browser/feedback/tracing_manager.h b/chrome/browser/feedback/tracing_manager.h
new file mode 100644
index 0000000..c70206a
--- /dev/null
+++ b/chrome/browser/feedback/tracing_manager.h
@@ -0,0 +1,80 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FEEDBACK_TRACING_MANAGER_H_
+#define CHROME_BROWSER_FEEDBACK_TRACING_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/trace_subscriber.h"
+
+// Callback used for getting the output of a trace.
+typedef base::Callback<void(scoped_refptr<base::RefCountedString> trace_data)>
+    TraceDataCallback;
+
+// This class is used to manage performance meterics that can be attached to
+// feedback reports.  This class is a Singleton that is owned by the preference
+// system.  It should only be created when it is enabled, and should only be
+// accessed elsewhere via Get().
+//
+// When a performance trace is desired, TracingManager::Get()->RequestTrace()
+// should be invoked.  The TracingManager will then start preparing a zipped
+// version of the performance data.  That data can then be requested via
+// GetTraceData().  When the data is no longer needed, it should be discarded
+// via DiscardTraceData().
+class TracingManager : public content::TraceSubscriber {
+ public:
+  virtual ~TracingManager();
+
+  // Create a TracingManager.  Can only be called when none exists.
+  static scoped_ptr<TracingManager> Create();
+
+  // Get the current TracingManager.  Returns NULL if one doesn't exist.
+  static TracingManager* Get();
+
+  // Request a trace ending at the current time.  If a trace is already being
+  // collected, the id for that trace is returned.
+  int RequestTrace();
+
+  // Get the trace data for |id|.  On success, true is returned, and the data is
+  // returned via |callback|.  Returns false on failure.
+  bool GetTraceData(int id, const TraceDataCallback& callback);
+
+  // Discard the data for trace |id|.
+  void DiscardTraceData(int id);
+
+ private:
+  void StartTracing();
+
+  // content::TraceSubscriber overrides
+  virtual void OnEndTracingComplete() OVERRIDE;
+  virtual void OnTraceDataCollected(
+      const scoped_refptr<base::RefCountedString>& trace_fragment) OVERRIDE;
+
+  TracingManager();
+
+  // Data being collected from the current trace.
+  std::string data_;
+
+  // ID of the trace that is being collected.
+  int current_trace_id_;
+
+  // Mapping of trace ID to trace data.
+  std::map<int, scoped_refptr<base::RefCountedString> > trace_data_;
+
+  // Callback for the current trace request.
+  TraceDataCallback trace_callback_;
+
+  base::WeakPtrFactory<TracingManager> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(TracingManager);
+};
+
+#endif  // CHROME_BROWSER_FEEDBACK_TRACING_MANAGER_H_
+
diff --git a/chrome/browser/google_apis/DEPS b/chrome/browser/google_apis/DEPS
index 214c501..20ee665 100644
--- a/chrome/browser/google_apis/DEPS
+++ b/chrome/browser/google_apis/DEPS
@@ -8,14 +8,9 @@
 specific_include_rules = {
   # AuthService should be gone. crbug.com/162157
   "auth_service\.(h|cc)": [
-    "!chrome/browser/chrome_notification_types.h",
     "!chrome/browser/profiles/profile.h",
-    "!chrome/browser/signin/token_service_factory.h",
-    "!chrome/browser/signin/token_service.h",
-    "!content/public/browser/notification_details.h",
-    "!content/public/browser/notification_observer.h",
-    "!content/public/browser/notification_registrar.h",
-    "!content/public/browser/notification_source.h",
-    "!content/public/browser/notification_types.h",
+    "!chrome/browser/signin/oauth2_token_service.h",
+    "!chrome/browser/signin/profile_oauth2_token_service.h",
+    "!chrome/browser/signin/profile_oauth2_token_service_factory.h",
   ],
 }
diff --git a/chrome/browser/google_apis/auth_service.cc b/chrome/browser/google_apis/auth_service.cc
index 7d2017a..195848b 100644
--- a/chrome/browser/google_apis/auth_service.cc
+++ b/chrome/browser/google_apis/auth_service.cc
@@ -8,20 +8,16 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/location.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/metrics/histogram.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/google_apis/auth_service_observer.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/token_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "google_apis/gaia/oauth2_access_token_fetcher.h"
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/login/login_state.h"
@@ -39,62 +35,49 @@
 const int kSuccessRatioHistogramTemporaryFailure = 3;
 const int kSuccessRatioHistogramMaxValue = 4;  // The max value is exclusive.
 
-}  // namespace
-
 // OAuth2 authorization token retrieval request.
-class AuthRequest : public OAuth2AccessTokenConsumer {
+class AuthRequest : public OAuth2TokenService::Consumer {
  public:
-  AuthRequest(net::URLRequestContextGetter* url_request_context_getter,
+  AuthRequest(Profile* profile,
+              net::URLRequestContextGetter* url_request_context_getter,
               const AuthStatusCallback& callback,
-              const std::vector<std::string>& scopes,
-              const std::string& refresh_token);
+              const std::vector<std::string>& scopes);
   virtual ~AuthRequest();
-  void Start();
-
-  // Overridden from OAuth2AccessTokenConsumer:
-  virtual void OnGetTokenSuccess(const std::string& access_token,
-                                 const base::Time& expiration_time) OVERRIDE;
-  virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
 
  private:
-  net::URLRequestContextGetter* url_request_context_getter_;
-  std::string refresh_token_;
+  // Overridden from OAuth2TokenService::Consumer:
+  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
+                                 const std::string& access_token,
+                                 const base::Time& expiration_time) OVERRIDE;
+  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
+                                 const GoogleServiceAuthError& error) OVERRIDE;
+
   AuthStatusCallback callback_;
-  std::vector<std::string> scopes_;
-  scoped_ptr<OAuth2AccessTokenFetcher> oauth2_access_token_fetcher_;
+  OAuth2TokenService::ScopeSet scopes_;
+  scoped_ptr<OAuth2TokenService::Request> request_;
   base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthRequest);
 };
 
 AuthRequest::AuthRequest(
+    Profile* profile,
     net::URLRequestContextGetter* url_request_context_getter,
     const AuthStatusCallback& callback,
-    const std::vector<std::string>& scopes,
-    const std::string& refresh_token)
-    : url_request_context_getter_(url_request_context_getter),
-      refresh_token_(refresh_token),
-      callback_(callback),
-      scopes_(scopes) {
+    const std::vector<std::string>& scopes)
+    : callback_(callback),
+      scopes_(scopes.begin(), scopes.end()) {
   DCHECK(!callback_.is_null());
+  request_ = ProfileOAuth2TokenServiceFactory::GetForProfile(profile)->
+      StartRequestWithContext(url_request_context_getter, scopes_, this);
 }
 
 AuthRequest::~AuthRequest() {}
 
-void AuthRequest::Start() {
-  DCHECK(!refresh_token_.empty());
-  oauth2_access_token_fetcher_.reset(new OAuth2AccessTokenFetcher(
-      this, url_request_context_getter_));
-  oauth2_access_token_fetcher_->Start(
-      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
-      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
-      refresh_token_,
-      scopes_);
-}
-
 // Callback for OAuth2AccessTokenFetcher on success. |access_token| is the token
 // used to start fetching user data.
-void AuthRequest::OnGetTokenSuccess(const std::string& access_token,
+void AuthRequest::OnGetTokenSuccess(const OAuth2TokenService::Request* request,
+                                    const std::string& access_token,
                                     const base::Time& expiration_time) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
@@ -107,7 +90,8 @@
 }
 
 // Callback for OAuth2AccessTokenFetcher on failure.
-void AuthRequest::OnGetTokenFailure(const GoogleServiceAuthError& error) {
+void AuthRequest::OnGetTokenFailure(const OAuth2TokenService::Request* request,
+                                    const GoogleServiceAuthError& error) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   LOG(WARNING) << "AuthRequest: token request using refresh token failed: "
@@ -137,6 +121,8 @@
   delete this;
 }
 
+}  // namespace
+
 AuthService::AuthService(
     Profile* profile,
     net::URLRequestContextGetter* url_request_context_getter,
@@ -146,19 +132,19 @@
       scopes_(scopes),
       weak_ptr_factory_(this) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(profile);
 
   // Get OAuth2 refresh token (if we have any) and register for its updates.
-  TokenService* service = TokenServiceFactory::GetForProfile(profile_);
-  refresh_token_ = service->GetOAuth2LoginRefreshToken();
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                 content::Source<TokenService>(service));
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_TOKEN_REQUEST_FAILED,
-                 content::Source<TokenService>(service));
+  OAuth2TokenService* service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
+  service->AddObserver(this);
+  has_refresh_token_ = service->RefreshTokenIsAvailable();
 }
 
 AuthService::~AuthService() {
+  OAuth2TokenService* service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
+  service->RemoveObserver(this);
 }
 
 void AuthService::StartAuthentication(const AuthStatusCallback& callback) {
@@ -172,12 +158,12 @@
                           base::Bind(callback, HTTP_SUCCESS, access_token_));
   } else if (HasRefreshToken()) {
     // We have refresh token, let's get an access token.
-    (new AuthRequest(url_request_context_getter_,
-                     base::Bind(&AuthService::OnAuthCompleted,
-                                weak_ptr_factory_.GetWeakPtr(),
-                                callback),
-                     scopes_,
-                     refresh_token_))->Start();
+    new AuthRequest(profile_,
+                    url_request_context_getter_,
+                    base::Bind(&AuthService::OnAuthCompleted,
+                               weak_ptr_factory_.GetWeakPtr(),
+                               callback),
+                    scopes_);
   } else {
     relay_proxy->PostTask(FROM_HERE,
                           base::Bind(callback, GDATA_NOT_READY, std::string()));
@@ -189,7 +175,7 @@
 }
 
 bool AuthService::HasRefreshToken() const {
-  return !refresh_token_.empty();
+  return has_refresh_token_;
 }
 
 const std::string& AuthService::access_token() const {
@@ -201,7 +187,7 @@
 }
 
 void AuthService::ClearRefreshToken() {
-  refresh_token_.clear();
+  has_refresh_token_ = false;
 
   FOR_EACH_OBSERVER(AuthServiceObserver,
                     observers_,
@@ -239,24 +225,19 @@
   observers_.RemoveObserver(observer);
 }
 
-void AuthService::Observe(int type,
-                          const content::NotificationSource& source,
-                          const content::NotificationDetails& details) {
-  DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE ||
-         type == chrome::NOTIFICATION_TOKEN_REQUEST_FAILED);
+void AuthService::OnRefreshTokenAvailable(const std::string& account_id) {
+  OnHandleRefreshToken(true);
+}
 
-  TokenService::TokenAvailableDetails* token_details =
-      content::Details<TokenService::TokenAvailableDetails>(details).ptr();
-  if (token_details->service() != GaiaConstants::kGaiaOAuth2LoginRefreshToken)
-    return;
+void AuthService::OnRefreshTokenRevoked(const std::string& account_id,
+                                        const GoogleServiceAuthError& error) {
+  OnHandleRefreshToken(false);
+}
 
+void AuthService::OnHandleRefreshToken(bool has_refresh_token) {
   access_token_.clear();
-  if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) {
-    TokenService* service = TokenServiceFactory::GetForProfile(profile_);
-    refresh_token_ = service->GetOAuth2LoginRefreshToken();
-  } else {
-    refresh_token_.clear();
-  }
+  has_refresh_token_ = has_refresh_token;
+
   FOR_EACH_OBSERVER(AuthServiceObserver,
                     observers_,
                     OnOAuth2RefreshTokenChanged());
diff --git a/chrome/browser/google_apis/auth_service.h b/chrome/browser/google_apis/auth_service.h
index a5647a7..4c92ab1 100644
--- a/chrome/browser/google_apis/auth_service.h
+++ b/chrome/browser/google_apis/auth_service.h
@@ -12,9 +12,7 @@
 #include "base/observer_list.h"
 #include "base/threading/thread_checker.h"
 #include "chrome/browser/google_apis/auth_service_interface.h"
-#include "chrome/browser/google_apis/gdata_errorcode.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "chrome/browser/signin/oauth2_token_service.h"
 
 class Profile;
 
@@ -31,7 +29,7 @@
 // (TokenService) and provides OAuth2 token refresh infrastructure.
 // All public functions must be called on UI thread.
 class AuthService : public AuthServiceInterface,
-                    public content::NotificationObserver {
+                    public OAuth2TokenService::Observer {
  public:
   // |url_request_context_getter| is used to perform authentication with
   // URLFetcher.
@@ -52,10 +50,11 @@
   virtual void ClearAccessToken() OVERRIDE;
   virtual void ClearRefreshToken() OVERRIDE;
 
-  // Overridden from content::NotificationObserver:
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
+  // Overridden from OAuth2TokenService::Observer:
+  virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
+  virtual void OnRefreshTokenRevoked(
+      const std::string& account_id,
+      const GoogleServiceAuthError& error) OVERRIDE;
 
   // Sets the access_token as specified.  This should be used only for testing.
   void set_access_token_for_testing(const std::string& token) {
@@ -68,6 +67,9 @@
   static bool CanAuthenticate(Profile* profile);
 
  private:
+  // Called when the state of the refresh token changes.
+  void OnHandleRefreshToken(bool has_refresh_token);
+
   // Called when authentication request from StartAuthentication() is
   // completed.
   void OnAuthCompleted(const AuthStatusCallback& callback,
@@ -76,14 +78,12 @@
 
   Profile* profile_;
   net::URLRequestContextGetter* url_request_context_getter_;  // Not owned.
-  std::string refresh_token_;
+  bool has_refresh_token_;
   std::string access_token_;
   std::vector<std::string> scopes_;
   ObserverList<AuthServiceObserver> observers_;
   base::ThreadChecker thread_checker_;
 
-  content::NotificationRegistrar registrar_;
-
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<AuthService> weak_ptr_factory_;
diff --git a/chrome/browser/guestview/webview/webview_constants.cc b/chrome/browser/guestview/webview/webview_constants.cc
index b80b635..2611a7d 100644
--- a/chrome/browser/guestview/webview/webview_constants.cc
+++ b/chrome/browser/guestview/webview/webview_constants.cc
@@ -16,6 +16,8 @@
 const char kEventLoadRedirect[] = "webview.onLoadRedirect";
 const char kEventLoadStart[] = "webview.onLoadStart";
 const char kEventLoadStop[] = "webview.onLoadStop";
+const char kEventResponsive[] = "webview.onResponsive";
+const char kEventUnresponsive[] = "webview.onUnresponsive";
 
 // Parameters/properties on events.
 const char kLevel[] = "level";
diff --git a/chrome/browser/guestview/webview/webview_constants.h b/chrome/browser/guestview/webview/webview_constants.h
index e8ce5a4..59532f2 100644
--- a/chrome/browser/guestview/webview/webview_constants.h
+++ b/chrome/browser/guestview/webview/webview_constants.h
@@ -19,11 +19,13 @@
 extern const char kEventLoadRedirect[];
 extern const char kEventLoadStart[];
 extern const char kEventLoadStop[];
+extern const char kEventResponsive[];
+extern const char kEventUnresponsive[];
 
 // Parameters/properties on events.
-extern const char kMessage[];
 extern const char kLevel[];
 extern const char kLine[];
+extern const char kMessage[];
 extern const char kNewURL[];
 extern const char kOldURL[];
 extern const char kProcessId[];
@@ -35,8 +37,6 @@
 extern const char kInternalEntryCount[];
 extern const char kInternalProcessId[];
 
-// Parameters/properties on events.
-
 }  // namespace webview
 
 #endif  // CHROME_BROWSER_GUESTVIEW_WEBVIEW_WEBVIEW_CONSTANTS_H_
diff --git a/chrome/browser/guestview/webview/webview_guest.cc b/chrome/browser/guestview/webview/webview_guest.cc
index 71a4e6c..9bd9389 100644
--- a/chrome/browser/guestview/webview/webview_guest.cc
+++ b/chrome/browser/guestview/webview/webview_guest.cc
@@ -160,6 +160,22 @@
   return false;
 }
 
+// TODO(fsamuel): Find a reliable way to test the 'responsive' and
+// 'unresponsive' events.
+void WebViewGuest::RendererResponsive() {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  args->SetInteger(webview::kProcessId,
+      guest_web_contents()->GetRenderProcessHost()->GetID());
+  DispatchEvent(new GuestView::Event(webview::kEventResponsive, args.Pass()));
+}
+
+void WebViewGuest::RendererUnresponsive() {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  args->SetInteger(webview::kProcessId,
+      guest_web_contents()->GetRenderProcessHost()->GetID());
+  DispatchEvent(new GuestView::Event(webview::kEventUnresponsive, args.Pass()));
+}
+
 void WebViewGuest::Observe(int type,
                            const content::NotificationSource& source,
                            const content::NotificationDetails& details) {
diff --git a/chrome/browser/guestview/webview/webview_guest.h b/chrome/browser/guestview/webview/webview_guest.h
index 5f63ecd..a13e306 100644
--- a/chrome/browser/guestview/webview/webview_guest.h
+++ b/chrome/browser/guestview/webview/webview_guest.h
@@ -48,6 +48,8 @@
   virtual void GuestProcessGone(base::TerminationStatus status) OVERRIDE;
   virtual bool HandleKeyboardEvent(
       const content::NativeWebKeyboardEvent& event) OVERRIDE;
+  virtual void RendererResponsive() OVERRIDE;
+  virtual void RendererUnresponsive() OVERRIDE;
 
   // NotificationObserver implementation.
   virtual void Observe(int type,
diff --git a/chrome/browser/media/webrtc_browsertest_common.cc b/chrome/browser/media/webrtc_browsertest_common.cc
index 83c24fc..cf067b6 100644
--- a/chrome/browser/media/webrtc_browsertest_common.cc
+++ b/chrome/browser/media/webrtc_browsertest_common.cc
@@ -6,7 +6,6 @@
 
 #include "base/file_util.h"
 #include "base/path_service.h"
-#include "base/process_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/test_timeouts.h"
 #include "base/time/time.h"
diff --git a/chrome/browser/memory_details_android.cc b/chrome/browser/memory_details_android.cc
index 9be87ae..fab8422 100644
--- a/chrome/browser/memory_details_android.cc
+++ b/chrome/browser/memory_details_android.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/process/process_iterator.h"
 #include "chrome/common/chrome_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/process_type.h"
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index 54e26c7..c8ee4cf 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -411,7 +411,7 @@
 // static
 const int ThreadWatcherList::kUnresponsiveSeconds = 2;
 // static
-const int ThreadWatcherList::kUnresponsiveCount = 7;
+const int ThreadWatcherList::kUnresponsiveCount = 9;
 // static
 const int ThreadWatcherList::kLiveThreadsThreshold = 2;
 
diff --git a/chrome/browser/net/net_error_tab_helper.cc b/chrome/browser/net/net_error_tab_helper.cc
index 6f20a8a..c441c2c 100644
--- a/chrome/browser/net/net_error_tab_helper.cc
+++ b/chrome/browser/net/net_error_tab_helper.cc
@@ -143,7 +143,7 @@
       dns_error_active_(false),
       dns_error_page_committed_(false),
       dns_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE),
-      enabled_by_trial_(chrome_common_net::DnsProbesEnabledByFieldTrial()) {
+      probes_enabled_(chrome_common_net::DnsProbesEnabled()) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // If this helper is under test, it won't have a WebContents.
@@ -208,7 +208,7 @@
     return testing_state_ == TESTING_FORCE_ENABLED;
 
   // TODO(ttuttle): Disable on mobile?
-  return enabled_by_trial_ && *resolve_errors_with_web_service_;
+  return probes_enabled_ && *resolve_errors_with_web_service_;
 }
 
 void NetErrorTabHelper::SendInfo() {
diff --git a/chrome/browser/net/net_error_tab_helper.h b/chrome/browser/net/net_error_tab_helper.h
index fd0553e..2a38e0c 100644
--- a/chrome/browser/net/net_error_tab_helper.h
+++ b/chrome/browser/net/net_error_tab_helper.h
@@ -108,8 +108,8 @@
   // navigations), it re-sends the status whenever an error page commits.
   chrome_common_net::DnsProbeStatus dns_probe_status_;
 
-  // Whether we are enabled to run by the DnsProbe-Enable field trial.
-  const bool enabled_by_trial_;
+  // Whether probes are enabled (by the command-line option or the field trial).
+  const bool probes_enabled_;
 
   // Optional callback for browser test to snoop on outgoing NetErrorInfo IPCs.
   DnsProbeStatusSnoopCallback dns_probe_status_snoop_callback_;
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.cc b/chrome/browser/policy/cloud/user_policy_signin_service.cc
index 4091e32..2baff3d 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
 #include "google_apis/gaia/gaia_constants.h"
 
 #if defined(ENABLE_MANAGED_USERS)
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_base.cc b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
index d530557..2b78d89 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_source.h"
 
 namespace policy {
 
diff --git a/chrome/browser/prerender/prerender_local_predictor.cc b/chrome/browser/prerender/prerender_local_predictor.cc
index 93525f6..520dc22 100644
--- a/chrome/browser/prerender/prerender_local_predictor.cc
+++ b/chrome/browser/prerender/prerender_local_predictor.cc
@@ -198,6 +198,10 @@
   return (transition & content::PAGE_TRANSITION_CHAIN_END) == 0;
 }
 
+bool IsFormSubmit(PageTransition transition) {
+  return (transition & content::PAGE_TRANSITION_FORM_SUBMIT) != 0;
+}
+
 bool ShouldExcludeTransitionForPrediction(PageTransition transition) {
   return IsBackForward(transition) || IsHomePage(transition) ||
       IsIntermediateRedirect(transition);
@@ -441,7 +445,8 @@
       if (!last_visited.is_null() &&
           last_visited > visits[i].time - max_age &&
           last_visited < visits[i].time - min_age) {
-        next_urls_currently_found.insert(visits[i].url_id);
+        if (!IsFormSubmit(visits[i].transition))
+          next_urls_currently_found.insert(visits[i].url_id);
       }
     }
     if (i == static_cast<int>(visits.size()) - 1 ||
@@ -715,6 +720,7 @@
   PrerenderProperties* prerender_properties = NULL;
 
   for (int i = 0; i < static_cast<int>(info->candidate_urls_.size()); i++) {
+    RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_EXAMINE_NEXT_URL);
     url_info.reset(new LocalPredictorURLInfo(info->candidate_urls_[i]));
 
     // We need to check whether we can issue a prerender for this URL.
@@ -813,11 +819,13 @@
             p->prerender_handle.get())) {
       new_prerender_handle->OnCancel();
       new_prerender_handle.reset(NULL);
+      RecordEvent(EVENT_ISSUE_PRERENDER_ALREADY_PRERENDERING);
       break;
     }
   }
 
   if (new_prerender_handle.get()) {
+    RecordEvent(EVENT_ISSUE_PRERENDER_NEW_PRERENDER);
     // The new prerender does not match any existing prerenders. Update
     // prerender_properties so that it reflects the new entry.
     prerender_properties->url_id = url_id;
@@ -829,8 +837,10 @@
     prerender_properties->prerender_handle.swap(new_prerender_handle);
     // new_prerender_handle now represents the old previou prerender that we
     // are replacing. So we need to cancel it.
-    if (new_prerender_handle)
+    if (new_prerender_handle) {
       new_prerender_handle->OnCancel();
+      RecordEvent(EVENT_ISSUE_PRERENDER_CANCELLED_OLD_PRERENDER);
+    }
   }
 
   RecordEvent(EVENT_ADD_VISIT_PRERENDERING);
diff --git a/chrome/browser/prerender/prerender_local_predictor.h b/chrome/browser/prerender/prerender_local_predictor.h
index ebd8e03..67cea7f 100644
--- a/chrome/browser/prerender/prerender_local_predictor.h
+++ b/chrome/browser/prerender/prerender_local_predictor.h
@@ -91,6 +91,10 @@
     EVENT_TAB_HELPER_URL_SEEN_NAMESPACE_MATCH = 48,
     EVENT_PRERENDER_URL_LOOKUP_MULTIPLE_SOURCE_WEBCONTENTS_FOUND = 49,
     EVENT_CONTINUE_PRERENDER_CHECK_ON_SIDE_EFFECT_FREE_WHITELIST = 50,
+    EVENT_CONTINUE_PRERENDER_CHECK_EXAMINE_NEXT_URL = 51,
+    EVENT_ISSUE_PRERENDER_ALREADY_PRERENDERING = 52,
+    EVENT_ISSUE_PRERENDER_NEW_PRERENDER = 53,
+    EVENT_ISSUE_PRERENDER_CANCELLED_OLD_PRERENDER = 54,
     EVENT_MAX_VALUE
   };
 
diff --git a/chrome/browser/printing/printing_layout_browsertest.cc b/chrome/browser/printing/printing_layout_browsertest.cc
index 1d80518..cc0c449 100644
--- a/chrome/browser/printing/printing_layout_browsertest.cc
+++ b/chrome/browser/printing/printing_layout_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/process/process.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_file_util.h"
diff --git a/chrome/browser/profile_resetter/brandcode_config_fetcher.cc b/chrome/browser/profile_resetter/brandcode_config_fetcher.cc
index b3fb98b..f9c6c83 100644
--- a/chrome/browser/profile_resetter/brandcode_config_fetcher.cc
+++ b/chrome/browser/profile_resetter/brandcode_config_fetcher.cc
@@ -27,12 +27,20 @@
 "      >\n"
 "    <updatecheck />\n"
 "    <data name=\"install\" "
-    "index=\"skipfirstrunui-importsearch-defaultbrowser\" />\n"
+    "index=\"__BRANDCODE_PLACEHOLDER__\" />\n"
 "  </app>\n"
 "</request>";
 
-std::string GetUploadData() {
-  return kPostXml;
+// Returns the query to the server which can be used to retrieve the config.
+// |brand| is a brand code, it mustn't be empty.
+std::string GetUploadData(const std::string& brand) {
+  DCHECK(!brand.empty());
+  std::string data(kPostXml);
+  const std::string placeholder("__BRANDCODE_PLACEHOLDER__");
+  size_t placeholder_pos = data.find(placeholder);
+  DCHECK(placeholder_pos != std::string::npos);
+  data.replace(placeholder_pos, placeholder.size(), brand);
+  return data;
 }
 
 // Extracts json master prefs from xml.
@@ -130,15 +138,17 @@
 } // namespace
 
 BrandcodeConfigFetcher::BrandcodeConfigFetcher(const FetchCallback& callback,
-                                               const GURL& url)
+                                               const GURL& url,
+                                               const std::string& brandcode)
     : fetch_callback_(callback) {
+  DCHECK(!brandcode.empty());
   config_fetcher_.reset(net::URLFetcher::Create(0 /* ID used for testing */,
                                                 url,
                                                 net::URLFetcher::POST,
                                                 this));
   config_fetcher_->SetRequestContext(
       g_browser_process->system_request_context());
-  config_fetcher_->SetUploadData("text/xml", GetUploadData());
+  config_fetcher_->SetUploadData("text/xml", GetUploadData(brandcode));
   config_fetcher_->AddExtraRequestHeader("Accept: text/xml");
   config_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
                                 net::LOAD_DO_NOT_SAVE_COOKIES |
diff --git a/chrome/browser/profile_resetter/brandcode_config_fetcher.h b/chrome/browser/profile_resetter/brandcode_config_fetcher.h
index cacee4d..bbb5631 100644
--- a/chrome/browser/profile_resetter/brandcode_config_fetcher.h
+++ b/chrome/browser/profile_resetter/brandcode_config_fetcher.h
@@ -20,7 +20,8 @@
   typedef base::Callback<void ()> FetchCallback;
 
   BrandcodeConfigFetcher(const FetchCallback& callback,
-                         const GURL& url);
+                         const GURL& url,
+                         const std::string& brandcode);
   virtual ~BrandcodeConfigFetcher();
 
   bool IsActive() const { return config_fetcher_; }
diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
index f1caa33..0c3b529 100644
--- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
@@ -72,6 +72,9 @@
 using extensions::Extension;
 using extensions::Manifest;
 
+
+// ProfileResetterTest --------------------------------------------------------
+
 // ProfileResetterTest sets up the extension, WebData and TemplateURL services.
 class ProfileResetterTest : public ExtensionServiceTestBase,
                             public ProfileResetterTestBase {
@@ -101,6 +104,125 @@
   return new TemplateURLService(static_cast<Profile*>(context));
 }
 
+
+// PinnedTabsResetTest --------------------------------------------------------
+
+class PinnedTabsResetTest : public BrowserWithTestWindowTest,
+                            public ProfileResetterTestBase {
+ protected:
+  virtual void SetUp() OVERRIDE;
+
+  content::WebContents* CreateWebContents();
+};
+
+void PinnedTabsResetTest::SetUp() {
+  BrowserWithTestWindowTest::SetUp();
+  resetter_.reset(new ProfileResetter(profile()));
+}
+
+content::WebContents* PinnedTabsResetTest::CreateWebContents() {
+  return content::WebContents::Create(
+      content::WebContents::CreateParams(profile()));
+}
+
+
+// ConfigParserTest -----------------------------------------------------------
+
+// URLFetcher delegate that simply records the upload data.
+struct URLFetcherRequestListener : net::URLFetcherDelegate {
+  URLFetcherRequestListener();
+  virtual ~URLFetcherRequestListener();
+
+  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+
+  std::string upload_data;
+  net::URLFetcherDelegate* real_delegate;
+};
+
+URLFetcherRequestListener::URLFetcherRequestListener()
+    : real_delegate(NULL) {
+}
+
+URLFetcherRequestListener::~URLFetcherRequestListener() {
+}
+
+void URLFetcherRequestListener::OnURLFetchComplete(
+    const net::URLFetcher* source) {
+  const net::TestURLFetcher* test_fetcher =
+      static_cast<const net::TestURLFetcher*>(source);
+  upload_data = test_fetcher->upload_data();
+  DCHECK(real_delegate);
+  real_delegate->OnURLFetchComplete(source);
+}
+
+class ConfigParserTest : public testing::Test {
+ protected:
+  ConfigParserTest();
+  virtual ~ConfigParserTest();
+
+  scoped_ptr<BrandcodeConfigFetcher> WaitForRequest(const GURL& url);
+
+  net::FakeURLFetcherFactory& factory() { return factory_; }
+
+ private:
+  scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
+      const GURL& url,
+      net::URLFetcherDelegate* fetcher_delegate,
+      const std::string& response_data,
+      bool success);
+
+  MOCK_METHOD0(Callback, void(void));
+
+  base::MessageLoop loop_;
+  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThread io_thread_;
+  URLFetcherRequestListener request_listener_;
+  net::FakeURLFetcherFactory factory_;
+};
+
+ConfigParserTest::ConfigParserTest()
+    : loop_(base::MessageLoop::TYPE_IO),
+      ui_thread_(content::BrowserThread::UI, &loop_),
+      io_thread_(content::BrowserThread::IO, &loop_),
+      factory_(NULL, base::Bind(&ConfigParserTest::CreateFakeURLFetcher,
+                                base::Unretained(this))) {
+}
+
+ConfigParserTest::~ConfigParserTest() {}
+
+scoped_ptr<BrandcodeConfigFetcher> ConfigParserTest::WaitForRequest(
+    const GURL& url) {
+  EXPECT_CALL(*this, Callback());
+  scoped_ptr<BrandcodeConfigFetcher> fetcher(
+      new BrandcodeConfigFetcher(base::Bind(&ConfigParserTest::Callback,
+                                            base::Unretained(this)),
+                                 url,
+                                 "ABCD"));
+  base::MessageLoop::current()->RunUntilIdle();
+  EXPECT_FALSE(fetcher->IsActive());
+  // Look for the brand code in the request.
+  EXPECT_NE(std::string::npos, request_listener_.upload_data.find("ABCD"));
+  return fetcher.Pass();
+}
+
+scoped_ptr<net::FakeURLFetcher> ConfigParserTest::CreateFakeURLFetcher(
+    const GURL& url,
+    net::URLFetcherDelegate* fetcher_delegate,
+    const std::string& response_data,
+    bool success) {
+  request_listener_.real_delegate = fetcher_delegate;
+  scoped_ptr<net::FakeURLFetcher> fetcher(
+      new net::FakeURLFetcher(url, &request_listener_, response_data, success));
+  scoped_refptr<net::HttpResponseHeaders> download_headers =
+      new net::HttpResponseHeaders("");
+  download_headers->AddHeader("Content-Type: text/xml");
+  fetcher->set_response_headers(download_headers);
+  return fetcher.Pass();
+}
+
+
+// helper functions -----------------------------------------------------------
+
 scoped_refptr<Extension> CreateExtension(const std::string& name,
                                          const base::FilePath& path,
                                          Manifest::Location location,
@@ -123,78 +245,6 @@
   return extension;
 }
 
-class PinnedTabsResetTest : public BrowserWithTestWindowTest,
-                            public ProfileResetterTestBase {
- protected:
-  virtual void SetUp() OVERRIDE;
-
-  content::WebContents* CreateWebContents();
-};
-
-void PinnedTabsResetTest::SetUp() {
-  BrowserWithTestWindowTest::SetUp();
-  resetter_.reset(new ProfileResetter(profile()));
-}
-
-content::WebContents* PinnedTabsResetTest::CreateWebContents() {
-  return content::WebContents::Create(
-      content::WebContents::CreateParams(profile()));
-}
-
-class ConfigParserTest : public testing::Test {
- protected:
-  ConfigParserTest();
-  virtual ~ConfigParserTest();
-
-  MOCK_METHOD0(Callback, void(void));
-
-  scoped_ptr<BrandcodeConfigFetcher> WaitForRequest(const GURL& url);
-
-  static scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
-      const GURL& url,
-      net::URLFetcherDelegate* d,
-      const std::string& response_data,
-      bool success);
-
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread io_thread_;
-};
-
-ConfigParserTest::ConfigParserTest()
-    : loop_(base::MessageLoop::TYPE_IO),
-      ui_thread_(content::BrowserThread::UI, &loop_),
-      io_thread_(content::BrowserThread::IO, &loop_) {
-}
-
-ConfigParserTest::~ConfigParserTest() {}
-
-scoped_ptr<BrandcodeConfigFetcher> ConfigParserTest::WaitForRequest(
-    const GURL& url) {
-  EXPECT_CALL(*this, Callback());
-  scoped_ptr<BrandcodeConfigFetcher> fetcher(
-      new BrandcodeConfigFetcher(base::Bind(&ConfigParserTest::Callback,
-                                            base::Unretained(this)),
-                                 url));
-  base::MessageLoop::current()->RunUntilIdle();
-  EXPECT_FALSE(fetcher->IsActive());
-  return fetcher.Pass();
-}
-
-scoped_ptr<net::FakeURLFetcher> ConfigParserTest::CreateFakeURLFetcher(
-    const GURL& url,
-    net::URLFetcherDelegate* d,
-    const std::string& response_data,
-    bool success) {
-  scoped_ptr<net::FakeURLFetcher> fetcher(
-      new net::FakeURLFetcher(url, d, response_data, success));
-  scoped_refptr<net::HttpResponseHeaders> download_headers =
-      new net::HttpResponseHeaders("");
-  download_headers->AddHeader("Content-Type: text/xml");
-  fetcher->set_response_headers(download_headers);
-  return fetcher.Pass();
-}
-
 void ReplaceString(std::string* str,
                    const std::string& placeholder,
                    const std::string& substitution) {
@@ -523,9 +573,8 @@
 
 // Tries to load unavailable config file.
 TEST_F(ConfigParserTest, NoConnectivity) {
-  net::FakeURLFetcherFactory factory(NULL);
   const std::string url("http://test");
-  factory.SetFakeResponse(url, "", false);
+  factory().SetFakeResponse(url, "", false);
 
   scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
   EXPECT_FALSE(fetcher->GetSettings());
@@ -533,16 +582,13 @@
 
 // Tries to load available config file.
 TEST_F(ConfigParserTest, ParseConfig) {
-  net::FakeURLFetcherFactory factory(
-      NULL,
-      base::Bind(&ConfigParserTest::CreateFakeURLFetcher));
   const std::string url("http://test");
   std::string xml_config(kXmlConfig);
   ReplaceString(&xml_config, "placeholder_for_data", kDistributionConfig);
   ReplaceString(&xml_config,
                 "placeholder_for_id",
                 "abbaabbaabbaabbaabbaabbaabbaabba");
-  factory.SetFakeResponse(url, xml_config, true);
+  factory().SetFakeResponse(url, xml_config, true);
 
   scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
   scoped_ptr<BrandcodedDefaultSettings> settings = fetcher->GetSettings();
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 38b80e9..35cae78 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -118,8 +118,8 @@
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/extensions/input_method_api.h"
 #include "chrome/browser/chromeos/extensions/media_player_api.h"
-#include "chrome/browser/chromeos/extensions/networking_private_event_router_factory.h"
 #include "chrome/browser/extensions/api/input_ime/input_ime_api.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_event_router_factory.h"
 #if defined(FILE_MANAGER_EXTENSION)
 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api_factory.h"
 #endif
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.html b/chrome/browser/resources/chromeos/login/screen_error_message.html
index 0365067..82db057 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.html
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.html
@@ -1,7 +1,7 @@
 <div id="error-message" class="step hidden show-offline-error">
   <div class="step-contents">
     <div class="error-header">
-      <img alt class="error-icon" src="chrome://theme/IDR_NETWORK_ERROR">
+      <img alt class="error-icon" src="chrome://theme/IDR_ERROR_NETWORK_OFFLINE">
       <div id="captive-portal-title" i18n-content="captivePortalTitle"
           class="error-title
                  show-with-error-state-portal
diff --git a/chrome/browser/resources/file_manager/js/file_copy_manager.js b/chrome/browser/resources/file_manager/js/file_copy_manager.js
index 9fe76ce..766c251 100644
--- a/chrome/browser/resources/file_manager/js/file_copy_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_copy_manager.js
@@ -693,6 +693,8 @@
     task, successCallback, errorCallback) {
   if (task.zip)
     this.serviceZipTask_(task, successCallback, errorCallback);
+  else if (task.move)
+    this.serviceMoveTask_(task, successCallback, errorCallback);
   else
     this.serviceCopyTask_(task, successCallback, errorCallback);
 };
@@ -701,7 +703,6 @@
  * Service all entries in the copy (and move) task.
  * Note: this method contains also the operation of "Move" due to historical
  * reason.
- * TODO(hidehiko): extract "move" related code into another method.
  *
  * @param {FileCopyManager.Task} task A copy task to be run.
  * @param {function()} successCallback On success.
@@ -753,7 +754,7 @@
 };
 
 /**
- * Service the next entry in a given task.
+ * Copies the next entry in a given task.
  * TODO(olege): Refactor this method into a separate class.
  *
  * @param {FileManager.Task} task A task.
@@ -817,28 +818,11 @@
     onCopyCompleteBase(targetEntry, 0);
   };
 
-  var onFilesystemMoveComplete = function(sourceEntry, targetEntry) {
-    self.sendOperationEvent_('moved', [sourceEntry, targetEntry]);
-    onCopyCompleteBase(targetEntry, 0);
-  };
-
   var onFilesystemError = function(err) {
     onError('FILESYSTEM_ERROR', err);
   };
 
   var onDeduplicated = function(targetRelativePath) {
-    if (task.move) {
-      targetDirEntry.getDirectory(
-          PathUtil.dirname(targetRelativePath), {create: false},
-          function(dirEntry) {
-            sourceEntry.moveTo(dirEntry, PathUtil.basename(targetRelativePath),
-                               onFilesystemMoveComplete.bind(self, sourceEntry),
-                               onFilesystemError);
-          },
-          onFilesystemError);
-      return;
-    }
-
     // TODO(benchan): drive::FileSystem has not implemented directory copy,
     // and thus we only call FileEntry.copyTo() for files. Revisit this
     // code when drive::FileSystem supports directory copy.
@@ -986,6 +970,106 @@
 };
 
 /**
+ * Moves all entries in the task.
+ *
+ * @param {FileCopyManager.Task} task A move task to be run.
+ * @param {function()} successCallback On success.
+ * @param {function(FileCopyManager.Error)} errorCallback On error.
+ * @private
+ */
+FileCopyManager.prototype.serviceMoveTask_ = function(
+    task, successCallback, errorCallback) {
+  this.serviceNextMoveTaskEntry_(
+      task,
+      (function onCompleted() {
+        // We should not dispatch a PROGRESS event when there is no pending
+        // items in the task.
+        if (task.pendingDirectories.length + task.pendingFiles.length == 0) {
+          successCallback();
+          return;
+        }
+
+        // Move the next entry.
+        this.sendProgressEvent_('PROGRESS');
+        this.serviceNextMoveTaskEntry_(
+            task, onCompleted.bind(this), errorCallback);
+      }).bind(this),
+      errorCallback);
+};
+
+/**
+ * Moves the next entry in a given task.
+ *
+ * Implementation note: This method can be simplified more. For example, in
+ * Task.setEntries(), the flag to recurse is set to false for move task,
+ * so that all the entries' originalSourcePath should be
+ * dirname(sourceEntry.fullPath).
+ * Thus, targetRelativePath should contain exact one component. Also we can
+ * skip applyRenames, because the destination directory always should be
+ * task.targetDirEntry.
+ * The unnecessary complexity is due to historical reason.
+ * TODO(hidehiko): Refactor this method.
+ *
+ * @param {FileManager.Task} task A move task.
+ * @param {function()} successCallback On success.
+ * @param {function(FileCopyManager.Error)} errorCallback On error.
+ * @private
+ */
+FileCopyManager.prototype.serviceNextMoveTaskEntry_ = function(
+    task, successCallback, errorCallback) {
+  if (this.maybeCancel_())
+    return;
+
+  var self = this;
+  var sourceEntry = task.getNextEntry();
+
+  if (!sourceEntry) {
+    // All entries in this task have been copied.
+    successCallback();
+    return;
+  }
+
+  var onError = function(reason, data) {
+    self.log_('serviceNextMoveTaskEntry error: ' + reason + ':', data);
+    errorCallback(new FileCopyManager.Error(reason, data));
+  };
+
+  // |sourceEntry.originalSourcePath| is set in util.recurseAndResolveEntries.
+  var sourcePath = sourceEntry.originalSourcePath;
+  if (sourceEntry.fullPath.substr(0, sourcePath.length) != sourcePath) {
+    // We found an entry in the list that is not relative to the base source
+    // path, something is wrong.
+    onError('UNEXPECTED_SOURCE_FILE', sourceEntry.fullPath);
+    return;
+  }
+
+  util.deduplicatePath(
+      task.targetDirEntry,
+      task.applyRenames(sourceEntry.fullPath.substr(sourcePath.length + 1)),
+      function(targetRelativePath) {
+        var onFilesystemError = function(err) {
+          onError('FILESYSTEM_ERROR', err);
+        };
+
+        task.targetDirEntry.getDirectory(
+            PathUtil.dirname(targetRelativePath), {create: false},
+            function(dirEntry) {
+              sourceEntry.moveTo(
+                  dirEntry, PathUtil.basename(targetRelativePath),
+                  function(targetEntry) {
+                    self.sendOperationEvent_(
+                        'moved', [sourceEntry, targetEntry]);
+                    task.markEntryComplete(targetEntry, 0);
+                    successCallback();
+                  },
+                  onFilesystemError);
+            },
+            onFilesystemError);
+      },
+      onError);
+};
+
+/**
  * Service a zip file creation task.
  *
  * @param {FileCopyManager.Task} task A zip task to be run.
@@ -1083,7 +1167,7 @@
         reportedProgress = progress.loaded;
       };
 
-      writer.onwriteend = function() {
+      writer.onwrite = function() {
         sourceEntry.getMetadata(function(metadata) {
           chrome.fileBrowserPrivate.setLastModified(targetEntry.toURL(),
               '' + Math.round(metadata.modificationTime.getTime() / 1000));
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 66cb272..fc02338 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -637,13 +637,13 @@
 
     var doc = this.document_;
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'newfolder',
+    CommandUtil.registerCommand(doc, 'newfolder',
         Commands.newFolderCommand, this, this.directoryModel_);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'newwindow',
+    CommandUtil.registerCommand(doc, 'newwindow',
         Commands.newWindowCommand, this, this.directoryModel_);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'change-default-app',
+    CommandUtil.registerCommand(doc, 'change-default-app',
         Commands.changeDefaultAppCommand, this);
 
     CommandUtil.registerCommand(this.volumeList_, 'unmount',
@@ -652,58 +652,53 @@
     CommandUtil.registerCommand(this.volumeList_, 'import-photos',
         Commands.importCommand, this.volumeList_);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'format',
+    CommandUtil.registerCommand(doc, 'format',
         Commands.formatCommand, this.volumeList_, this,
         this.directoryModel_);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'delete',
+    CommandUtil.registerCommand(doc, 'delete',
         Commands.deleteFileCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'rename',
+    CommandUtil.registerCommand(doc, 'rename',
         Commands.renameFileCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'volume-help',
+    CommandUtil.registerCommand(doc, 'volume-help',
         Commands.volumeHelpCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'drive-buy-more-space',
+    CommandUtil.registerCommand(doc, 'drive-buy-more-space',
         Commands.driveBuySpaceCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_,
-        'drive-clear-local-cache', Commands.driveClearCacheCommand, this);
+    CommandUtil.registerCommand(doc, 'drive-clear-local-cache',
+        Commands.driveClearCacheCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'drive-go-to-drive',
+    CommandUtil.registerCommand(doc, 'drive-go-to-drive',
         Commands.driveGoToDriveCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'paste',
+    CommandUtil.registerCommand(doc, 'paste',
         Commands.pasteFileCommand, doc, this.fileTransferController_);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'open-with',
+    CommandUtil.registerCommand(doc, 'open-with',
         Commands.openWithCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'toggle-pinned',
+    CommandUtil.registerCommand(doc, 'toggle-pinned',
         Commands.togglePinnedCommand, this);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'zip-selection',
+    CommandUtil.registerCommand(doc, 'zip-selection',
         Commands.zipSelectionCommand, this, this.directoryModel_);
 
-    CommandUtil.registerCommand(this.dialogContainer_, 'share',
-        Commands.shareCommand, this);
+    CommandUtil.registerCommand(doc, 'share', Commands.shareCommand, this);
+    CommandUtil.registerCommand(doc, 'create-folder-shortcut',
+        Commands.createFolderShortcutCommand, this);
+    CommandUtil.registerCommand(doc, 'remove-folder-shortcut',
+        Commands.removeFolderShortcutCommand, this, this.volumeList_);
 
-    CommandUtil.registerCommand(this.dialogContainer_,
-        'create-folder-shortcut', Commands.createFolderShortcutCommand, this);
-
-    CommandUtil.registerCommand(this.dialogContainer_,
-        'remove-folder-shortcut', Commands.removeFolderShortcutCommand, this,
-        this.volumeList_);
-
-    CommandUtil.registerCommand(this.dialogContainer_, 'search',
-        Commands.searchCommand, this,
+    CommandUtil.registerCommand(doc, 'search', Commands.searchCommand, this,
         this.dialogDom_.querySelector('#search-box'));
 
     // Register commands with CTRL-1..9 shortcuts for switching between
     // volumes.
     for (var i = 1; i <= 9; i++) {
-      CommandUtil.registerCommand(this.dialogContainer_,
+      CommandUtil.registerCommand(doc,
                                   'volume-switch-' + i,
                                   Commands.volumeSwitchCommand,
                                   this.volumeList_,
diff --git a/chrome/browser/resources/gesture_config.js b/chrome/browser/resources/gesture_config.js
index e38baa9..1e201b2 100644
--- a/chrome/browser/resources/gesture_config.js
+++ b/chrome/browser/resources/gesture_config.js
@@ -331,7 +331,12 @@
     },
     {
       key: 'minimum_threshold_start',
-      label: 'Start overscroll gesture after scrolling',
+      label: 'Start overscroll gesture (horizontal)',
+      units: 'pixels'
+    },
+    {
+      key: 'vertical_threshold_start',
+      label: 'Start overscroll gesture (vertical)',
       units: 'pixels'
     },
     {
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index e63fbaa..23272e0 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -391,8 +391,7 @@
 
 
 /**
- * Renders the attribution if the image is present and loadable.  Otherwise
- * hides it.
+ * Renders the attribution if the URL is present, otherwise hides it.
  * @param {string} url The URL of the attribution image, if any.
  * @private
  */
@@ -401,18 +400,14 @@
     setAttributionVisibility_(false);
     return;
   }
-  var attributionImage = new Image();
-  attributionImage.onload = function() {
-    var oldAttributionImage = attribution.querySelector('img');
-    if (oldAttributionImage)
-      removeNode(oldAttributionImage);
+
+  var attributionImage = attribution.querySelector('img');
+  if (!attributionImage) {
+    attributionImage = new Image();
     attribution.appendChild(attributionImage);
-    setAttributionVisibility_(true);
-  };
-  attributionImage.onerror = function() {
-    setAttributionVisibility_(false);
-  };
-  attributionImage.src = url;
+  }
+  attributionImage.style.content = url;
+  setAttributionVisibility_(true);
 }
 
 
diff --git a/chrome/browser/resources/net_internals/waterfall_row.js b/chrome/browser/resources/net_internals/waterfall_row.js
index d24595a..d17ebc3 100644
--- a/chrome/browser/resources/net_internals/waterfall_row.js
+++ b/chrome/browser/resources/net_internals/waterfall_row.js
@@ -41,15 +41,23 @@
         addTextNode(this.urlCell_, this.description_);
       }
 
-      this.barCell_.innerHTML = '';
+      this.rowCell_.innerHTML = '';
+
       var matchingEventPairs = this.findLogEntryPairs_(this.eventTypes_);
 
       // Creates the spacing in the beginning to show start time.
       var startTime = this.parentView_.getStartTime();
       var sourceEntryStartTime = this.sourceEntry_.getStartTime();
       var delay = sourceEntryStartTime - startTime;
-      var scaledMinTime = delay * scale;
-      this.createNode_(this.barCell_, scaledMinTime, 'padding');
+      var frontNode = addNode(this.rowCell_, 'div');
+      setNodeWidth(frontNode, delay * scale);
+
+      var barCell = addNode(this.rowCell_, 'div');
+      barCell.classList.add('waterfall-view-bar');
+
+      if (this.sourceEntry_.isError()) {
+        barCell.classList.add('error');
+      }
 
       var currentEnd = sourceEntryStartTime;
       for (var i = 0; i < matchingEventPairs.length; ++i) {
@@ -64,20 +72,22 @@
         // Handles the spaces between events.
         if (currentEnd < event.startTime) {
           var eventDuration = event.startTime - currentEnd;
-          var eventWidth = eventDuration * scale;
-          this.createNode_(this.barCell_, eventWidth, this.type_);
+          var padNode = this.createNode_(
+              barCell, eventDuration, this.type_, 'source');
         }
 
         // Creates event bars.
         var eventType = eventTypeToCssClass_(EventTypeNames[event.eventType]);
-        var eventWidth = event.eventDuration * scale;
-        this.createNode_(this.barCell_, eventWidth, eventType);
+        var eventNode = this.createNode_(
+            barCell, event.eventDuration, eventType, event);
         currentEnd = event.startTime + event.eventDuration;
       }
+
       // Creates a bar for the part after the last event.
       if (this.getEndTime() > currentEnd) {
-        var endWidth = (this.getEndTime() - currentEnd) * scale;
-        this.createNode_(this.barCell_, endWidth, this.type_);
+        var endDuration = (this.getEndTime() - currentEnd);
+        var endNode = this.createNode_(
+            barCell, endDuration, this.type_, 'source');
       }
     },
 
@@ -89,11 +99,84 @@
       return this.sourceEntry_.getEndTime();
     },
 
+    clearPopup_: function(parentNode) {
+      parentNode.innerHTML = '';
+    },
+
+    // TODO(viona): Create popup at mouse location.
+    createPopup_: function(parentNode, event, eventType, duration, mouse) {
+      var tableStart = this.parentView_.getStartTime();
+
+      var newPopup = addNode(parentNode, 'div');
+      newPopup.classList.add('waterfall-view-popup');
+
+      var popupList = addNode(newPopup, 'ul');
+      popupList.classList.add('waterfall-view-popup-list');
+
+      this.createPopupItem_(
+          popupList, 'Event Type', eventType);
+      this.createPopupItem_(
+          popupList, 'Event Duration', duration.toFixed(0) + 'ms');
+
+      if (event != 'source') {
+        this.createPopupItem_(
+            popupList, 'Event Start Time', event.startTime - tableStart + 'ms');
+        this.createPopupItem_(
+            popupList, 'Event End Time', event.endTime - tableStart + 'ms');
+      }
+
+      this.createPopupItem_(
+          popupList, 'Source Start Time',
+          this.getStartTime() - tableStart + 'ms');
+      this.createPopupItem_(
+          popupList, 'Source End Time', this.getEndTime() - tableStart + 'ms');
+      this.createPopupItem_(
+          popupList, 'Source ID', this.sourceEntry_.getSourceId());
+      var urlListItem = this.createPopupItem_(
+          popupList, 'Source Description: ', this.description_);
+
+      var viewWidth = $(WaterfallView.MAIN_BOX_ID).offsetWidth;
+      // Controls the overflow of extremely long URLs by cropping to window.
+      if (urlListItem.offsetWidth > viewWidth) {
+        urlListItem.style.width = viewWidth + 'px';
+      }
+      urlListItem.classList.add('waterfall-view-popup-list-url-item');
+
+      this.createPopupItem_(
+          popupList, 'Has Error', this.sourceEntry_.isError());
+
+      // Fixes cases where the popup appears 'off-screen'.
+      var popupLeft = mouse.pageX + $(WaterfallView.MAIN_BOX_ID).scrollLeft;
+      var popupRight = popupLeft + newPopup.offsetWidth;
+      var viewRight = viewWidth + $(WaterfallView.MAIN_BOX_ID).scrollLeft;
+
+      if (viewRight - popupRight < 0) {
+        popupLeft = viewRight - newPopup.offsetWidth;
+      }
+      newPopup.style.left = popupLeft + 'px';
+
+      var popupTop = mouse.pageY + $(WaterfallView.MAIN_BOX_ID).scrollTop;
+      var popupBottom = popupTop + newPopup.offsetHeight;
+      var viewBottom = $(WaterfallView.MAIN_BOX_ID).offsetHeight +
+          $(WaterfallView.MAIN_BOX_ID).scrollTop;
+
+      if (viewBottom - popupBottom < 0) {
+        popupTop = viewBottom - newPopup.offsetHeight;
+      }
+      newPopup.style.top = popupTop + 'px';
+    },
+
+    createPopupItem_: function(parentPopup, key, popupInformation) {
+      var popupItem = addNode(parentPopup, 'li');
+      addTextNode(popupItem, key + ': ' + popupInformation);
+      return popupItem;
+    },
+
     createRow_: function() {
       // Create a row.
       var tr = addNode($(WaterfallView.TBODY_ID), 'tr');
       tr._id = this.sourceEntry_.getSourceId();
-      this.row_ = tr;
+      this.tableRow = tr;
 
       var idCell = addNode(tr, 'td');
       addTextNode(idCell, this.sourceEntry_.getSourceId());
@@ -103,22 +186,30 @@
       addTextNode(urlCell, this.description_);
       this.urlCell_ = urlCell;
 
-      // Creates the offset for where the color bar appears.
-      var barCell = addNode(tr, 'td');
-      barCell.classList.add('waterfall-view-row');
-      this.barCell_ = barCell;
+      // Creates the color bar.
 
-      this.updateRow();
+      var rowCell = addNode(tr, 'td');
+      rowCell.classList.add('waterfall-view-row');
+      this.rowCell_ = rowCell;
 
       var sourceTypeString = this.sourceEntry_.getSourceTypeString();
       this.type_ = eventTypeToCssClass_(sourceTypeString);
+
+      this.updateRow();
     },
 
     // Generates nodes.
-    createNode_: function(parentNode, durationScaled, eventType) {
+    createNode_: function(parentNode, duration, eventType, event) {
+      var scale = this.parentView_.getScaleFactor();
       var newNode = addNode(parentNode, 'div');
-      setNodeWidth(newNode, durationScaled);
-      newNode.classList.add('waterfall-view-row-' + eventType);
+      setNodeWidth(newNode, duration * scale);
+      newNode.classList.add(eventType);
+      newNode.addEventListener(
+          'mouseover',
+          this.createPopup_.bind(this, newNode, event, eventType, duration),
+          true);
+      newNode.addEventListener(
+          'mouseout', this.clearPopup_.bind(this, newNode), true);
       return newNode;
     },
 
@@ -135,24 +226,24 @@
       var startEntries = {};
       var entries = this.sourceEntry_.getLogEntries();
       for (var i = 0; i < entries.length; ++i) {
-        var type = entries[i].type;
+        var currentEntry = entries[i];
+        var type = currentEntry.type;
         if (typeList.indexOf(type) < 0) {
           continue;
         }
-        if (entries[i].phase == EventPhase.PHASE_BEGIN) {
-          startEntries[type] = entries[i];
+        if (currentEntry.phase == EventPhase.PHASE_BEGIN) {
+          startEntries[type] = currentEntry;
         }
-        if (startEntries[type] && entries[i].phase == EventPhase.PHASE_END) {
+        if (startEntries[type] && currentEntry.phase == EventPhase.PHASE_END) {
           var event = {
             startEntry: startEntries[type],
-            endEntry: entries[i],
+            endEntry: currentEntry,
           };
           matchingEventPairs.push(event);
         }
       }
       return matchingEventPairs;
     },
-
   };
 
   function eventTypeToCssClass_(rawEventType) {
diff --git a/chrome/browser/resources/net_internals/waterfall_view.css b/chrome/browser/resources/net_internals/waterfall_view.css
index 2d1b636..14a0f60c 100644
--- a/chrome/browser/resources/net_internals/waterfall_view.css
+++ b/chrome/browser/resources/net_internals/waterfall_view.css
@@ -3,6 +3,16 @@
  * found in the LICENSE file.
  */
 
+#waterfall-view-controls {
+  background-color: #FFF;
+  border-color: #000;
+  border-style: solid;
+  border-width: 1px;
+  padding-left: 5px;
+  position: fixed;
+  top: 40px;
+}
+
 .waterfall-view-url-cell {
   display: inline-block;
   overflow: hidden;
@@ -17,44 +27,101 @@
 
 .waterfall-view-row * {
   display: inline-block;
-  height: 15px;
-  opacity: 0.5;
   padding-top: 0;
 }
 
-.waterfall-view-row [class*='http-stream-request'] {
-  background-color: #000;
+.waterfall-view-bar > * {
+  height: 15px;
 }
 
-.waterfall-view-row [class*='http-transaction-read-headers'] {
-  background-color: rgb(255, 0, 0);
+.waterfall-view-popup-list {
+  background-color: rgba(255, 255, 255, 0.8);
+  border-color: #000;
+  border-style: solid;
+  border-width: 2px;
+  color: #000;
+  padding-right: 1em;
+  z-index: -1;
 }
 
-.waterfall-view-row [class*='url-request'] {
-  background-color: rgb(0, 0, 255);
+.waterfall-view-popup-list > li {
+  display: list-item;
+}
+.waterfall-view-popup-list-url-item {
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
-.waterfall-view-row [class*='http-stream-job'] {
-  background-color: rgb(0, 255, 0);
+.waterfall-view-bar.error {
+  border-color: rgba(255, 0, 0, 0.8);
+  border-style: solid;
+  border-width: 1px;
+  height: 18px;
 }
 
-.waterfall-view-row [class*='proxy-service'] {
-  background-color: rgb(122, 122, 0);
+.waterfall-view-row .http-stream-request {
+  background: -webkit-linear-gradient(top, #EEE, rgba(0, 0, 0, 0.5));
 }
 
-.waterfall-view-row [class*='socket-pool-connect-job'] {
-  background-color: rgb(0, 122, 122);
+.waterfall-view-row .http-stream-request-bound-to-job {
+  background: -webkit-linear-gradient(top, #EEE, rgba(200, 200, 200, 0.5));
 }
 
-.waterfall-view-row [class*='host-resolver-impl'] {
-  background-color: rgb(122, 0, 122);
+.waterfall-view-row .http-transaction-read-headers {
+  background: -webkit-linear-gradient(top, #EEE, rgba(255, 0, 0, 0.5));
 }
 
-.waterfall-view-row [class*='socket'] {
-  background-color: rgb(122, 178, 0);
+.waterfall-view-row .url-request {
+  background: -webkit-linear-gradient(top, #EEE, rgba(0, 0, 255, 0.5));
 }
 
-.waterfall-popup {
-  display: block;
-  font-size: 15px;
+.waterfall-view-row .http-stream-job {
+  background: -webkit-linear-gradient(top, #EEE, rgba(0, 255, 0, 0.5));
+}
+
+.waterfall-view-row .proxy-service {
+  background: -webkit-linear-gradient(top, #EEE, rgba(122, 122, 0, 0.5));
+}
+
+.waterfall-view-row .socket-pool-connect-job {
+  background: -webkit-linear-gradient(top, #EEE, rgba(0, 122, 122, 0.5));
+}
+
+.waterfall-view-row .host-resolver-impl {
+  background: -webkit-linear-gradient(top, #EEE, rgba(122, 0, 122, 0.5));
+}
+
+.waterfall-view-row .socket {
+  background: -webkit-linear-gradient(top, #EEE, rgba(122, 178, 0, 0.5));
+}
+
+.waterfall-view-row .tcp-connect {
+  background: -webkit-linear-gradient(top, #EEE, rgba(0, 178, 122, 0.5));
+}
+
+.waterfall-view-row .ssl-connect {
+  background: -webkit-linear-gradient(top, #EEE, rgba(55, 122, 178, 0.5));
+}
+
+.waterfall-view-popup {
+  display: inline-block;
+  position: absolute;
+}
+
+.waterfall-view-time-scale-row {
+  white-space: nowrap;
+}
+
+.waterfall-view-time-scale {
+  border-color: #000;
+  border-left-style: solid;
+  border-width: 1px;
+  box-sizing: border-box;
+  display: inline-block;
+  height: 15px;
+}
+
+/* Colors every fifth bar red. */
+.waterfall-view-time-scale-special {
+  border-color: rgb(255, 0, 0);
 }
diff --git a/chrome/browser/resources/net_internals/waterfall_view.html b/chrome/browser/resources/net_internals/waterfall_view.html
index d605122..ac88a7a 100644
--- a/chrome/browser/resources/net_internals/waterfall_view.html
+++ b/chrome/browser/resources/net_internals/waterfall_view.html
@@ -1,16 +1,18 @@
 <!-- =============== Events Waterfall View ================= -->
 <div id=waterfall-view-tab-content class=content-box>
   <div>
-    Information:
-    <p>Currently only captures URL Request events. Blue represents URL
-    Requests. Red represents Header Reads. Grey represents Stream Requests.
-    <input id=waterfall-view-time-scale type="button"
-        value="Scale To Fit Window">
+    <div id=waterfall-view-controls>
+      Start Time: <input id=waterfall-view-start-input type=number min=0 value=0>
+      End Time: <input id=waterfall-view-end-input type=number min=0>
+      <input id=waterfall-view-adjust-to-window type=button value="Fit Range in Window">
+    </div>
+    <p>
     <table id=waterfall-view-source-list-table>
       <thead>
       <tr>
         <td id=waterfall-view-source-id>ID</td>
         <td id=waterfall-view-source-header>Source</td>
+        <td id=waterfall-view-time-scale-labels></td>
       </tr>
       </thead>
       <!-- Events Waterfall table body: This is where request rows go into -->
diff --git a/chrome/browser/resources/net_internals/waterfall_view.js b/chrome/browser/resources/net_internals/waterfall_view.js
index 2f1b0ed..aac15b6 100644
--- a/chrome/browser/resources/net_internals/waterfall_view.js
+++ b/chrome/browser/resources/net_internals/waterfall_view.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// TODO(viona): Write a README document/instructions.
+
 /** This view displays the event waterfall. */
 var WaterfallView = (function() {
   'use strict';
@@ -22,7 +24,10 @@
 
     // For adjusting the range of view.
     $(WaterfallView.SCALE_ID).addEventListener(
-        'click', this.adjustToWindow_.bind(this), true);
+        'click', this.setStartEndTimes_.bind(this), true);
+
+    $(WaterfallView.MAIN_BOX_ID).addEventListener(
+        'mousewheel', this.scrollToZoom_.bind(this), true);
 
     this.initializeSourceList_();
   }
@@ -34,9 +39,22 @@
   // IDs for special HTML elements in events_waterfall_view.html.
   WaterfallView.MAIN_BOX_ID = 'waterfall-view-tab-content';
   WaterfallView.TBODY_ID = 'waterfall-view-source-list-tbody';
-  WaterfallView.SCALE_ID = 'waterfall-view-time-scale';
+  WaterfallView.SCALE_ID = 'waterfall-view-adjust-to-window';
   WaterfallView.ID_HEADER_ID = 'waterfall-view-source-id';
   WaterfallView.SOURCE_HEADER_ID = 'waterfall-view-source-header';
+  WaterfallView.TIME_SCALE_HEADER_ID = 'waterfall-view-time-scale-labels';
+  WaterfallView.TIME_RANGE_ID = 'waterfall-view-time-range-submit';
+  WaterfallView.START_TIME_ID = 'waterfall-view-start-input';
+  WaterfallView.END_TIME_ID = 'waterfall-view-end-input';
+
+  // The number of units mouse wheel deltas increase for each tick of the
+  // wheel.
+  var MOUSE_WHEEL_UNITS_PER_CLICK = 120;
+
+  // Amount we zoom for one vertical tick of the mouse wheel, as a ratio.
+  var MOUSE_WHEEL_ZOOM_RATE = 1.25;
+  // Amount we scroll for one horizontal tick of the mouse wheel, in pixels.
+  var MOUSE_WHEEL_SCROLL_RATE = MOUSE_WHEEL_UNITS_PER_CLICK;
 
   cr.addSingletonGetter(WaterfallView);
 
@@ -55,24 +73,29 @@
         this.startTime_ = timeutil.convertTimeTicksToTime(logEntries[0].time);
         // Initial scale factor.
         this.scaleFactor_ = 0.1;
+        this.eventsList_ = this.createEventsList_();
       }
       for (var i = 0; i < sourceEntries.length; ++i) {
         var sourceEntry = sourceEntries[i];
         var id = sourceEntry.getSourceId();
-        if (sourceEntry.getSourceType() == EventSourceType.URL_REQUEST) {
-          var row = this.sourceIdToRowMap_[id];
-          if (!row) {
-            var importantEventTypes = [
-                EventType.HTTP_STREAM_REQUEST,
-                EventType.HTTP_TRANSACTION_READ_HEADERS
-            ];
-            this.sourceIdToRowMap_[id] =
-                new WaterfallRow(this, sourceEntry, importantEventTypes);
-          } else {
-            row.onSourceUpdated();
+        for (var j = 0; j < this.eventsList_.length; ++j) {
+          var eventObject = this.eventsList_[j];
+          if (sourceEntry.getSourceType() == eventObject.mainEvent) {
+            var row = this.sourceIdToRowMap_[id];
+            if (!row) {
+              var newRow = new WaterfallRow(
+                  this, sourceEntry, eventObject.importantEventTypes);
+              if (newRow == undefined) {
+                console.log(sourceEntry);
+              }
+              this.sourceIdToRowMap_[id] = newRow;
+            } else {
+              row.onSourceUpdated();
+            }
           }
         }
       }
+      this.updateTimeScale_(this.scaleFactor_);
     },
 
     onAllSourceEntriesDeleted: function() {
@@ -103,28 +126,65 @@
     },
 
     /**
-     * Changes width of the bars such that horizontally, everything fits into
-     * the user's current window size.
-     * TODO(viona): Deal with the magic number.
+     * Changes scroll position of the window such that horizontally, everything
+     * within the specified range fits into the user's viewport.
+     * TODO(viona): Find a way to get rid of the magic number.
      */
-    adjustToWindow_: function() {
-      var usedWidth = $(WaterfallView.SOURCE_HEADER_ID).offsetWidth +
-          $(WaterfallView.ID_HEADER_ID).offsetWidth;
-      var availableWidth = ($(WaterfallView.MAIN_BOX_ID).offsetWidth -
-          usedWidth - 50);
-      if (availableWidth <= 0) {
-        availableWidth = 1;
-      }
+    adjustToWindow_: function(windowStart, windowEnd) {
+      var maxWidth = $(WaterfallView.MAIN_BOX_ID).offsetWidth - 50;
+      $(WaterfallView.TBODY_ID).width = maxWidth + 'px';
       var totalDuration = 0;
-      for (var id in this.sourceIdToRowMap_) {
-        var row = this.sourceIdToRowMap_[id];
-        var rowDuration = row.getEndTime() - this.startTime_;
-        if (totalDuration < rowDuration) {
-          totalDuration = rowDuration;
+      if (windowEnd != -1) {
+        totalDuration = windowEnd - windowStart;
+      } else {
+        for (var id in this.sourceIdToRowMap_) {
+          var row = this.sourceIdToRowMap_[id];
+          var rowDuration = row.getEndTime() - this.startTime_;
+          if (totalDuration < rowDuration && !row.hide) {
+            totalDuration = rowDuration;
+          }
         }
       }
-      var scaleFactor = availableWidth / totalDuration;
-      this.scaleAll_(scaleFactor);
+      if (totalDuration <= 0) {
+        return;
+      }
+      this.scaleAll_(maxWidth / totalDuration);
+      var waterfallLeft = $(WaterfallView.TIME_SCALE_HEADER_ID).offsetLeft;
+      $(WaterfallView.MAIN_BOX_ID).scrollLeft =
+          windowStart * this.scaleFactor_ + waterfallLeft;
+    },
+
+    // Updates the time tick indicators.
+    updateTimeScale_: function(scaleFactor) {
+      var timePerTick = 1;
+      var minTickDistance = 20;
+
+      $(WaterfallView.TIME_SCALE_HEADER_ID).innerHTML = '';
+
+      // Holder provides environment to prevent wrapping.
+      var timeTickRow = addNode($(WaterfallView.TIME_SCALE_HEADER_ID), 'div');
+      timeTickRow.classList.add('waterfall-view-time-scale-row');
+
+      var availableWidth = $(WaterfallView.TBODY_ID).clientWidth;
+      var tickDistance = scaleFactor * timePerTick;
+
+      while (tickDistance < minTickDistance) {
+        timePerTick = timePerTick * 10;
+        tickDistance = scaleFactor * timePerTick;
+      }
+
+      var tickCount = availableWidth / tickDistance;
+      for (var i = 0; i < tickCount; ++i) {
+        var timeCell = addNode(timeTickRow, 'div');
+        setNodeWidth(timeCell, tickDistance);
+        timeCell.classList.add('waterfall-view-time-scale');
+        timeCell.title = i * timePerTick + ' to ' +
+           (i + 1) * timePerTick + ' ms';
+        // Red marker for every 5th bar.
+        if (i % 5 == 0) {
+          timeCell.classList.add('waterfall-view-time-scale-special');
+        }
+      }
     },
 
     /**
@@ -136,6 +196,76 @@
         var row = this.sourceIdToRowMap_[id];
         row.updateRow();
       }
+      this.updateTimeScale_(scaleFactor);
+    },
+
+    scrollToZoom_: function(event) {
+      // To use scrolling to control zoom, hold down the alt key and scroll.
+      if ('wheelDelta' in event && event.altKey) {
+        var zoomFactor = Math.pow(MOUSE_WHEEL_ZOOM_RATE,
+             event.wheelDeltaY / MOUSE_WHEEL_UNITS_PER_CLICK);
+
+        var waterfallLeft = $(WaterfallView.TIME_SCALE_HEADER_ID).offsetLeft;
+        var oldCursorPosition = event.pageX +
+            $(WaterfallView.MAIN_BOX_ID).scrollLeft;
+        var oldCursorPositionInTable = oldCursorPosition - waterfallLeft;
+
+        this.scaleAll_(this.scaleFactor_ * zoomFactor);
+
+        // Shifts the view when scrolling. newScroll could be less than 0 or
+        // more than the maximum scroll position, but both cases are handled
+        // by the inbuilt scrollLeft implementation.
+        var newScroll =
+            oldCursorPositionInTable * zoomFactor - event.pageX + waterfallLeft;
+        $(WaterfallView.MAIN_BOX_ID).scrollLeft = newScroll;
+      }
+    },
+
+    // Parses user input, then calls adjustToWindow to shift that into view.
+    setStartEndTimes_: function() {
+      var windowStart = parseInt($(WaterfallView.START_TIME_ID).value);
+      var windowEnd = parseInt($(WaterfallView.END_TIME_ID).value);
+      if ($(WaterfallView.END_TIME_ID).value == '') {
+        windowEnd = -1;
+      }
+      if ($(WaterfallView.START_TIME_ID).value == '') {
+        windowStart = 0;
+      }
+      this.adjustToWindow_(windowStart, windowEnd);
+    },
+
+    // Provides a structure that can be used to define source entry types and
+    // the log entries that are of interest.
+    createEventsList_: function() {
+      var eventsList = [];
+      // Creating list of events.
+      // TODO(viona): This is hard-coded. Consider user-input.
+      //              Also, work on getting socket information inlined in the
+      //              relevant URL_REQUEST events.
+      var urlRequestEvents = [
+        EventType.HTTP_STREAM_REQUEST,
+        EventType.HTTP_STREAM_REQUEST_BOUND_TO_JOB,
+        EventType.HTTP_TRANSACTION_READ_HEADERS
+      ];
+
+      eventsList.push(this.createEventTypeObjects_(
+          EventSourceType.URL_REQUEST, urlRequestEvents));
+
+      var httpStreamJobEvents = [EventType.PROXY_SERVICE];
+      eventsList.push(this.createEventTypeObjects_(
+          EventSourceType.HTTP_STREAM_JOB, httpStreamJobEvents));
+
+      return eventsList;
+    },
+
+    // Creates objects that can be used to define source entry types and
+    // the log entries that are of interest.
+    createEventTypeObjects_: function(mainEventType, eventTypesList) {
+      var eventTypeObject = {
+        mainEvent: mainEventType,
+        importantEventTypes: eventTypesList
+      };
+      return eventTypeObject;
     },
   };
 
diff --git a/chrome/browser/resources/print_preview/print_preview.css b/chrome/browser/resources/print_preview/print_preview.css
index ed5424c..9369e1a 100644
--- a/chrome/browser/resources/print_preview/print_preview.css
+++ b/chrome/browser/resources/print_preview/print_preview.css
@@ -295,3 +295,9 @@
   height: 100%;
   position: relative;
 }
+
+html:not(.focus-outline-visible)
+:enabled:focus:-webkit-any(input[type='checkbox'],input[type='radio'],button) {
+  /* Cancel border-color for :focus specified in widgets.css. */
+  border-color: rgba(0,0,0,0.25);
+}
diff --git a/chrome/browser/resources/print_preview/print_preview.html b/chrome/browser/resources/print_preview/print_preview.html
index e246549..1133332 100644
--- a/chrome/browser/resources/print_preview/print_preview.html
+++ b/chrome/browser/resources/print_preview/print_preview.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html i18n-values="dir:textdirection;" id="print-preview">
+<html i18n-values="dir:textdirection;" id="print-preview" class="focus-outline-visible">
 
 <head>
   <meta charset="utf-8">
@@ -29,6 +29,8 @@
   <script src="chrome://print/strings.js"></script>
   <script src="chrome://resources/js/cr.js"></script>
   <script src="chrome://resources/js/cr/event_target.js"></script>
+  <script src="chrome://resources/js/cr/ui.js"></script>
+  <script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
   <script src="chrome://resources/js/event_tracker.js"></script>
   <script src="chrome://resources/js/local_strings.js"></script>
   <script src="chrome://resources/js/util.js"></script>
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index 0fc07b7..4f906bd 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -227,6 +227,7 @@
       }
       this.nativeLayer_.startGetInitialSettings();
       this.destinationStore_.startLoadLocalDestinations();
+      cr.ui.FocusOutlineManager.forDocument(document);
     },
 
     /** @override */
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index 5c5a781..1f67d5c 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -177,18 +177,22 @@
       return;
     }
 
+    bool malware_killswitch_on = database_manager_->IsMalwareKillSwitchOn();
+
     BrowserThread::PostTask(
         BrowserThread::UI,
         FROM_HERE,
-        base::Bind(&ShouldClassifyUrlRequest::CheckCache, this));
+        base::Bind(&ShouldClassifyUrlRequest::CheckCache, this,
+                   malware_killswitch_on));
   }
 
-  void CheckCache() {
+  void CheckCache(bool malware_killswitch_on) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     if (canceled_) {
       return;
     }
 
+    host_->SetMalwareKillSwitch(malware_killswitch_on);
     // If result is cached, we don't want to run classification again
     bool is_phishing;
     if (csd_service_->GetValidCachedResult(params_.url, &is_phishing)) {
@@ -251,6 +255,7 @@
       csd_service_(NULL),
       weak_factory_(this),
       unsafe_unique_page_id_(-1),
+      malware_killswitch_on_(false),
       malware_report_enabled_(false) {
   DCHECK(tab);
   // Note: csd_service_ and sb_service will be NULL here in testing.
@@ -386,15 +391,16 @@
       browse_info_.get() &&
       verdict->ParseFromString(verdict_str) &&
       verdict->IsInitialized()) {
-    if (malware_report_enabled_) {
+    // We do the malware IP matching and request sending if the feature
+    // is enabled.
+    if (malware_report_enabled_ && !MalwareKillSwitchIsOn()) {
       scoped_ptr<ClientMalwareRequest> malware_verdict(
           new ClientMalwareRequest);
       // Start browser-side malware feature extraction.  Once we're done it will
       // send the malware client verdict request.
       malware_verdict->set_url(verdict->url());
       feature_extractor_->ExtractMalwareFeatures(
-          browse_info_.get(),
-          malware_verdict.get());
+          browse_info_.get(), malware_verdict.get());
       MalwareFeatureExtractionDone(malware_verdict.Pass());
     }
 
@@ -512,7 +518,8 @@
   DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED);
   const ResourceRequestDetails* req = content::Details<ResourceRequestDetails>(
       details).ptr();
-  if (req && browse_info_.get()) {
+  if (req && browse_info_.get() && malware_report_enabled_ &&
+      !MalwareKillSwitchIsOn()) {
     UpdateIPHostMap(req->socket_address.host() /* ip */,
                     req->url.host()  /* url host */);
   }
@@ -545,4 +552,14 @@
   database_manager_ = database_manager;
 }
 
+bool ClientSideDetectionHost::MalwareKillSwitchIsOn() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  return malware_killswitch_on_;
+}
+
+void ClientSideDetectionHost::SetMalwareKillSwitch(bool killswitch_on) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  malware_killswitch_on_ = killswitch_on;
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.h b/chrome/browser/safe_browsing/client_side_detection_host.h
index 7329f52..7f3e93e 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.h
+++ b/chrome/browser/safe_browsing/client_side_detection_host.h
@@ -102,6 +102,10 @@
       SafeBrowsingUIManager* ui_manager,
       SafeBrowsingDatabaseManager* database_manager);
 
+  // Get/Set malware_killswitch_on_ value. These methods called on UI thread.
+  bool MalwareKillSwitchIsOn();
+  void SetMalwareKillSwitch(bool killswitch_on);
+
   // This pointer may be NULL if client-side phishing detection is disabled.
   ClientSideDetectionService* csd_service_;
   // These pointers may be NULL if SafeBrowsing is disabled.
@@ -137,8 +141,14 @@
   int unsafe_unique_page_id_;
   scoped_ptr<SafeBrowsingUIManager::UnsafeResource> unsafe_resource_;
 
+  // Whether the malware IP matching feature killswitch is on.
+  // This should be accessed from UI thread.
+  bool malware_killswitch_on_;
+
   // Whether the malware bad ip matching and report feature is enabled.
+  // This should be accessed from UI thread.
   bool malware_report_enabled_;
+
   DISALLOW_COPY_AND_ASSIGN(ClientSideDetectionHost);
 };
 
diff --git a/chrome/browser/safe_browsing/database_manager.cc b/chrome/browser/safe_browsing/database_manager.cc
index 47b238d..db0963a 100644
--- a/chrome/browser/safe_browsing/database_manager.cc
+++ b/chrome/browser/safe_browsing/database_manager.cc
@@ -306,6 +306,14 @@
   return database_->ContainsDownloadWhitelistedString(str);
 }
 
+bool SafeBrowsingDatabaseManager::IsMalwareKillSwitchOn() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (!enabled_ || !MakeDatabaseAvailable()) {
+    return true;
+  }
+  return database_->IsMalwareIPMatchKillSwitchOn();
+}
+
 bool SafeBrowsingDatabaseManager::CheckBrowseUrl(const GURL& url,
                                                  Client* client) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
diff --git a/chrome/browser/safe_browsing/database_manager.h b/chrome/browser/safe_browsing/database_manager.h
index 09f64bd..acc38ef 100644
--- a/chrome/browser/safe_browsing/database_manager.h
+++ b/chrome/browser/safe_browsing/database_manager.h
@@ -172,6 +172,9 @@
   // This method is expected to be called on the IO thread.
   virtual bool MatchDownloadWhitelistString(const std::string& str);
 
+  // Check if the CSD malware IP matching kill switch is turned on.
+  virtual bool IsMalwareKillSwitchOn();
+
   // Called on the IO thread to cancel a pending check if the result is no
   // longer needed.
   void CancelCheck(Client* client);
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index 62c12fa..6756bbf 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -10,6 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -388,6 +389,14 @@
             << item_->GetUrlChain().back() << ": success="
             << source->GetStatus().is_success() << " response_code="
             << source->GetResponseCode();
+    if (source->GetStatus().is_success()) {
+      UMA_HISTOGRAM_SPARSE_SLOWLY(
+          "SBClientDownload.DownloadRequestResponseCode",
+          source->GetResponseCode());
+    }
+    UMA_HISTOGRAM_SPARSE_SLOWLY(
+        "SBClientDownload.DownloadRequestNetError",
+        -source->GetStatus().error());
     DownloadCheckResultReason reason = REASON_SERVER_PING_FAILED;
     DownloadCheckResult result = SAFE;
     if (source->GetStatus().is_success() &&
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index 9f43ecd..b193f50 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -12,6 +12,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/stats_counters.h"
+#include "base/process/process.h"
 #include "base/process/process_metrics.h"
 #include "base/time/time.h"
 #include "chrome/browser/safe_browsing/prefix_set.h"
@@ -70,6 +71,12 @@
 const char kWhitelistKillSwitchUrl[] =
     "sb-ssl.google.com/safebrowsing/csd/killswitch";  // Don't change this!
 
+// If the hash of this exact expression is on a whitelist then the
+// malware IP blacklisting feature will be disabled in csd.
+// Don't change this!
+const char kMalwareIPKillSwitchUrl[] =
+    "sb-ssl.google.com/safebrowsing/csd/killswitch_malware";
+
 // To save space, the incoming |chunk_id| and |list_id| are combined
 // into an |encoded_chunk_id| for storage by shifting the |list_id|
 // into the low-order bits.  These functions decode that information.
@@ -1605,3 +1612,12 @@
     whitelist->first.swap(new_whitelist);
   }
 }
+
+bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() {
+  SBFullHash malware_kill_switch;
+  crypto::SHA256HashString(kMalwareIPKillSwitchUrl, &malware_kill_switch,
+                           sizeof(malware_kill_switch));
+  std::vector<SBFullHash> full_hashes;
+  full_hashes.push_back(malware_kill_switch);
+  return ContainsWhitelistedHashes(csd_whitelist_, full_hashes);
+}
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.h b/chrome/browser/safe_browsing/safe_browsing_database.h
index 219f1ea..6446e35 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.h
+++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -171,6 +171,10 @@
       const std::vector<SBPrefix>& prefixes,
       const std::vector<SBFullHashResult>& full_hits) = 0;
 
+  // Returns true if the malware IP blacklisting killswitch URL is present
+  // in the csd whitelist.
+  virtual bool IsMalwareIPMatchKillSwitchOn() = 0;
+
   // The name of the bloom-filter file for the given database file.
   // NOTE(shess): OBSOLETE.  Present for deleting stale files.
   static base::FilePath BloomFilterForFilename(
@@ -297,6 +301,9 @@
       const std::vector<SBPrefix>& prefixes,
       const std::vector<SBFullHashResult>& full_hits) OVERRIDE;
 
+  // Returns the value of malware_kill_switch_;
+  virtual bool IsMalwareIPMatchKillSwitchOn() OVERRIDE;
+
  private:
   friend class SafeBrowsingDatabaseTest;
   FRIEND_TEST_ALL_PREFIXES(SafeBrowsingDatabaseTest, HashCaching);
@@ -368,8 +375,7 @@
 
   // Lock for protecting access to variables that may be used on the
   // IO thread.  This includes |prefix_set_|, |full_browse_hashes_|,
-  // |pending_browse_hashes_|, |prefix_miss_cache_|, |csd_whitelist_|,
-  // and |csd_whitelist_all_urls_|.
+  // |pending_browse_hashes_|, |prefix_miss_cache_|, |csd_whitelist_|.
   base::Lock lookup_lock_;
 
   // Underlying persistent store for chunk data.
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
index ec50a66..7e934a9 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -1365,6 +1365,19 @@
   EXPECT_FALSE(database_->ContainsDownloadWhitelistedUrl(
       GURL(std::string("http://www.google.com/"))));
 
+  // Test only add the malware IP killswitch
+  csd_chunks.clear();
+  chunk.hosts.clear();
+  InsertAddChunkHostFullHashes(
+      &chunk, 15, "sb-ssl.google.com/",
+      "sb-ssl.google.com/safebrowsing/csd/killswitch_malware");
+  csd_chunks.push_back(chunk);
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  database_->InsertChunks(safe_browsing_util::kCsdWhiteList, csd_chunks);
+  database_->UpdateFinished(true);
+
+  EXPECT_TRUE(database_->IsMalwareIPMatchKillSwitchOn());
+
   // Test that the kill-switch works as intended.
   csd_chunks.clear();
   download_chunks.clear();
@@ -1373,7 +1386,6 @@
   InsertAddChunkHostFullHashes(&chunk, 5, "sb-ssl.google.com/",
                                "sb-ssl.google.com/safebrowsing/csd/killswitch");
   csd_chunks.push_back(chunk);
-
   chunk.hosts.clear();
   InsertAddChunkHostFullHashes(&chunk, 5, "sb-ssl.google.com/",
                                "sb-ssl.google.com/safebrowsing/csd/killswitch");
@@ -1385,6 +1397,7 @@
                           download_chunks);
   database_->UpdateFinished(true);
 
+  EXPECT_TRUE(database_->IsMalwareIPMatchKillSwitchOn());
   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
       GURL(std::string("https://") + kGood1Url2 + "/c.html")));
   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
@@ -1413,6 +1426,12 @@
   csd_chunks.push_back(sub_chunk);
 
   sub_chunk.hosts.clear();
+  InsertSubChunkHostFullHash(
+      &sub_chunk, 10, 15, "sb-ssl.google.com/",
+      "sb-ssl.google.com/safebrowsing/csd/killswitch_malware");
+  csd_chunks.push_back(sub_chunk);
+
+  sub_chunk.hosts.clear();
   InsertSubChunkHostFullHash(&sub_chunk, 1, 5,
                              "sb-ssl.google.com/",
                              "sb-ssl.google.com/safebrowsing/csd/killswitch");
@@ -1424,6 +1443,7 @@
                           download_chunks);
   database_->UpdateFinished(true);
 
+  EXPECT_FALSE(database_->IsMalwareIPMatchKillSwitchOn());
   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
       GURL(std::string("https://") + kGood1Url2 + "/c.html")));
   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 20543d5..c36e23f 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -143,6 +143,9 @@
       const std::vector<SBFullHashResult>& full_hits) OVERRIDE {
     // Do nothing for the cache.
   }
+  virtual bool IsMalwareIPMatchKillSwitchOn() OVERRIDE {
+    return false;
+  }
 
   // Fill up the database with test URL.
   void AddUrl(const GURL& url,
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index 883c43e..291fb08 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -161,6 +161,13 @@
        google_util::StartsWithCommandLineGoogleBaseURL(url));
 }
 
+// Returns true if |url| matches --instant-new-tab-url.
+bool IsCommandLineInstantNTPURL(const GURL& url) {
+  const GURL ntp_url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+      switches::kInstantNewTabURL));
+  return ntp_url.is_valid() && MatchesOriginAndPath(ntp_url, url);
+}
+
 // Returns true if |url| can be used as an Instant URL for |profile|.
 bool IsInstantURL(const GURL& url, Profile* profile) {
   if (!IsInstantExtendedAPIEnabled())
@@ -169,6 +176,9 @@
   if (!url.is_valid())
     return false;
 
+  if (IsCommandLineInstantNTPURL(url))
+    return true;
+
   TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
   if (!template_url)
     return false;
@@ -316,11 +326,16 @@
     return false;
 
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
-  return IsInstantExtendedAPIEnabled() &&
-         IsRenderedInInstantProcess(contents, profile) &&
-         (IsInstantURL(entry->GetVirtualURL(), profile) ||
-          entry->GetVirtualURL() == GetLocalInstantURL(profile)) &&
-         GetSearchTermsImpl(contents, entry).empty();
+  if (!IsInstantExtendedAPIEnabled() ||
+      !IsRenderedInInstantProcess(contents, profile))
+    return false;
+
+  if (IsInstantURL(entry->GetVirtualURL(), profile) ||
+      entry->GetVirtualURL() == GetLocalInstantURL(profile))
+    return GetSearchTermsImpl(contents, entry).empty();
+
+  return entry->GetVirtualURL() == GURL(chrome::kChromeUINewTabURL) &&
+      IsCommandLineInstantNTPURL(entry->GetURL());
 }
 
 bool IsSuggestPrefEnabled(Profile* profile) {
@@ -380,6 +395,12 @@
 }
 
 bool ShouldShowInstantNTP() {
+  // If the instant-new-tab-url flag is set, we'll always just load the NTP
+  // directly instead of preloading contents using InstantNTP.
+  const CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kInstantNewTabURL))
+    return false;
+
   FieldTrialFlags flags;
   if (GetFieldTrialInfo(
           base::FieldTrialList::FindFullName(kInstantExtendedFieldTrialName),
@@ -478,6 +499,39 @@
   return false;
 }
 
+bool HandleNewTabURLRewrite(GURL* url,
+                            content::BrowserContext* browser_context) {
+  if (!IsInstantExtendedAPIEnabled())
+    return false;
+
+  if (!url->SchemeIs(chrome::kChromeUIScheme) ||
+      url->host() != chrome::kChromeUINewTabHost)
+    return false;
+
+  const GURL ntp_url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+      switches::kInstantNewTabURL));
+  if (!ntp_url.is_valid())
+    return false;
+
+  *url = ntp_url;
+  return true;
+}
+
+bool HandleNewTabURLReverseRewrite(GURL* url,
+                                   content::BrowserContext* browser_context) {
+  if (!IsInstantExtendedAPIEnabled())
+    return false;
+
+  const GURL ntp_url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+      switches::kInstantNewTabURL));
+  if (!MatchesOriginAndPath(ntp_url, *url))
+    return false;
+
+  *url = GURL(chrome::kChromeUINewTabURL);
+  return true;
+}
+
+
 void EnableInstantExtendedAPIForTesting() {
   CommandLine* cl = CommandLine::ForCurrentProcess();
   cl->AppendSwitch(switches::kEnableInstantExtendedAPI);
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h
index 7f1bf78..ef59f2d 100644
--- a/chrome/browser/search/search.h
+++ b/chrome/browser/search/search.h
@@ -18,6 +18,7 @@
 class TemplateURLRef;
 
 namespace content {
+class BrowserContext;
 class NavigationEntry;
 class WebContents;
 }
@@ -147,6 +148,17 @@
 // Returns true if |contents| corresponds to a preloaded instant extended NTP.
 bool IsPreloadedInstantExtendedNTP(const content::WebContents* contents);
 
+// Rewrites |url| if
+//   1. |url| is kChromeUINewTabURL,
+//   2. InstantExtended is enabled, and
+//   3. The --instant-new-tab-url switch is set to a valid URL.
+// |url| is rewritten to the value of --instant-new-tab-url.
+bool HandleNewTabURLRewrite(GURL* url,
+                            content::BrowserContext* browser_context);
+// Reverses the operation from HandleNewTabURLRewrite.
+bool HandleNewTabURLReverseRewrite(GURL* url,
+                                   content::BrowserContext* browser_context);
+
 // -----------------------------------------------------
 // The following APIs are exposed for use in tests only.
 // -----------------------------------------------------
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index c986500..925a56d 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -583,4 +583,23 @@
   EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec());
 }
 
+TEST_F(SearchTest, ShouldShowInstantNTP_Default) {
+  EnableInstantExtendedAPIForTesting();
+  EXPECT_TRUE(ShouldShowInstantNTP());
+}
+
+TEST_F(SearchTest, ShouldShowInstantNTP_DisabledViaFinch) {
+  EnableInstantExtendedAPIForTesting();
+  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
+                                                     "Group1 show_ntp:0"));
+  EXPECT_FALSE(ShouldShowInstantNTP());
+}
+
+TEST_F(SearchTest, ShouldShowInstantNTP_DisabledByInstantNewTabURLSwitch) {
+  EnableInstantExtendedAPIForTesting();
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kInstantNewTabURL, "http://example.com/newtab");
+  EXPECT_FALSE(ShouldShowInstantNTP());
+}
+
 }  // namespace chrome
diff --git a/chrome/browser/signin/oauth2_token_service.cc b/chrome/browser/signin/oauth2_token_service.cc
index 1790aea..1cc4e18 100644
--- a/chrome/browser/signin/oauth2_token_service.cc
+++ b/chrome/browser/signin/oauth2_token_service.cc
@@ -309,6 +309,14 @@
 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
     const OAuth2TokenService::ScopeSet& scopes,
     OAuth2TokenService::Consumer* consumer) {
+  return StartRequestWithContext(GetRequestContext(), scopes, consumer);
+}
+
+scoped_ptr<OAuth2TokenService::Request>
+OAuth2TokenService::StartRequestWithContext(
+    net::URLRequestContextGetter* getter,
+    const ScopeSet& scopes,
+    Consumer* consumer) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
   scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
@@ -340,10 +348,7 @@
   }
 
   pending_fetchers_[fetch_parameters] =
-      Fetcher::CreateAndStart(this,
-                              GetRequestContext(),
-                              refresh_token,
-                              scopes,
+      Fetcher::CreateAndStart(this, getter, refresh_token, scopes,
                               request->AsWeakPtr());
   return request.PassAs<Request>();
 }
diff --git a/chrome/browser/signin/oauth2_token_service.h b/chrome/browser/signin/oauth2_token_service.h
index b40066e..d979fcf 100644
--- a/chrome/browser/signin/oauth2_token_service.h
+++ b/chrome/browser/signin/oauth2_token_service.h
@@ -117,6 +117,14 @@
   virtual scoped_ptr<Request> StartRequest(const ScopeSet& scopes,
                                            Consumer* consumer);
 
+  // This method does the same as |StartRequest| except it uses the request
+  // context given by |getter| instead of using the one returned by
+  // |GetRequestContext| implemented by derived classes.
+  virtual scoped_ptr<Request> StartRequestWithContext(
+      net::URLRequestContextGetter* getter,
+      const ScopeSet& scopes,
+      Consumer* consumer);
+
   // Returns true if a refresh token exists. If false, calls to
   // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
   virtual bool RefreshTokenIsAvailable();
diff --git a/chrome/browser/signin/signin_manager.cc b/chrome/browser/signin/signin_manager.cc
index f419d84..09a4862 100644
--- a/chrome/browser/signin/signin_manager.cc
+++ b/chrome/browser/signin/signin_manager.cc
@@ -125,18 +125,6 @@
     token_service->LoadTokensFromDB();
 }
 
-void SigninManager::CleanupNotificationRegistration() {
-  content::Source<TokenService> token_service(
-      TokenServiceFactory::GetForProfile(profile_));
-  if (registrar_.IsRegistered(this,
-                              chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                              token_service)) {
-    registrar_.Remove(this,
-                      chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                      token_service);
-  }
-}
-
 std::string SigninManager::SigninTypeToString(
     SigninManager::SigninType type) {
   switch (type) {
@@ -202,15 +190,6 @@
                                   login_token,
                                   login_captcha,
                                   GaiaAuthFetcher::HostedAccountsNotAllowed);
-
-  // Register for token availability.  The signin manager will pre-login the
-  // user when the GAIA service token is ready for use.
-  if (delegate_->AreSigninCookiesAllowed()) {
-    TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-    registrar_.Add(this,
-                   chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                   content::Source<TokenService>(token_service));
-  }
 }
 
 void SigninManager::ProvideSecondFactorAccessCode(
@@ -312,7 +291,6 @@
 void SigninManager::ClearTransientSigninData() {
   DCHECK(IsInitialized());
 
-  CleanupNotificationRegistration();
   client_login_.reset();
   last_result_ = ClientLoginResult();
   possibly_invalid_username_.clear();
@@ -409,6 +387,11 @@
   }
 }
 
+void SigninManager::Shutdown() {
+  local_state_pref_registrar_.RemoveAll();
+  SigninManagerBase::Shutdown();
+}
+
 void SigninManager::OnGoogleServicesUsernamePatternChanged() {
   if (!GetAuthenticatedUsername().empty() &&
       !IsAllowedUsername(GetAuthenticatedUsername())) {
@@ -651,60 +634,21 @@
   OnClientLoginFailure(error);
 }
 
-void SigninManager::OnUbertokenSuccess(const std::string& token) {
-  ubertoken_fetcher_.reset();
-  if (client_login_.get() == NULL) {
-    client_login_.reset(
-        new GaiaAuthFetcher(this,
-                            GaiaConstants::kChromeSource,
-                            profile_->GetRequestContext()));
-  }
-
-  client_login_->StartMergeSession(token);
-}
-
-void SigninManager::OnUbertokenFailure(const GoogleServiceAuthError& error) {
-  LOG(WARNING) << " Unable to login the user to the web: " << error.ToString();
-  ubertoken_fetcher_.reset();
-}
-
 void SigninManager::Observe(int type,
                             const content::NotificationSource& source,
                             const content::NotificationDetails& details) {
-  switch (type) {
-    case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
-      TokenService::TokenAvailableDetails* tok_details =
-          content::Details<TokenService::TokenAvailableDetails>(
-              details).ptr();
+  DCHECK_EQ(content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, type);
 
-      // If a GAIA service token has become available, use it to pre-login the
-      // user to other services that depend on GAIA credentials.
-      if (tok_details->service() ==
-          GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
-        ubertoken_fetcher_.reset(new UbertokenFetcher(profile_, this));
-        ubertoken_fetcher_->StartFetchingToken();
-
-        // We only want to do this once per sign-in.
-        CleanupNotificationRegistration();
-      }
-      break;
-    }
-    case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
-      // It's possible we're listening to a "stale" renderer because it was
-      // replaced with a new process by process-per-site. In either case,
-      // stop listening to it, but only reset signin_process_id_ tracking
-      // if this was from the current signin process.
-      registrar_.Remove(this,
-                        content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
-                        source);
-      if (signin_process_id_ ==
-          content::Source<content::RenderProcessHost>(source)->GetID()) {
-        signin_process_id_ = kInvalidProcessId;
-      }
-      break;
-    }
-    default:
-      NOTREACHED();
+  // It's possible we're listening to a "stale" renderer because it was
+  // replaced with a new process by process-per-site. In either case,
+  // stop listening to it, but only reset signin_process_id_ tracking
+  // if this was from the current signin process.
+  registrar_.Remove(this,
+                    content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
+                    source);
+  if (signin_process_id_ ==
+      content::Source<content::RenderProcessHost>(source)->GetID()) {
+    signin_process_id_ = kInvalidProcessId;
   }
 }
 
diff --git a/chrome/browser/signin/signin_manager.h b/chrome/browser/signin/signin_manager.h
index 1e84e0a..3c54c94 100644
--- a/chrome/browser/signin/signin_manager.h
+++ b/chrome/browser/signin/signin_manager.h
@@ -33,7 +33,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_internals_util.h"
 #include "chrome/browser/signin/signin_manager_base.h"
-#include "chrome/browser/signin/ubertoken_fetcher.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -50,7 +49,6 @@
 
 class SigninManager : public SigninManagerBase,
                       public GaiaAuthConsumer,
-                      public UbertokenConsumer,
                       public content::NotificationObserver {
  public:
   // The callback invoked once the OAuth token has been fetched during signin,
@@ -120,6 +118,7 @@
   // invalid username policy updates, we need to check this during
   // initialization and sign the user out.
   virtual void Initialize(Profile* profile, PrefService* local_state) OVERRIDE;
+  virtual void Shutdown() OVERRIDE;
 
   // Invoked from an OAuthTokenFetchedCallback to complete user signin.
   virtual void CompletePendingSignin();
@@ -161,10 +160,6 @@
   virtual void OnGetUserInfoFailure(
       const GoogleServiceAuthError& error) OVERRIDE;
 
-  // UbertokenConsumer
-  virtual void OnUbertokenSuccess(const std::string& token) OVERRIDE;
-  virtual void OnUbertokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
-
   // content::NotificationObserver
   virtual void Observe(int type,
                        const content::NotificationSource& source,
@@ -260,8 +255,6 @@
   std::string password_;  // This is kept empty whenever possible.
   bool had_two_factor_error_;
 
-  void CleanupNotificationRegistration();
-
   // Result of the last client login, kept pending the lookup of the
   // canonical email.
   ClientLoginResult last_result_;
@@ -272,9 +265,6 @@
   // Registrar for notifications from the TokenService.
   content::NotificationRegistrar registrar_;
 
-  // UbertokenFetcher to login to user to the web property.
-  scoped_ptr<UbertokenFetcher> ubertoken_fetcher_;
-
   // OAuth revocation fetcher for sign outs.
   scoped_ptr<GaiaAuthFetcher> revoke_token_fetcher_;
 
diff --git a/chrome/browser/signin/ubertoken_fetcher.cc b/chrome/browser/signin/ubertoken_fetcher.cc
index 01d9ad4..b726b70 100644
--- a/chrome/browser/signin/ubertoken_fetcher.cc
+++ b/chrome/browser/signin/ubertoken_fetcher.cc
@@ -7,15 +7,13 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "base/strings/stringprintf.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/token_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "net/base/load_flags.h"
 
 UbertokenFetcher::UbertokenFetcher(Profile* profile,
                                    UbertokenConsumer* consumer)
@@ -28,86 +26,11 @@
 }
 
 void UbertokenFetcher::StartFetchingToken() {
-  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-  if (token_service->HasOAuthLoginToken()) {
-    StartFetchingUbertoken();
-  } else {
-    registrar_.Add(this,
-                   chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                   content::Source<TokenService>(token_service));
-    registrar_.Add(this,
-                   chrome::NOTIFICATION_TOKEN_REQUEST_FAILED,
-                   content::Source<TokenService>(token_service));
-    token_service->StartFetchingTokens();
-  }
-}
-
-void UbertokenFetcher::StartFetchingUbertoken() {
-  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-  DCHECK(token_service->HasOAuthLoginToken());
-  gaia::OAuthClientInfo client_info;
-  GaiaUrls* urls = GaiaUrls::GetInstance();
-  client_info.client_id = urls->oauth2_chrome_client_id();
-  client_info.client_secret = urls->oauth2_chrome_client_secret();
-  gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
-      profile_->GetRequestContext()));
-  std::vector<std::string> empty_scope_list;  // (Use scope from refresh token.)
-  gaia_oauth_client_->RefreshToken(
-      client_info, token_service->GetOAuth2LoginRefreshToken(),
-      empty_scope_list, 1, this);
-}
-
-void UbertokenFetcher::Observe(int type,
-                               const content::NotificationSource& source,
-                               const content::NotificationDetails& details) {
-  DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE ||
-         type == chrome::NOTIFICATION_TOKEN_REQUEST_FAILED);
-
-  if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) {
-    TokenService::TokenAvailableDetails* token_details =
-        content::Details<TokenService::TokenAvailableDetails>(details).ptr();
-    if (token_details->service() !=
-        GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
-      return;
-    }
-    registrar_.RemoveAll();
-    StartFetchingUbertoken();
-  } else {
-    TokenService::TokenRequestFailedDetails* token_details =
-        content::Details<TokenService::TokenRequestFailedDetails>(details).
-            ptr();
-    if (token_details->service() == GaiaConstants::kLSOService ||
-        token_details->service() ==
-            GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
-      consumer_->OnUbertokenFailure(token_details->error());
-    }
-  }
-}
-
-void UbertokenFetcher::OnGetTokensResponse(const std::string& refresh_token,
-                                           const std::string& access_token,
-                                           int expires_in_seconds) {
-  NOTREACHED();
-}
-
-void UbertokenFetcher::OnRefreshTokenResponse(const std::string& access_token,
-                                              int expires_in_seconds) {
-  gaia_auth_fetcher_.reset(new GaiaAuthFetcher(this,
-                                               GaiaConstants::kChromeSource,
-                                               profile_->GetRequestContext()));
-  gaia_auth_fetcher_->StartTokenFetchForUberAuthExchange(access_token);
-}
-
-void UbertokenFetcher::OnOAuthError() {
-  GoogleServiceAuthError error(
-      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-  consumer_->OnUbertokenFailure(error);
-}
-
-void UbertokenFetcher::OnNetworkError(int response_code) {
-  GoogleServiceAuthError error =
-      GoogleServiceAuthError::FromConnectionError(response_code);
-  consumer_->OnUbertokenFailure(error);
+  OAuth2TokenService::ScopeSet scopes;
+  scopes.insert(GaiaUrls::GetInstance()->oauth1_login_scope());
+  access_token_request_ =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
+          StartRequest(scopes, this);
 }
 
 void UbertokenFetcher::OnUberAuthTokenSuccess(const std::string& token) {
@@ -118,3 +41,21 @@
     const GoogleServiceAuthError& error) {
   consumer_->OnUbertokenFailure(error);
 }
+
+void UbertokenFetcher::OnGetTokenSuccess(
+    const OAuth2TokenService::Request* request,
+    const std::string& access_token,
+    const base::Time& expiration_time) {
+  access_token_request_.reset();
+  gaia_auth_fetcher_.reset(new GaiaAuthFetcher(this,
+                                               GaiaConstants::kChromeSource,
+                                               profile_->GetRequestContext()));
+  gaia_auth_fetcher_->StartTokenFetchForUberAuthExchange(access_token);
+}
+
+void UbertokenFetcher::OnGetTokenFailure(
+    const OAuth2TokenService::Request* request,
+    const GoogleServiceAuthError& error) {
+  access_token_request_.reset();
+  consumer_->OnUbertokenFailure(error);
+}
diff --git a/chrome/browser/signin/ubertoken_fetcher.h b/chrome/browser/signin/ubertoken_fetcher.h
index 3c4a516..b7dd6d0 100644
--- a/chrome/browser/signin/ubertoken_fetcher.h
+++ b/chrome/browser/signin/ubertoken_fetcher.h
@@ -6,24 +6,19 @@
 #define CHROME_BROWSER_SIGNIN_UBERTOKEN_FETCHER_H_
 
 #include "base/memory/scoped_ptr.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_source.h"
+#include "chrome/browser/signin/oauth2_token_service.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/gaia_oauth_client.h"
 
 // Allow to retrieves an uber-auth token for the user. This class uses the
-// |TokenService| and considers that the user is already logged in. It will then
-// retrieve the OAuth2 refresh token, use it to generate an OAuth2 access token
-// and finally use this access token to generate the uber-auth token.
+// |OAuth2TokenService| and considers that the user is already logged in. It
+// will use the OAuth2 access token to generate the uber-auth token.
 //
 // This class should be used on a single thread, but it can be whichever thread
 // that you like.
 //
 // This class can handle one request at a time.
 
+class GaiaAuthFetcher;
 class GoogleServiceAuthError;
 class Profile;
 
@@ -37,9 +32,8 @@
 };
 
 // Allows to retrieve an uber-auth token.
-class UbertokenFetcher : public content::NotificationObserver,
-                         public gaia::GaiaOAuthClient::Delegate,
-                         public GaiaAuthConsumer {
+class UbertokenFetcher : public GaiaAuthConsumer,
+                         public OAuth2TokenService::Consumer {
  public:
   UbertokenFetcher(Profile* profile, UbertokenConsumer* consumer);
   virtual ~UbertokenFetcher();
@@ -47,33 +41,23 @@
   // Start fetching the token.
   void StartFetchingToken();
 
-  // Overriden from gaia::GaiaOAuthClient::Delegate:
-  virtual void OnGetTokensResponse(const std::string& refresh_token,
-                                   const std::string& access_token,
-                                   int expires_in_seconds) OVERRIDE;
-  virtual void OnRefreshTokenResponse(const std::string& access_token,
-                                      int expires_in_seconds) OVERRIDE;
-  virtual void OnOAuthError() OVERRIDE;
-  virtual void OnNetworkError(int response_code) OVERRIDE;
-
   // Overriden from GaiaAuthConsumer
   virtual void OnUberAuthTokenSuccess(const std::string& token) OVERRIDE;
   virtual void OnUberAuthTokenFailure(
       const GoogleServiceAuthError& error) OVERRIDE;
 
-  // Overriden from content::NotificationObserver:
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
+  // Overriden from OAuth2TokenService::Consumer:
+  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
+                                 const std::string& access_token,
+                                 const base::Time& expiration_time) OVERRIDE;
+  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
+                                 const GoogleServiceAuthError& error) OVERRIDE;
 
  private:
-  void StartFetchingUbertoken();
-
   Profile* profile_;
   UbertokenConsumer* consumer_;
-  content::NotificationRegistrar registrar_;
-  scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
   scoped_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
+  scoped_ptr<OAuth2TokenService::Request> access_token_request_;
 
   DISALLOW_COPY_AND_ASSIGN(UbertokenFetcher);
 };
diff --git a/chrome/browser/signin/ubertoken_fetcher_unittest.cc b/chrome/browser/signin/ubertoken_fetcher_unittest.cc
index ec752c7..90b1d78 100644
--- a/chrome/browser/signin/ubertoken_fetcher_unittest.cc
+++ b/chrome/browser/signin/ubertoken_fetcher_unittest.cc
@@ -4,13 +4,16 @@
 
 #include "chrome/browser/signin/ubertoken_fetcher.h"
 
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/signin/token_service.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/token_service_unittest.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+
 class MockUbertokenConsumer : public UbertokenConsumer {
  public:
   MockUbertokenConsumer()
@@ -37,15 +40,40 @@
   int nb_error_;
 };
 
+class MockOAuth2TokenService : public ProfileOAuth2TokenService {
+  // OAuth2TokenService overrides:
+  virtual scoped_ptr<OAuth2TokenService::Request>
+      StartRequest(const OAuth2TokenService::ScopeSet& scopes,
+                   OAuth2TokenService::Consumer* consumer) OVERRIDE {
+    // Don't actually make a request.
+    scoped_ptr<OAuth2TokenService::Request> request;
+    return request.Pass();
+  }
+};
+
+
+BrowserContextKeyedService* Build(content::BrowserContext* profile) {
+  MockOAuth2TokenService* token_service = new MockOAuth2TokenService();
+  token_service->Initialize(static_cast<Profile*>(profile));
+  return token_service;
+}
+
+}  // namespace
+
 class UbertokenFetcherTest : public TokenServiceTestHarness {
  public:
   virtual void SetUp() OVERRIDE {
     TokenServiceTestHarness::SetUp();
+    profile()->CreateRequestContext(NULL);
+
+    ProfileOAuth2TokenServiceFactory::GetInstance()->
+        SetTestingFactoryAndUse(profile(), Build);
     UpdateCredentialsOnService();
     fetcher_.reset(new UbertokenFetcher(profile(), &consumer_));
   }
 
   virtual void TearDown() OVERRIDE {
+    fetcher_.reset();
     TokenServiceTestHarness::TearDown();
   }
 
@@ -55,50 +83,51 @@
   scoped_ptr<UbertokenFetcher> fetcher_;
 };
 
-TEST_F(UbertokenFetcherTest, TestSuccessWithoutRefreshToken) {
-  fetcher_->StartFetchingToken();
-  TokenService::TokenAvailableDetails
-      details(GaiaConstants::kGaiaOAuth2LoginRefreshToken, "refreshToken");
+TEST_F(UbertokenFetcherTest, Basic) {
+}
+
+TEST_F(UbertokenFetcherTest, Success) {
   service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
                                    "refreshToken");
-  fetcher_->Observe(chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                    content::Source<TokenService>(service()),
-                    content::Details<const TokenService::TokenAvailableDetails>(
-                        &details));
-  fetcher_->OnRefreshTokenResponse("accessToken", 3600);
+  fetcher_->StartFetchingToken();
+  fetcher_->OnGetTokenSuccess(NULL, "accessToken", base::Time());
   fetcher_->OnUberAuthTokenSuccess("uberToken");
   EXPECT_EQ(0, consumer_.nb_error_);
   EXPECT_EQ(1, consumer_.nb_correct_token_);
   EXPECT_EQ("uberToken", consumer_.last_token_);
 }
 
-TEST_F(UbertokenFetcherTest, TestSuccessWithRefreshToken) {
-  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                   "refreshToken");
+TEST_F(UbertokenFetcherTest, NoRefreshToken) {
   fetcher_->StartFetchingToken();
-  fetcher_->OnRefreshTokenResponse("accessToken", 3600);
-  fetcher_->OnUberAuthTokenSuccess("uberToken");
-  EXPECT_EQ(0, consumer_.nb_error_);
-  EXPECT_EQ(1, consumer_.nb_correct_token_);
-  EXPECT_EQ("uberToken", consumer_.last_token_);
-}
-
-
-TEST_F(UbertokenFetcherTest, TestFailures) {
   GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
-  EXPECT_EQ(0, consumer_.nb_error_);
-  TokenService::TokenRequestFailedDetails
-      details(GaiaConstants::kGaiaOAuth2LoginRefreshToken, error);
-  fetcher_->Observe(
-      chrome::NOTIFICATION_TOKEN_REQUEST_FAILED,
-      content::Source<TokenService>(service()),
-      content::Details<const TokenService::TokenRequestFailedDetails>(
-          &details));
+  fetcher_->OnGetTokenFailure(NULL, error);
   EXPECT_EQ(1, consumer_.nb_error_);
-  fetcher_->OnOAuthError();
-  EXPECT_EQ(2, consumer_.nb_error_);
-  fetcher_->OnNetworkError(401);
-  EXPECT_EQ(3, consumer_.nb_error_);
+  EXPECT_EQ(0, consumer_.nb_correct_token_);
+}
+
+TEST_F(UbertokenFetcherTest, FailureToGetAccessToken) {
+  GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
+
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
+  fetcher_->StartFetchingToken();
+  fetcher_->OnGetTokenFailure(NULL, error);
+
+  EXPECT_EQ(1, consumer_.nb_error_);
+  EXPECT_EQ(0, consumer_.nb_correct_token_);
+  EXPECT_EQ("", consumer_.last_token_);
+}
+
+TEST_F(UbertokenFetcherTest, FailureToGetUberToken) {
+  GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
+
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
+  fetcher_->StartFetchingToken();
+  fetcher_->OnGetTokenSuccess(NULL, "accessToken", base::Time());
   fetcher_->OnUberAuthTokenFailure(error);
-  EXPECT_EQ(4, consumer_.nb_error_);
+
+  EXPECT_EQ(1, consumer_.nb_error_);
+  EXPECT_EQ(0, consumer_.nb_correct_token_);
+  EXPECT_EQ("", consumer_.last_token_);
 }
diff --git a/chrome/browser/ui/app_list/search/webstore_provider.cc b/chrome/browser/ui/app_list/search/webstore_provider.cc
index 479ded0..761cee0 100644
--- a/chrome/browser/ui/app_list/search/webstore_provider.cc
+++ b/chrome/browser/ui/app_list/search/webstore_provider.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/metrics/field_trial.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -16,6 +17,7 @@
 #include "chrome/browser/ui/app_list/search/webstore_result.h"
 #include "chrome/browser/ui/app_list/search/webstore_search_fetcher.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/url_constants.h"
 #include "url/gurl.h"
 
 namespace app_list {
@@ -34,6 +36,49 @@
   return base::FieldTrialList::FindFullName(kFieldTrialName) == kEnable;
 }
 
+// Returns whether or not the user's input string, |query|, might contain any
+// sensitive information, based purely on its value and not where it came from.
+bool IsSensitiveInput(const string16& query) {
+  const GURL query_as_url(query);
+  if (!query_as_url.is_valid())
+    return false;
+
+  // The input can be interpreted as a URL. Check to see if it is potentially
+  // sensitive. (Code shamelessly copied from search_provider.cc's
+  // IsQuerySuitableForSuggest function.)
+
+  // First we check the scheme: if this looks like a URL with a scheme that is
+  // file, we shouldn't send it. Sending such things is a waste of time and a
+  // disclosure of potentially private, local data. If the scheme is OK, we
+  // still need to check other cases below.
+  if (LowerCaseEqualsASCII(query_as_url.scheme(), chrome::kFileScheme))
+    return true;
+
+  // Don't send URLs with usernames, queries or refs. Some of these are
+  // private, and the Suggest server is unlikely to have any useful results
+  // for any of them. Also don't send URLs with ports, as we may initially
+  // think that a username + password is a host + port (and we don't want to
+  // send usernames/passwords), and even if the port really is a port, the
+  // server is once again unlikely to have and useful results.
+  if (!query_as_url.username().empty() ||
+      !query_as_url.port().empty() ||
+      !query_as_url.query().empty() ||
+      !query_as_url.ref().empty()) {
+    return true;
+  }
+
+  // Don't send anything for https except the hostname. Hostnames are OK
+  // because they are visible when the TCP connection is established, but the
+  // specific path may reveal private information.
+  if (LowerCaseEqualsASCII(query_as_url.scheme(), chrome::kHttpsScheme) &&
+      !query_as_url.path().empty() &&
+      query_as_url.path() != "/") {
+    return true;
+  }
+
+  return false;
+}
+
 }  // namespace
 
 WebstoreProvider::WebstoreProvider(Profile* profile,
@@ -44,6 +89,13 @@
 WebstoreProvider::~WebstoreProvider() {}
 
 void WebstoreProvider::Start(const base::string16& query) {
+  ClearResults();
+
+  // If |query| contains sensitive data, bail out and do not create the place
+  // holder "search-web-store" result.
+  if (IsSensitiveInput(query))
+    return;
+
   const std::string query_utf8 = UTF16ToUTF8(query);
 
   if (UseWebstoreSearch()) {
@@ -59,7 +111,6 @@
 
   // Add a placeholder result which when clicked will run the user's query in a
   // browser. This placeholder is removed when the search results arrive.
-  ClearResults();
   Add(scoped_ptr<ChromeSearchResult>(
       new SearchWebstoreResult(profile_, query_utf8)).Pass());
 }
diff --git a/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc b/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
index b60133a..ced21f4 100644
--- a/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
+++ b/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
@@ -189,5 +189,26 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_F(WebstoreProviderTest, NoSearchForSensitiveData) {
+  // None of the following input strings should be accepted because they may
+  // contain private data.
+  const char* inputs[] = {
+    // file: scheme is bad.
+    "file://filename",
+    "FILE://filename",
+    // URLs with usernames, ports, queries or refs are bad.
+    "http://username:password@hostname/",
+    "http://www.example.com:1000",
+    "http://foo:1000",
+    "http://hostname/?query=q",
+    "http://hostname/path#ref",
+    // A https URL with path is bad.
+    "https://hostname/path",
+  };
+
+  for (size_t i = 0; i < arraysize(inputs); ++i)
+    EXPECT_EQ("", RunQuery(inputs[i], ""));
+}
+
 }  // namespace test
 }  // namespace app_list
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 2fe7f2f..38c6905 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -101,6 +101,9 @@
 // HSL shift to gray out an image.
 const color_utils::HSL kGrayImageShift = {-1, 0, 0.8};
 
+// Limit Wallet items refresh rate to at most once per minute.
+const int kWalletItemsRefreshRateSeconds = 60;
+
 // Returns true if |card_type| is supported by Wallet.
 bool IsWalletSupportedCard(const std::string& card_type) {
   return card_type == autofill::kVisaCard ||
@@ -643,6 +646,17 @@
     view_->Hide();
 }
 
+void AutofillDialogControllerImpl::TabActivated() {
+  // If the user switched away from this tab and then switched back, reload the
+  // Wallet items, in case they've changed.
+  int seconds_elapsed_since_last_refresh =
+      (base::TimeTicks::Now() - last_wallet_items_fetch_timestamp_).InSeconds();
+  if (IsPayingWithWallet() && wallet_items_ &&
+      seconds_elapsed_since_last_refresh >= kWalletItemsRefreshRateSeconds) {
+    GetWalletItems();
+  }
+}
+
 void AutofillDialogControllerImpl::OnAutocheckoutError() {
   DCHECK_EQ(AUTOCHECKOUT_IN_PROGRESS, autocheckout_state_);
   GetMetricLogger().LogAutocheckoutDuration(
@@ -901,7 +915,15 @@
 }
 
 void AutofillDialogControllerImpl::GetWalletItems() {
+  if (wallet_items_) {
+    previously_selected_instrument_id_ = ActiveInstrument()->object_id();
+    previously_selected_shipping_address_id_ =
+        ActiveShippingAddress()->object_id();
+  }
+
+  last_wallet_items_fetch_timestamp_ = base::TimeTicks::Now();
   wallet_items_.reset();
+
   // The "Loading..." page should be showing now, which should cause the
   // account chooser to hide.
   view_->UpdateAccountChooser();
@@ -2092,6 +2114,10 @@
       GURL settings_url(chrome::kChromeUISettingsURL);
       url = settings_url.Resolve(chrome::kAutofillSubPage);
     } else {
+      // Reset |last_wallet_items_fetch_timestamp_| to ensure that the Wallet
+      // data is refreshed as soon as the user switches back to this tab after
+      // potentially editing his data.
+      last_wallet_items_fetch_timestamp_ = base::TimeTicks();
       url = SectionForSuggestionsMenuModel(*model) == SECTION_SHIPPING ?
           wallet::GetManageAddressesUrl() : wallet::GetManageInstrumentsUrl();
     }
@@ -2489,9 +2515,14 @@
           addresses[i]->DisplayName(),
           addresses[i]->DisplayNameDetail());
 
-      if (addresses[i]->object_id() == wallet_items_->default_address_id())
+      const std::string default_shipping_address_id =
+          !previously_selected_shipping_address_id_.empty() ?
+              previously_selected_shipping_address_id_ :
+              wallet_items_->default_address_id();
+      if (addresses[i]->object_id() == default_shipping_address_id)
         suggested_shipping_.SetCheckedItem(key);
     }
+    previously_selected_shipping_address_id_.clear();
 
     if (!IsSubmitPausedOn(wallet::VERIFY_CVV)) {
       const std::vector<wallet::WalletItems::MaskedInstrument*>& instruments =
@@ -2519,12 +2550,16 @@
         if (allowed) {
           if (first_active_instrument_key.empty())
             first_active_instrument_key = key;
-          if (instruments[i]->object_id() ==
-              wallet_items_->default_instrument_id()) {
+
+          const std::string default_instrument_id =
+              !previously_selected_instrument_id_.empty() ?
+                  previously_selected_instrument_id_ :
+                  wallet_items_->default_instrument_id();
+          if (instruments[i]->object_id() == default_instrument_id)
             default_instrument_key = key;
-          }
         }
       }
+      previously_selected_instrument_id_.clear();
 
       // TODO(estade): this should have a URL sublabel.
       suggested_cc_billing_.AddKeyedItem(
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
index 88e7429..7769189 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
@@ -92,6 +92,10 @@
   void Show();
   void Hide();
 
+  // Called when the tab hosting this dialog is activated by a user gesture.
+  // Used to trigger a refresh of the user's Wallet data.
+  void TabActivated();
+
   // Adds a step in the flow to the Autocheckout UI.
   void AddAutocheckoutStep(AutocheckoutStepType step_type);
 
@@ -597,6 +601,15 @@
   scoped_ptr<wallet::WalletItems> wallet_items_;
   scoped_ptr<wallet::FullWallet> full_wallet_;
 
+  // The last active instrument and shipping address object ids. These
+  // variables are only set (i.e. non-empty) when the Wallet items are being
+  // re-fetched.
+  std::string previously_selected_instrument_id_;
+  std::string previously_selected_shipping_address_id_;
+
+  // When the Wallet items were last fetched.
+  base::TimeTicks last_wallet_items_fetch_timestamp_;
+
   // Local machine signals to pass along on each request to trigger (or
   // discourage) risk challenges; sent if the user is up to date on legal docs.
   std::string risk_data_;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index a647868..51f2d16 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -2284,4 +2284,59 @@
   controller()->ViewClosed();
 }
 
+TEST_F(AutofillDialogControllerTest, ReloadWalletItemsOnActivation) {
+  // Switch into Wallet mode and initialize some Wallet data.
+  SwitchToWallet();
+
+  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
+  wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
+  wallet_items->AddAddress(wallet::GetTestNonDefaultShippingAddress());
+  wallet_items->AddAddress(wallet::GetTestShippingAddress());
+  controller()->OnDidGetWalletItems(wallet_items.Pass());
+
+  // Initially, the default entries should be selected.
+  ui::MenuModel* cc_billing_model =
+      controller()->MenuModelForSection(SECTION_CC_BILLING);
+  ui::MenuModel* shipping_model =
+      controller()->MenuModelForSection(SECTION_SHIPPING);
+  // "add", "manage", and 2 suggestions.
+  ASSERT_EQ(4, cc_billing_model->GetItemCount());
+  EXPECT_TRUE(cc_billing_model->IsItemCheckedAt(0));
+  // "use billing", "add", "manage", and 2 suggestions.
+  ASSERT_EQ(5, shipping_model->GetItemCount());
+  EXPECT_TRUE(shipping_model->IsItemCheckedAt(2));
+
+  // Select entries other than the defaults.
+  cc_billing_model->ActivatedAt(1);
+  shipping_model->ActivatedAt(1);
+  // "add", "manage", and 2 suggestions.
+  ASSERT_EQ(4, cc_billing_model->GetItemCount());
+  EXPECT_TRUE(cc_billing_model->IsItemCheckedAt(1));
+  // "use billing", "add", "manage", and 2 suggestions.
+  ASSERT_EQ(5, shipping_model->GetItemCount());
+  EXPECT_TRUE(shipping_model-> IsItemCheckedAt(1));
+
+  // Simulate switching away from the tab and back.  This should issue a request
+  // for wallet items.
+  EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_));
+  controller()->TabActivated();
+
+  // Simulate a response that includes different items.
+  wallet_items = wallet::GetTestWalletItems();
+  wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentExpired());
+  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
+  wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
+  wallet_items->AddAddress(wallet::GetTestNonDefaultShippingAddress());
+  controller()->OnDidGetWalletItems(wallet_items.Pass());
+
+  // The previously selected entries should still be selected.
+  // "add", "manage", and 3 suggestions.
+  ASSERT_EQ(5, cc_billing_model->GetItemCount());
+  EXPECT_TRUE(cc_billing_model->IsItemCheckedAt(2));
+  // "use billing", "add", "manage", and 1 suggestion.
+  ASSERT_EQ(4, shipping_model->GetItemCount());
+  EXPECT_TRUE(shipping_model->IsItemCheckedAt(1));
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
index 44603d9..00007ba 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/common/url_constants.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
@@ -46,6 +47,14 @@
   DCHECK(!popup_controller_);
 }
 
+void TabAutofillManagerDelegate::TabActivated(int reason) {
+  if (reason != TabStripModelObserver::CHANGE_REASON_USER_GESTURE)
+    return;
+
+  if (dialog_controller_.get())
+    dialog_controller_->TabActivated();
+}
+
 PersonalDataManager* TabAutofillManagerDelegate::GetPersonalDataManager() {
   Profile* profile =
       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
index 75879bd..004a0bb 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
@@ -37,6 +37,9 @@
  public:
   virtual ~TabAutofillManagerDelegate();
 
+  // Called when the tab corresponding to |this| instance is activated.
+  void TabActivated(int reason);
+
   // AutofillManagerDelegate implementation.
   virtual PersonalDataManager* GetPersonalDataManager() OVERRIDE;
   virtual PrefService* GetPrefs() OVERRIDE;
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
index c248a37..2c12189 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -262,10 +262,10 @@
 
   // Launch the blocked popup.
   EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
-  IDMap<chrome::NavigateParams, IDMapOwnPointer>::const_iterator iter(
-      &popup_blocker_helper->GetBlockedPopupRequests());
-  ASSERT_FALSE(iter.IsAtEnd());
-  popup_blocker_helper->ShowBlockedPopup(iter.GetCurrentKey());
+  std::map<int32, GURL> blocked_requests =
+      popup_blocker_helper->GetBlockedPopupRequests();
+  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
+  popup_blocker_helper->ShowBlockedPopup(iter->first);
 
   observer.Wait();
 }
@@ -299,10 +299,10 @@
   PopupBlockerTabHelper* popup_blocker_helper =
       PopupBlockerTabHelper::FromWebContents(web_contents);
   EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
-  IDMap<chrome::NavigateParams, IDMapOwnPointer>::const_iterator iter(
-      &popup_blocker_helper->GetBlockedPopupRequests());
-  ASSERT_FALSE(iter.IsAtEnd());
-  popup_blocker_helper->ShowBlockedPopup(iter.GetCurrentKey());
+  std::map<int32, GURL> blocked_requests =
+      popup_blocker_helper->GetBlockedPopupRequests();
+  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
+  popup_blocker_helper->ShowBlockedPopup(iter->first);
 
   observer.Wait();
 }
@@ -336,10 +336,10 @@
   PopupBlockerTabHelper* popup_blocker_helper =
       PopupBlockerTabHelper::FromWebContents(web_contents);
   EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
-  IDMap<chrome::NavigateParams, IDMapOwnPointer>::const_iterator iter(
-      &popup_blocker_helper->GetBlockedPopupRequests());
-  ASSERT_FALSE(iter.IsAtEnd());
-  popup_blocker_helper->ShowBlockedPopup(iter.GetCurrentKey());
+  std::map<int32, GURL> blocked_requests =
+      popup_blocker_helper->GetBlockedPopupRequests();
+  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
+  popup_blocker_helper->ShowBlockedPopup(iter->first);
 
   observer.Wait();
   Browser* new_browser = browser_observer.WaitForSingleNewBrowser();
@@ -380,10 +380,54 @@
   PopupBlockerTabHelper* popup_blocker_helper =
       PopupBlockerTabHelper::FromWebContents(web_contents);
   EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
-  IDMap<chrome::NavigateParams, IDMapOwnPointer>::const_iterator iter(
-      &popup_blocker_helper->GetBlockedPopupRequests());
-  ASSERT_FALSE(iter.IsAtEnd());
-  popup_blocker_helper->ShowBlockedPopup(iter.GetCurrentKey());
+  std::map<int32, GURL> blocked_requests =
+      popup_blocker_helper->GetBlockedPopupRequests();
+  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
+  popup_blocker_helper->ShowBlockedPopup(iter->first);
+
+  observer.Wait();
+  Browser* new_browser = browser_observer.WaitForSingleNewBrowser();
+
+  // Check that the referrer was correctly set.
+  web_contents = new_browser->tab_strip_model()->GetActiveWebContents();
+  base::string16 expected_title(base::ASCIIToUTF16("PASS"));
+  content::TitleWatcher title_watcher(web_contents, expected_title);
+  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest, WindowFeaturesBarProps) {
+  GURL url(ui_test_utils::GetTestUrl(
+      base::FilePath(kTestDir),
+      base::FilePath(FILE_PATH_LITERAL("popup-windowfeatures.html"))));
+
+  CountRenderViewHosts counter;
+
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // If the popup blocker blocked the blank post, there should be only one tab.
+  EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
+                                        browser()->host_desktop_type()));
+  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+  WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_EQ(url, web_contents->GetURL());
+
+  // And no new RVH created.
+  EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
+
+  content::WindowedNotificationObserver observer(
+      chrome::NOTIFICATION_TAB_ADDED,
+      content::NotificationService::AllSources());
+  ui_test_utils::BrowserAddedObserver browser_observer;
+
+  // Launch the blocked popup.
+  PopupBlockerTabHelper* popup_blocker_helper =
+      PopupBlockerTabHelper::FromWebContents(web_contents);
+  EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
+  std::map<int32, GURL> blocked_requests =
+      popup_blocker_helper->GetBlockedPopupRequests();
+  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
+  popup_blocker_helper->ShowBlockedPopup(iter->first);
 
   observer.Wait();
   Browser* new_browser = browser_observer.WaitForSingleNewBrowser();
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc
index 41b36ff..cc8077c 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc
@@ -9,14 +9,27 @@
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/common/render_messages.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
+#include "third_party/WebKit/public/web/WebWindowFeatures.h"
+
+using WebKit::WebWindowFeatures;
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PopupBlockerTabHelper);
 
+struct PopupBlockerTabHelper::BlockedRequest {
+  BlockedRequest(const chrome::NavigateParams& params,
+                 const WebWindowFeatures& window_features)
+      : params(params), window_features(window_features) {}
+
+  chrome::NavigateParams params;
+  WebWindowFeatures window_features;
+};
+
 PopupBlockerTabHelper::PopupBlockerTabHelper(
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents) {
@@ -49,7 +62,8 @@
 }
 
 bool PopupBlockerTabHelper::MaybeBlockPopup(
-    const chrome::NavigateParams& params) {
+    const chrome::NavigateParams& params,
+    const WebWindowFeatures& window_features) {
   // A page can't spawn popups (or do anything else, either) until its load
   // commits, so when we reach here, the popup was spawned by the
   // NavigationController's last committed entry, not the active entry.  For
@@ -69,7 +83,7 @@
           CONTENT_SETTING_ALLOW) {
     return false;
   } else {
-    blocked_popups_.Add(new chrome::NavigateParams(params));
+    blocked_popups_.Add(new BlockedRequest(params, window_features));
     TabSpecificContentSettings::FromWebContents(web_contents())->
         OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS, std::string());
     return true;
@@ -77,10 +91,14 @@
 }
 
 void PopupBlockerTabHelper::ShowBlockedPopup(int32 id) {
-  chrome::NavigateParams* params = blocked_popups_.Lookup(id);
-  if (!params)
+  BlockedRequest* popup = blocked_popups_.Lookup(id);
+  if (!popup)
     return;
-  chrome::Navigate(params);
+  chrome::Navigate(&popup->params);
+  if (popup->params.target_contents) {
+    popup->params.target_contents->Send(new ChromeViewMsg_SetWindowFeatures(
+        popup->params.target_contents->GetRoutingID(), popup->window_features));
+  }
   blocked_popups_.Remove(id);
   if (blocked_popups_.IsEmpty())
     PopupNotificationVisibilityChanged(false);
@@ -90,7 +108,13 @@
   return blocked_popups_.size();
 }
 
-IDMap<chrome::NavigateParams, IDMapOwnPointer>&
-PopupBlockerTabHelper::GetBlockedPopupRequests() {
-  return blocked_popups_;
+std::map<int32, GURL> PopupBlockerTabHelper::GetBlockedPopupRequests() {
+  std::map<int32, GURL> result;
+  for (IDMap<BlockedRequest, IDMapOwnPointer>::const_iterator iter(
+           &blocked_popups_);
+       !iter.IsAtEnd();
+       iter.Advance()) {
+    result[iter.GetCurrentKey()] = iter.GetCurrentValue()->params.url;
+  }
+  return result;
 }
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h
index 1526054..9631742 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h
+++ b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h
@@ -5,13 +5,21 @@
 #ifndef CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_BLOCKER_TAB_HELPER_H_
 #define CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_BLOCKER_TAB_HELPER_H_
 
+#include <map>
+
 #include "base/id_map.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
 namespace chrome {
 struct NavigateParams;
-};
+}
+
+namespace WebKit {
+struct WebWindowFeatures;
+}
+
+class GURL;
 
 // Per-tab class to manage blocked popups.
 class PopupBlockerTabHelper
@@ -22,7 +30,8 @@
 
   // Returns true if the popup request defined by |params| should be blocked.
   // In that case, it is also added to the |blocked_contents_| container.
-  bool MaybeBlockPopup(const chrome::NavigateParams& params);
+  bool MaybeBlockPopup(const chrome::NavigateParams& params,
+                       const WebKit::WebWindowFeatures& window_features);
 
   // Creates the blocked popup with |popup_id|.
   void ShowBlockedPopup(int32 popup_id);
@@ -31,8 +40,7 @@
   size_t GetBlockedPopupsCount() const;
 
   // Returns the mapping from popup IDs to blocked popup requests.
-  IDMap<chrome::NavigateParams, IDMapOwnPointer>&
-  GetBlockedPopupRequests();
+  std::map<int32, GURL> GetBlockedPopupRequests();
 
   // content::WebContentsObserver overrides:
   virtual void DidNavigateMainFrame(
@@ -40,13 +48,15 @@
       const content::FrameNavigateParams& params) OVERRIDE;
 
  private:
-  explicit PopupBlockerTabHelper(content::WebContents* web_contents);
+  struct BlockedRequest;
   friend class content::WebContentsUserData<PopupBlockerTabHelper>;
 
+  explicit PopupBlockerTabHelper(content::WebContents* web_contents);
+
   // Called when the blocked popup notification is shown or hidden.
   void PopupNotificationVisibilityChanged(bool visible);
 
-  IDMap<chrome::NavigateParams, IDMapOwnPointer> blocked_popups_;
+  IDMap<BlockedRequest, IDMapOwnPointer> blocked_popups_;
 
   DISALLOW_COPY_AND_ASSIGN(PopupBlockerTabHelper);
 };
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 3020251..8fb374d 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -88,6 +88,7 @@
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h"
+#include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.h"
 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
@@ -1083,6 +1084,9 @@
   // This needs to be called after UpdateSearchState().
   if (instant_controller_)
     instant_controller_->ActiveTabChanged();
+
+  autofill::TabAutofillManagerDelegate::FromWebContents(new_contents)->
+      TabActivated(reason);
 }
 
 void Browser::TabMoved(WebContents* contents,
@@ -1289,8 +1293,10 @@
          params.disposition == NEW_BACKGROUND_TAB) &&
         !params.user_gesture && !CommandLine::ForCurrentProcess()->HasSwitch(
                                     switches::kDisablePopupBlocking)) {
-      if (popup_blocker_helper->MaybeBlockPopup(nav_params))
+      if (popup_blocker_helper->MaybeBlockPopup(nav_params,
+                                                WebWindowFeatures())) {
         return NULL;
+      }
     }
   }
 
@@ -1538,7 +1544,7 @@
     else
       nav_params.disposition = disposition;
 
-    return !popup_blocker_helper->MaybeBlockPopup(nav_params);
+    return !popup_blocker_helper->MaybeBlockPopup(nav_params, features);
   }
 
   return true;
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
index b2bd578..c50ca8b 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -547,15 +547,13 @@
 void ContentSettingPopupBubbleModel::SetPopups() {
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableBetterPopupBlocking)) {
-    IDMap<chrome::NavigateParams, IDMapOwnPointer>& blocked_popups =
+    std::map<int32, GURL> blocked_popups =
         PopupBlockerTabHelper::FromWebContents(web_contents())
             ->GetBlockedPopupRequests();
-    for (IDMap<chrome::NavigateParams, IDMapOwnPointer>::const_iterator
-             iter(&blocked_popups);
-         !iter.IsAtEnd();
-         iter.Advance()) {
-
-      std::string title(iter.GetCurrentValue()->url.spec());
+    for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
+         iter != blocked_popups.end();
+         ++iter) {
+      std::string title(iter->second.spec());
       // The popup may not have a valid URL.
       if (title.empty())
         title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
@@ -563,7 +561,7 @@
           ui::ResourceBundle::GetSharedInstance().GetImageNamed(
               IDR_DEFAULT_FAVICON),
           title,
-          iter.GetCurrentKey());
+          iter->first);
       add_popup(popup_item);
     }
     return;
diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
index 7c593fa..73c59c8 100644
--- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
+++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
@@ -55,7 +55,9 @@
       { prefs::kOverscrollVerticalThresholdComplete,
         OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE },
       { prefs::kOverscrollMinimumThresholdStart,
-        OVERSCROLL_CONFIG_MIN_THRESHOLD_START },
+        OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START },
+      { prefs::kOverscrollVerticalThresholdStart,
+        OVERSCROLL_CONFIG_VERT_THRESHOLD_START },
       { prefs::kOverscrollHorizontalResistThreshold,
         OVERSCROLL_CONFIG_HORIZ_RESIST_AFTER },
       { prefs::kOverscrollVerticalResistThreshold,
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 1a226db..33e119b 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -195,8 +195,16 @@
 void SearchTabHelper::DetermineIfPageSupportsInstant() {
   Profile* profile =
       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
-  if (!chrome::ShouldAssignURLToInstantRenderer(web_contents_->GetURL(),
-                                                profile)) {
+  // Use the underlying URL rather than the virtual URL when checking whether
+  // this navigation can land in the Instant process. Otherwise this check
+  // would fail if a URL like chrome://newtab is being rewritten to an Instant
+  // URL.
+  // TODO(samarth): actually check whether this WebContents is rendered in an
+  // Instant process rather than checking the URL.
+  const content::NavigationEntry* entry =
+      web_contents_->GetController().GetActiveEntry();
+  const GURL& current_url = entry ? entry->GetURL() : web_contents_->GetURL();
+  if (!chrome::ShouldAssignURLToInstantRenderer(current_url, profile)) {
     // The page is not in the Instant process. This page does not support
     // instant. If we send an IPC message to a page that is not in the Instant
     // process, it will never receive it and will never respond. Therefore,
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc
index 918ae0f..072885c 100644
--- a/chrome/browser/ui/search_engines/template_url_table_model.cc
+++ b/chrome/browser/ui/search_engines/template_url_table_model.cc
@@ -252,14 +252,7 @@
   template_url_service_->RemoveObserver(this);
   TemplateURL* template_url = GetTemplateURL(index);
 
-  scoped_ptr<ModelEntry> entry(entries_[index]);
-  entries_.erase(entries_.begin() + index);
-  if (index < last_search_engine_index_)
-    --last_search_engine_index_;
-  if (index < last_other_engine_index_)
-    --last_other_engine_index_;
-  if (observer_)
-    observer_->OnItemsRemoved(index, 1);
+  scoped_ptr<ModelEntry> entry(RemoveEntry(index));
 
   // Make sure to remove from the table model first, otherwise the
   // TemplateURL would be freed.
@@ -280,13 +273,9 @@
   data.SetURL(url);
   TemplateURL* turl = new TemplateURL(template_url_service_->profile(), data);
   template_url_service_->Add(turl);
-  ModelEntry* entry = new ModelEntry(this, turl);
+  scoped_ptr<ModelEntry> entry(new ModelEntry(this, turl));
   template_url_service_->AddObserver(this);
-  entries_.insert(entries_.begin() + index, entry);
-  if (index <= last_other_engine_index_)
-    ++last_other_engine_index_;
-  if (observer_)
-    observer_->OnItemsAdded(index, 1);
+  AddEntry(index, entry.Pass());
 }
 
 void TemplateURLTableModel::ModifyTemplateURL(int index,
@@ -332,15 +321,9 @@
   if (index < last_search_engine_index_)
     return index;  // Already in the main group.
 
-  ModelEntry* current_entry = entries_[index];
-  entries_.erase(index + entries_.begin());
-  if (observer_)
-    observer_->OnItemsRemoved(index, 1);
-
+  scoped_ptr<ModelEntry> current_entry(RemoveEntry(index));
   const int new_index = last_search_engine_index_++;
-  entries_.insert(entries_.begin() + new_index, current_entry);
-  if (observer_)
-    observer_->OnItemsAdded(new_index, 1);
+  AddEntry(new_index, current_entry.Pass());
   return new_index;
 }
 
@@ -393,3 +376,23 @@
 void TemplateURLTableModel::OnTemplateURLServiceChanged() {
   Reload();
 }
+
+scoped_ptr<ModelEntry> TemplateURLTableModel::RemoveEntry(int index) {
+  scoped_ptr<ModelEntry> entry(entries_[index]);
+  entries_.erase(index + entries_.begin());
+  if (index < last_search_engine_index_)
+    --last_search_engine_index_;
+  if (index < last_other_engine_index_)
+    --last_other_engine_index_;
+  if (observer_)
+    observer_->OnItemsRemoved(index, 1);
+  return entry.Pass();
+}
+
+void TemplateURLTableModel::AddEntry(int index, scoped_ptr<ModelEntry> entry) {
+  entries_.insert(entries_.begin() + index, entry.release());
+  if (index <= last_other_engine_index_)
+    ++last_other_engine_index_;
+  if (observer_)
+    observer_->OnItemsAdded(index, 1);
+}
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.h b/chrome/browser/ui/search_engines/template_url_table_model.h
index 5e00d97..864b48c 100644
--- a/chrome/browser/ui/search_engines/template_url_table_model.h
+++ b/chrome/browser/ui/search_engines/template_url_table_model.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/search_engines/template_url_service_observer.h"
 #include "ui/base/models/table_model.h"
@@ -110,6 +111,12 @@
   // TemplateURLServiceObserver notification.
   virtual void OnTemplateURLServiceChanged() OVERRIDE;
 
+  // Removes the entry at |index| from |entries_| and returns the removed item.
+  scoped_ptr<ModelEntry> RemoveEntry(int index);
+
+  // Adds |entry| to |entries_| at |index| and takes ownership.
+  void AddEntry(int index, scoped_ptr<ModelEntry> entry);
+
   ui::TableModelObserver* observer_;
 
   // The entries.
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
index a376e94..478abc6 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
@@ -33,6 +33,8 @@
 #include "ui/gfx/skia_util.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/button/blue_button.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/image_button.h"
@@ -535,7 +537,6 @@
     : image_view_(new views::ImageView()),
       message_stack_(new views::View()),
       button_(new views::BlueButton(listener, string16())) {
-  set_border(views::Border::CreateEmptyBorder(12, 12, 12, 12));
   set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
       GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
 
@@ -620,8 +621,12 @@
   fade_out_.reset();
 }
 
+gfx::Insets AutofillDialogViews::OverlayView::GetInsets() const {
+  return gfx::Insets(12, 12, 12, 12);
+}
+
 void AutofillDialogViews::OverlayView::Layout() {
-  gfx::Rect bounds = GetContentsBounds();
+  gfx::Rect bounds = ContentBoundsSansBubbleBorder();
   if (!message_stack_->visible()) {
     image_view_->SetBoundsRect(bounds);
     return;
@@ -653,8 +658,9 @@
 void AutofillDialogViews::OverlayView::OnPaint(gfx::Canvas* canvas) {
   // BubbleFrameView doesn't mask the window, it just draws the border via
   // image assets. Match that rounding here.
-  static const SkScalar kCornerRadius = SkIntToScalar(2);
-  gfx::Rect rect = GetContentsBounds();
+  gfx::Rect rect = ContentBoundsSansBubbleBorder();
+  const SkScalar kCornerRadius = SkIntToScalar(
+      GetBubbleBorder() ? GetBubbleBorder()->GetBorderCornerRadius() : 2);
   gfx::Path window_mask;
   window_mask.addRoundRect(gfx::RectToSkRect(rect),
                            kCornerRadius, kCornerRadius);
@@ -706,6 +712,24 @@
   views::View::PaintChildren(canvas);
 }
 
+views::BubbleBorder* AutofillDialogViews::OverlayView::GetBubbleBorder() {
+  views::View* frame = GetWidget()->non_client_view()->frame_view();
+  std::string bubble_frame_view_name(views::BubbleFrameView::kViewClassName);
+  if (frame->GetClassName() == bubble_frame_view_name)
+    return static_cast<views::BubbleFrameView*>(frame)->bubble_border();
+  NOTREACHED();
+  return NULL;
+}
+
+gfx::Rect AutofillDialogViews::OverlayView::ContentBoundsSansBubbleBorder() {
+  gfx::Rect bounds = GetContentsBounds();
+  int bubble_width = 5;
+  if (GetBubbleBorder())
+    bubble_width = GetBubbleBorder()->GetBorderThickness();
+  bounds.Inset(bubble_width, bubble_width, bubble_width, bubble_width);
+  return bounds;
+}
+
 // AutofillDialogViews::NotificationArea ---------------------------------------
 
 AutofillDialogViews::NotificationArea::NotificationArea(
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.h b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
index cae7ce1..27df407 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
@@ -35,6 +35,7 @@
 }
 
 namespace views {
+class BubbleBorder;
 class Checkbox;
 class Combobox;
 class FocusableBorder;
@@ -292,12 +293,19 @@
     virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
 
     // views::View implementation:
+    virtual gfx::Insets GetInsets() const OVERRIDE;
     virtual void Layout() OVERRIDE;
     virtual const char* GetClassName() const OVERRIDE;
     virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
     virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
 
    private:
+    // Gets the border of the non-client frame view as a BubbleBorder.
+    views::BubbleBorder* GetBubbleBorder();
+
+    // Gets the bounds of this view without the frame view's bubble border.
+    gfx::Rect ContentBoundsSansBubbleBorder();
+
     // Child View. Front and center.
     views::ImageView* image_view_;
     // Child View. When visible, below |image_view_|.
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.cc b/chrome/browser/ui/views/avatar_menu_bubble_view.cc
index 6119289..3089862 100644
--- a/chrome/browser/ui/views/avatar_menu_bubble_view.cc
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.cc
@@ -472,6 +472,7 @@
 
 // static
 AvatarMenuBubbleView* AvatarMenuBubbleView::avatar_bubble_ = NULL;
+bool AvatarMenuBubbleView::close_on_deactivate_ = true;
 
 // static
 void AvatarMenuBubbleView::ShowBubble(
@@ -487,6 +488,7 @@
   avatar_bubble_ = new AvatarMenuBubbleView(
       anchor_view, arrow, anchor_rect, browser);
   views::BubbleDelegateView::CreateBubble(avatar_bubble_);
+  avatar_bubble_->set_close_on_deactivate(close_on_deactivate_);
   avatar_bubble_->SetBackgroundColors();
   avatar_bubble_->SetAlignment(border_alignment);
   avatar_bubble_->GetWidget()->Show();
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.h b/chrome/browser/ui/views/avatar_menu_bubble_view.h
index 29597b1..c49ae45 100644
--- a/chrome/browser/ui/views/avatar_menu_bubble_view.h
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.h
@@ -79,6 +79,13 @@
   virtual void OnAvatarMenuModelChanged(
       AvatarMenuModel* avatar_menu_model) OVERRIDE;
 
+  // We normally close the bubble any time it becomes inactive but this can lead
+  // to flaky tests where unexpected UI events are triggering this behavior.
+  // Tests should call this with "false" for more consistent operation.
+  static void set_close_on_deactiavte(bool close) {
+    close_on_deactivate_ = close;
+  }
+
  private:
   AvatarMenuBubbleView(views::View* anchor_view,
                        views::BubbleBorder::Arrow arrow,
@@ -118,6 +125,7 @@
   views::Link* switch_profile_link_;
 
   static AvatarMenuBubbleView* avatar_bubble_;
+  static bool close_on_deactivate_;
 
   // Is set to true if the managed user has clicked on Switch Users.
   bool expanded_;
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index c6e21b3..1a6c4ff1 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -96,6 +96,8 @@
   AvatarMenuButton* button = GetAvatarMenuButton();
   ASSERT_TRUE(button);
 
+  AvatarMenuBubbleView::set_close_on_deactiavte(false);
+  ProfileChooserView::set_close_on_deactiavte(false);
   static_cast<views::MenuButtonListener*>(button)->OnMenuButtonClicked(
       NULL, gfx::Point());
   base::MessageLoop::current()->RunUntilIdle();
diff --git a/chrome/browser/ui/views/profile_chooser_view.cc b/chrome/browser/ui/views/profile_chooser_view.cc
index f432e77..afcd69f 100644
--- a/chrome/browser/ui/views/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profile_chooser_view.cc
@@ -30,6 +30,7 @@
 
 // static
 ProfileChooserView* ProfileChooserView::profile_bubble_ = NULL;
+bool ProfileChooserView::close_on_deactivate_ = true;
 
 // static
 void ProfileChooserView::ShowBubble(
@@ -45,6 +46,7 @@
   profile_bubble_ = new ProfileChooserView(
       anchor_view, arrow, anchor_rect, browser);
   views::BubbleDelegateView::CreateBubble(profile_bubble_);
+  profile_bubble_->set_close_on_deactivate(close_on_deactivate_);
   profile_bubble_->SetAlignment(border_alignment);
   profile_bubble_->GetWidget()->Show();
 }
diff --git a/chrome/browser/ui/views/profile_chooser_view.h b/chrome/browser/ui/views/profile_chooser_view.h
index 54dcb43..eb33739 100644
--- a/chrome/browser/ui/views/profile_chooser_view.h
+++ b/chrome/browser/ui/views/profile_chooser_view.h
@@ -43,6 +43,13 @@
   static bool IsShowing();
   static void Hide();
 
+  // We normally close the bubble any time it becomes inactive but this can lead
+  // to flaky tests where unexpected UI events are triggering this behavior.
+  // Tests should call this with "false" for more consistent operation.
+  static void set_close_on_deactiavte(bool close) {
+    close_on_deactivate_ = close;
+  }
+
  private:
   friend class AvatarMenuButtonTest;
   FRIEND_TEST_ALL_PREFIXES(AvatarMenuButtonTest, NewSignOut);
@@ -72,6 +79,7 @@
       AvatarMenuModel* avatar_menu_model) OVERRIDE;
 
   static ProfileChooserView* profile_bubble_;
+  static bool close_on_deactivate_;
 
   views::View* CreateProfileImageView(const gfx::Image& icon, int side);
   views::View* CreateProfileCardView(size_t avatar_to_show);
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
index bd4df7a..8abb284 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
@@ -87,7 +87,9 @@
 }
 
 void ChromeWebContentsViewDelegateViews::TakeFocus(bool reverse) {
-  GetFocusManager()->AdvanceFocus(reverse);
+  views::FocusManager* focus_manager = GetFocusManager();
+  if (focus_manager)
+    focus_manager->AdvanceFocus(reverse);
 }
 
 void ChromeWebContentsViewDelegateViews::StoreFocus() {
diff --git a/chrome/browser/ui/webui/chromeos/salsa_ui.cc b/chrome/browser/ui/webui/chromeos/salsa_ui.cc
index eb0bbf2..5d16335 100644
--- a/chrome/browser/ui/webui/chromeos/salsa_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/salsa_ui.cc
@@ -55,6 +55,7 @@
   prefs::kOverscrollHorizontalThresholdComplete,
   prefs::kOverscrollVerticalThresholdComplete,
   prefs::kOverscrollMinimumThresholdStart,
+  prefs::kOverscrollVerticalThresholdStart,
   prefs::kOverscrollHorizontalResistThreshold,
   prefs::kOverscrollVerticalResistThreshold,
   prefs::kImmersiveModeRevealDelayMs,
diff --git a/chrome/browser/ui/webui/identity_internals_ui.cc b/chrome/browser/ui/webui/identity_internals_ui.cc
index e575e49..3b0a167 100644
--- a/chrome/browser/ui/webui/identity_internals_ui.cc
+++ b/chrome/browser/ui/webui/identity_internals_ui.cc
@@ -19,6 +19,7 @@
 #include "content/public/browser/web_ui_controller.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
diff --git a/chrome/browser/ui/webui/ntp/ntp_login_handler.cc b/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
index a5c8050..f20351e 100644
--- a/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
@@ -38,11 +38,11 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
+#include "content/public/common/page_zoom.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
 #include "skia/ext/image_operations.h"
-#include "third_party/WebKit/public/web/WebView.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/image/image.h"
@@ -164,8 +164,7 @@
     success = args->GetDouble(3, &height);
     DCHECK(success);
 
-    double zoom =
-        WebKit::WebView::zoomLevelToZoomFactor(web_contents->GetZoomLevel());
+    double zoom = content::ZoomLevelToZoomFactor(web_contents->GetZoomLevel());
     gfx::Rect rect(x * zoom, y * zoom, width * zoom, height * zoom);
 
     browser->window()->ShowAvatarBubble(web_ui()->GetWebContents(), rect);
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index 800b984..d6aed6a 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -79,7 +79,6 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
-#include "third_party/WebKit/public/web/WebView.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/webui/web_ui_util.h"
@@ -1468,8 +1467,7 @@
 void BrowserOptionsHandler::HandleDefaultZoomFactor(const ListValue* args) {
   double zoom_factor;
   if (ExtractDoubleValue(args, &zoom_factor)) {
-    default_zoom_level_.SetValue(
-        WebKit::WebView::zoomFactorToZoomLevel(zoom_factor));
+    default_zoom_level_.SetValue(content::ZoomFactorToZoomLevel(zoom_factor));
   }
 }
 
@@ -1670,7 +1668,7 @@
   PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
   double default_zoom_level = pref_service->GetDouble(prefs::kDefaultZoomLevel);
   double default_zoom_factor =
-      WebKit::WebView::zoomLevelToZoomFactor(default_zoom_level);
+      content::ZoomLevelToZoomFactor(default_zoom_level);
 
   // Generate a vector of zoom factors from an array of known presets along with
   // the default factor added if necessary.
diff --git a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
index c8b991d..ad50697 100644
--- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
@@ -1011,14 +1011,8 @@
 void InternetOptionsHandler::EnableCellularCallback(
     const base::ListValue* args) {
   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
-  if (!handler->IsTechnologyEnabled(NetworkStateHandler::kMatchTypeMobile)) {
-    handler->SetTechnologyEnabled(
-        NetworkStateHandler::kMatchTypeMobile, true,
-        base::Bind(&ShillError, "EnableCellularCallback"));
-    return;
-  }
-  const DeviceState* device = handler->GetDeviceStateByType(
-      NetworkStateHandler::kMatchTypeMobile);
+  const DeviceState* device =
+      handler->GetDeviceStateByType(flimflam::kTypeCellular);
   if (!device) {
     LOG(ERROR) << "Mobile device not found.";
     return;
@@ -1028,6 +1022,12 @@
                                   SimDialogDelegate::SIM_DIALOG_UNLOCK);
     return;
   }
+  if (!handler->IsTechnologyEnabled(flimflam::kTypeCellular)) {
+    handler->SetTechnologyEnabled(
+        flimflam::kTypeCellular, true,
+        base::Bind(&ShillError, "EnableCellularCallback"));
+    return;
+  }
   if (device->IsSimAbsent()) {
     MobileConfig* config = MobileConfig::GetInstance();
     if (config->IsReady()) {
diff --git a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
index f28ec88..68ee2bb 100644
--- a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
@@ -28,6 +28,7 @@
 namespace options {
 
 ResetProfileSettingsHandler::ResetProfileSettingsHandler() {
+  google_util::GetBrand(&brandcode_);
 }
 
 ResetProfileSettingsHandler::~ResetProfileSettingsHandler() {
@@ -68,8 +69,8 @@
 
 void ResetProfileSettingsHandler::HandleResetProfileSettings(
     const ListValue* /*value*/) {
-  DCHECK(config_fetcher_);
-  if (config_fetcher_->IsActive()) {
+  DCHECK(brandcode_.empty() || config_fetcher_);
+  if (config_fetcher_ && config_fetcher_->IsActive()) {
     // Reset once the prefs are fetched.
     config_fetcher_->SetCallback(
         base::Bind(&ResetProfileSettingsHandler::ResetProfile,
@@ -84,11 +85,13 @@
 }
 
 void ResetProfileSettingsHandler::OnShowResetProfileDialog(const ListValue*) {
-  // TODO(vasilii): use a real request.
+  if (brandcode_.empty())
+    return;
   config_fetcher_.reset(new BrandcodeConfigFetcher(
       base::Bind(&ResetProfileSettingsHandler::OnSettingsFetched,
                  Unretained(this)),
-      GURL("https://tools.google.com/service/update2")));
+      GURL("https://tools.google.com/service/update2"),
+      brandcode_));
 }
 
 void ResetProfileSettingsHandler::OnSettingsFetched() {
@@ -100,13 +103,18 @@
 void ResetProfileSettingsHandler::ResetProfile() {
   DCHECK(resetter_);
   DCHECK(!resetter_->IsActive());
-  DCHECK(config_fetcher_);
-  DCHECK(!config_fetcher_->IsActive());
 
-  scoped_ptr<BrandcodedDefaultSettings> default_settings =
-      config_fetcher_->GetSettings();
-  config_fetcher_.reset();
-  // If we failed to fetch BrandcodedDefaultSettings, use default settings.
+  scoped_ptr<BrandcodedDefaultSettings> default_settings;
+  if (config_fetcher_) {
+    DCHECK(!config_fetcher_->IsActive());
+    default_settings = config_fetcher_->GetSettings();
+    config_fetcher_.reset();
+  } else {
+    DCHECK(brandcode_.empty());
+  }
+
+  // If failed to fetch BrandcodedDefaultSettings or this is an organic
+  // installation, use default settings.
   if (!default_settings)
     default_settings.reset(new BrandcodedDefaultSettings);
   resetter_->Reset(
diff --git a/chrome/browser/ui/webui/options/reset_profile_settings_handler.h b/chrome/browser/ui/webui/options/reset_profile_settings_handler.h
index 999b023..9431590 100644
--- a/chrome/browser/ui/webui/options/reset_profile_settings_handler.h
+++ b/chrome/browser/ui/webui/options/reset_profile_settings_handler.h
@@ -54,6 +54,9 @@
 
   scoped_ptr<BrandcodeConfigFetcher> config_fetcher_;
 
+  // Contains Chrome brand code; empty for organic Chrome.
+  std::string brandcode_;
+
   DISALLOW_COPY_AND_ASSIGN(ResetProfileSettingsHandler);
 };
 
diff --git a/chrome/browser/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector_impl.cc
index 15602d4..0bfdbf5 100644
--- a/chrome/browser/upgrade_detector_impl.cc
+++ b/chrome/browser/upgrade_detector_impl.cc
@@ -14,6 +14,7 @@
 #include "base/memory/singleton.h"
 #include "base/metrics/field_trial.h"
 #include "base/path_service.h"
+#include "base/process/launch.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"