Merge from Chromium at DEPS revision r213371

This commit was generated by merge_to_master.py.

Change-Id: I35a74205de4bff52a2dd6b15330f8a002a39efaf
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 278632f..b5c1fc7 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -105,6 +105,7 @@
   "+third_party/WebKit/public/web/WebPluginAction.h",
   "+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/about_flags.cc b/chrome/browser/about_flags.cc
index fe000fc..ca66678 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1116,6 +1116,13 @@
     SINGLE_VALUE_TYPE(chromeos::switches::kFileManagerEnableFolderShortcuts)
   },
   {
+    "file-manager-enable-webstore-integration",
+    IDS_FLAGS_FILE_MANAGER_ENABLE_WEBSTORE_INTEGRATION,
+    IDS_FLAGS_FILE_MANAGER_ENABLE_WEBSTORE_INTEGRATION_DESCRIPTION,
+    kOsCrOS,
+    SINGLE_VALUE_TYPE(chromeos::switches::kFileManagerEnableWebstoreIntegration)
+  },
+  {
     "disable-quickoffice-component-app",
     IDS_FLAGS_DISABLE_QUICKOFFICE_COMPONENT_APP_NAME,
     IDS_FLAGS_DISABLE_QUICKOFFICE_COMPONENT_APP_DESCRIPTION,
@@ -1578,6 +1585,13 @@
     kOsCrOS,
     SINGLE_VALUE_TYPE(switches::kEnableQuickofficeEdit),
   },
+  {
+    "enable-sticky-keys",
+    IDS_FLAGS_ENABLE_STICKY_KEYS_NAME,
+    IDS_FLAGS_ENABLE_STICKY_KEYS_DESCRIPTION,
+    kOsCrOS,
+    SINGLE_VALUE_TYPE(switches::kEnableStickyKeys),
+  },
 #endif
   {
     "enable-translate-settings",
diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc
index b32cadc..4aeb1c1 100644
--- a/chrome/browser/autocomplete/search_provider_unittest.cc
+++ b/chrome/browser/autocomplete/search_provider_unittest.cc
@@ -31,7 +31,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_status.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -78,10 +78,7 @@
         term1_(ASCIIToUTF16("term1")),
         keyword_t_url_(NULL),
         keyword_term_(ASCIIToUTF16("keyword")),
-        ui_thread_(content::BrowserThread::UI, &message_loop_),
-        io_thread_(content::BrowserThread::IO),
-        quit_when_done_(false) {
-    io_thread_.Start();
+        run_loop_(NULL) {
   }
 
   static void SetUpTestCase();
@@ -117,9 +114,6 @@
   // If we're waiting for the provider to finish, this exits the message loop.
   virtual void OnProviderUpdate(bool updated_matches) OVERRIDE;
 
-  // Waits until the provider instantiates a URLFetcher and returns it.
-  net::TestURLFetcher* WaitUntilURLFetcherIsReady(int fetcher_id);
-
   // Runs a nested message loop until provider_ is done. The message loop is
   // exited by way of OnProviderUpdate.
   void RunTillProviderDone();
@@ -147,9 +141,7 @@
   const string16 keyword_term_;
   GURL keyword_url_;
 
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   // URLFetcherFactory implementation registered.
   net::TestURLFetcherFactory test_factory_;
@@ -160,8 +152,8 @@
   // The provider.
   scoped_refptr<SearchProvider> provider_;
 
-  // If true, OnProviderUpdate exits out of the current message loop.
-  bool quit_when_done_;
+  // If non-NULL, OnProviderUpdate quits the current |run_loop_|.
+  base::RunLoop* run_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchProviderTest);
 };
@@ -238,7 +230,7 @@
 }
 
 void SearchProviderTest::TearDown() {
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Shutdown the provider before the profile.
   provider_ = NULL;
@@ -273,32 +265,19 @@
 }
 
 void SearchProviderTest::OnProviderUpdate(bool updated_matches) {
-  if (quit_when_done_ && provider_->done()) {
-    quit_when_done_ = false;
-    message_loop_.Quit();
+  if (run_loop_ && provider_->done()) {
+    run_loop_->Quit();
+    run_loop_ = NULL;
   }
 }
 
-net::TestURLFetcher* SearchProviderTest::WaitUntilURLFetcherIsReady(
-    int fetcher_id) {
-  net::TestURLFetcher* url_fetcher = test_factory_.GetFetcherByID(fetcher_id);
-  for (; !url_fetcher; url_fetcher = test_factory_.GetFetcherByID(fetcher_id))
-    message_loop_.RunUntilIdle();
-  return url_fetcher;
-}
-
 void SearchProviderTest::RunTillProviderDone() {
   if (provider_->done())
     return;
 
-  quit_when_done_ = true;
-#if defined(OS_ANDROID)
-  // Android doesn't have Run(), only Start().
-  message_loop_.Start();
-#else
   base::RunLoop run_loop;
+  run_loop_ = &run_loop;
   run_loop.Run();
-#endif
 }
 
 void SearchProviderTest::QueryForInput(const string16& text,
@@ -312,7 +291,7 @@
 
   // RunUntilIdle so that the task scheduled by SearchProvider to create the
   // URLFetchers runs.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 void SearchProviderTest::QueryForInputAndSetWYTMatch(
@@ -372,8 +351,9 @@
 }
 
 void SearchProviderTest::FinishDefaultSuggestQuery() {
-  net::TestURLFetcher* default_fetcher = WaitUntilURLFetcherIsReady(
-      SearchProvider::kDefaultProviderURLFetcherID);
+  net::TestURLFetcher* default_fetcher =
+      test_factory_.GetFetcherByID(
+          SearchProvider::kDefaultProviderURLFetcherID);
   ASSERT_TRUE(default_fetcher);
 
   // Tell the SearchProvider the default suggest query is done.
@@ -1041,8 +1021,9 @@
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
     QueryForInput(ASCIIToUTF16("a"), false, false);
-    net::TestURLFetcher* fetcher = WaitUntilURLFetcherIsReady(
-        SearchProvider::kDefaultProviderURLFetcherID);
+    net::TestURLFetcher* fetcher =
+        test_factory_.GetFetcherByID(
+            SearchProvider::kDefaultProviderURLFetcherID);
     ASSERT_TRUE(fetcher);
     fetcher->set_response_code(200);
     fetcher->SetResponseString(cases[i].json);
@@ -1506,16 +1487,18 @@
     QueryForInput(ASCIIToUTF16("k a"), false, true);
 
     // Set up a default fetcher with no results.
-    net::TestURLFetcher* default_fetcher = WaitUntilURLFetcherIsReady(
-        SearchProvider::kDefaultProviderURLFetcherID);
+    net::TestURLFetcher* default_fetcher =
+        test_factory_.GetFetcherByID(
+            SearchProvider::kDefaultProviderURLFetcherID);
     ASSERT_TRUE(default_fetcher);
     default_fetcher->set_response_code(200);
     default_fetcher->delegate()->OnURLFetchComplete(default_fetcher);
     default_fetcher = NULL;
 
     // Set up a keyword fetcher with provided results.
-    net::TestURLFetcher* keyword_fetcher = WaitUntilURLFetcherIsReady(
-        SearchProvider::kKeywordProviderURLFetcherID);
+    net::TestURLFetcher* keyword_fetcher =
+        test_factory_.GetFetcherByID(
+            SearchProvider::kKeywordProviderURLFetcherID);
     ASSERT_TRUE(keyword_fetcher);
     keyword_fetcher->set_response_code(200);
     keyword_fetcher->SetResponseString(cases[i].json);
@@ -1626,8 +1609,9 @@
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
     QueryForInput(cases[i].input, false, false);
-    net::TestURLFetcher* fetcher = WaitUntilURLFetcherIsReady(
-        SearchProvider::kDefaultProviderURLFetcherID);
+    net::TestURLFetcher* fetcher =
+        test_factory_.GetFetcherByID(
+            SearchProvider::kDefaultProviderURLFetcherID);
     ASSERT_TRUE(fetcher);
     fetcher->set_response_code(200);
     fetcher->SetResponseString(cases[i].json);
@@ -1726,8 +1710,9 @@
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
     QueryForInput(ASCIIToUTF16(cases[i].input), false, false);
-    net::TestURLFetcher* fetcher = WaitUntilURLFetcherIsReady(
-        SearchProvider::kDefaultProviderURLFetcherID);
+    net::TestURLFetcher* fetcher =
+        test_factory_.GetFetcherByID(
+            SearchProvider::kDefaultProviderURLFetcherID);
     ASSERT_TRUE(fetcher);
     fetcher->set_response_code(200);
     fetcher->SetResponseString(cases[i].json);
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 96456e5..316ccc0 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -351,6 +351,9 @@
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
       download_danger_type_string = "DANGEROUS_HOST";
       break;
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+      download_danger_type_string = "POTENTIALLY_UNWANTED";
+      break;
     case content::DOWNLOAD_DANGER_TYPE_MAX:
       NOTREACHED();
       download_danger_type_string = "UNKNOWN";
diff --git a/chrome/browser/automation/automation_provider_observers_chromeos.cc b/chrome/browser/automation/automation_provider_observers_chromeos.cc
index 3f973ee..ff954a9 100644
--- a/chrome/browser/automation/automation_provider_observers_chromeos.cc
+++ b/chrome/browser/automation/automation_provider_observers_chromeos.cc
@@ -64,7 +64,7 @@
       WizardController::default_controller()->current_screen()) {
     OOBEWebuiReady();
   } else {
-    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                    content::NotificationService::AllSources());
   }
 }
@@ -73,7 +73,7 @@
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
-  DCHECK(type == chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE);
+  DCHECK(type == chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE);
   OOBEWebuiReady();
 }
 
diff --git a/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc
index b138ac7..b06f9ae 100644
--- a/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/bind_helpers.h"
 #include "base/stl_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -29,7 +30,9 @@
 
 }  // namespace
 
-typedef testing::Test CannedBrowsingDataAppCacheHelperTest;
+class CannedBrowsingDataAppCacheHelperTest : public testing::Test {
+  content::TestBrowserThreadBundle thread_bundle_;
+};
 
 TEST_F(CannedBrowsingDataAppCacheHelperTest, SetInfo) {
   TestingProfile profile;
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
index eb6ab9f..7e02b83 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
@@ -5,45 +5,20 @@
 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/parsed_cookie.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 namespace {
 
 class BrowsingDataCookieHelperTest : public testing::Test {
  public:
-  void SetUpOnIOThread() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    // This is a workaround for a bug in the TestingProfile.
-    // The URLRequestContext will be created by GetCookieMonster on the UI
-    // thread, if it does not already exist. But it must be created on the IO
-    // thread or else it will DCHECK upon destruction.
-    // Force it to be created here.
-    testing_profile_->CreateRequestContext();
-    testing_profile_->GetRequestContext()->GetURLRequestContext();
-  }
-
-  virtual void SetUp() {
-    testing_profile_.reset(new TestingProfile());
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::Bind(&BrowsingDataCookieHelperTest::SetUpOnIOThread,
-                   base::Unretained(this)));
-    base::MessageLoop::current()->RunUntilIdle();
-  }
-
-  virtual void TearDown() {
-    // This must be reset before the IO thread stops, because the
-    // URLRequestContextGetter forces its own deletion to occur on that thread.
-    testing_profile_->ResetRequestContext();
+  BrowsingDataCookieHelperTest()
+      : testing_profile_(new TestingProfile()) {
   }
 
   void CreateCookiesForTest() {
@@ -83,7 +58,6 @@
     EXPECT_EQ("B", it->Name());
 
     ASSERT_TRUE(++it == cookies.end());
-    base::MessageLoop::current()->Quit();
   }
 
   void DomainCookieCallback(const net::CookieList& cookies) {
@@ -103,7 +77,6 @@
     EXPECT_EQ("2", it->Value());
 
     ASSERT_TRUE(++it == cookies.end());
-    base::MessageLoop::current()->Quit();
   }
 
   void DeleteCallback(const net::CookieList& cookies) {
@@ -115,7 +88,6 @@
     EXPECT_EQ("B", it->Name());
 
     ASSERT_TRUE(++it == cookies.end());
-    base::MessageLoop::current()->Quit();
   }
 
   void CannedUniqueCallback(const net::CookieList& cookies) {
@@ -212,9 +184,7 @@
   cookie_helper->StartFetching(
       base::Bind(&BrowsingDataCookieHelperTest::FetchCallback,
                  base::Unretained(this)));
-
-  // Blocks until BrowsingDataCookieHelperTest::FetchCallback is notified.
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(BrowsingDataCookieHelperTest, DomainCookie) {
@@ -225,9 +195,7 @@
   cookie_helper->StartFetching(
       base::Bind(&BrowsingDataCookieHelperTest::DomainCookieCallback,
                  base::Unretained(this)));
-
-  // Blocks until BrowsingDataCookieHelperTest::FetchCallback is notified.
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(BrowsingDataCookieHelperTest, DeleteCookie) {
@@ -238,9 +206,7 @@
   cookie_helper->StartFetching(
       base::Bind(&BrowsingDataCookieHelperTest::FetchCallback,
                  base::Unretained(this)));
-
-  // Blocks until BrowsingDataCookieHelperTest::FetchCallback is notified.
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 
   net::CanonicalCookie cookie = cookie_list_[0];
   cookie_helper->DeleteCookie(cookie);
@@ -248,7 +214,7 @@
   cookie_helper->StartFetching(
       base::Bind(&BrowsingDataCookieHelperTest::DeleteCallback,
                  base::Unretained(this)));
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(BrowsingDataCookieHelperTest, CannedDomainCookie) {
diff --git a/chrome/browser/browsing_data/browsing_data_database_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_database_helper_unittest.cc
index 565ef8c..276cb89 100644
--- a/chrome/browser/browsing_data/browsing_data_database_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_database_helper_unittest.cc
@@ -4,24 +4,14 @@
 
 #include "chrome/browser/browsing_data/browsing_data_database_helper.h"
 
-#include "base/message_loop/message_loop.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 namespace {
 
 class CannedBrowsingDataDatabaseHelperTest : public testing::Test {
- public:
-  CannedBrowsingDataDatabaseHelperTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_) {
-  }
-
- protected:
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 TEST_F(CannedBrowsingDataDatabaseHelperTest, Empty) {
diff --git a/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc
index 2ad644a..e9739e1 100644
--- a/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc
@@ -5,11 +5,14 @@
 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
 
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-typedef testing::Test CannedBrowsingDataLocalStorageTest;
+class CannedBrowsingDataLocalStorageTest : public testing::Test {
+  content::TestBrowserThreadBundle thread_bundle_;
+};
 
 TEST_F(CannedBrowsingDataLocalStorageTest, Empty) {
   TestingProfile profile;
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
index 3d659ce..fc758e4 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -223,7 +223,6 @@
 class RemoveProfileCookieTester : public RemoveCookieTester {
  public:
   explicit RemoveProfileCookieTester(TestingProfile* profile) {
-    profile->CreateRequestContext();
     SetMonster(profile->GetRequestContext()->GetURLRequestContext()->
         cookie_store()->GetCookieMonster());
   }
@@ -265,7 +264,6 @@
  public:
   explicit RemoveServerBoundCertTester(TestingProfile* profile)
       : ssl_config_changed_count_(0) {
-    profile->CreateRequestContext();
     server_bound_cert_service_ = profile->GetRequestContext()->
         GetURLRequestContext()->server_bound_cert_service();
     ssl_config_service_ = profile->GetSSLConfigService();
diff --git a/chrome/browser/browsing_data/browsing_data_server_bound_cert_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_server_bound_cert_helper_unittest.cc
index 68db3dc..4a12c5a 100644
--- a/chrome/browser/browsing_data/browsing_data_server_bound_cert_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_server_bound_cert_helper_unittest.cc
@@ -5,10 +5,10 @@
 #include "chrome/browser/browsing_data/browsing_data_server_bound_cert_helper.h"
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/run_loop.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/ssl/server_bound_cert_service.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -24,12 +24,7 @@
   }
 
   virtual void SetUp() OVERRIDE {
-    ui_thread_.reset(new content::TestBrowserThread(BrowserThread::UI,
-                                                    &message_loop_));
-    io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO,
-                                                    &message_loop_));
     testing_profile_.reset(new TestingProfile());
-    testing_profile_->CreateRequestContext();
 
     testing_profile_->GetSSLConfigService()->AddObserver(this);
   }
@@ -57,7 +52,6 @@
       const net::ServerBoundCertStore::ServerBoundCertList& certs) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     server_bound_cert_list_ = certs;
-    base::MessageLoop::current()->Quit();
   }
 
   // net::SSLConfigService::Observer implementation:
@@ -66,9 +60,7 @@
   }
 
  protected:
-  base::MessageLoop message_loop_;
-  scoped_ptr<content::TestBrowserThread> ui_thread_;
-  scoped_ptr<content::TestBrowserThread> io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> testing_profile_;
 
   net::ServerBoundCertStore::ServerBoundCertList server_bound_cert_list_;
@@ -87,7 +79,7 @@
 
   // Blocks until BrowsingDataServerBoundCertHelperTest::FetchCallback is
   // notified.
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(2UL, server_bound_cert_list_.size());
   net::ServerBoundCertStore::ServerBoundCertList::const_iterator it =
@@ -116,7 +108,7 @@
   helper->StartFetching(
       base::Bind(&BrowsingDataServerBoundCertHelperTest::FetchCallback,
                  base::Unretained(this)));
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(1, ssl_config_changed_count_);
   ASSERT_EQ(1UL, server_bound_cert_list_.size());
@@ -133,7 +125,8 @@
   helper->StartFetching(
       base::Bind(&BrowsingDataServerBoundCertHelperTest::FetchCallback,
                  base::Unretained(this)));
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(2, ssl_config_changed_count_);
   ASSERT_EQ(0UL, server_bound_cert_list_.size());
 }
@@ -155,7 +148,7 @@
   helper->StartFetching(
       base::Bind(&BrowsingDataServerBoundCertHelperTest::FetchCallback,
                  base::Unretained(this)));
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(1UL, server_bound_cert_list_.size());
   net::ServerBoundCertStore::ServerBoundCert& cert =
diff --git a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
index af509bc..6b6825d 100644
--- a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
@@ -47,7 +47,6 @@
 
   virtual void SetUp() OVERRIDE {
     profile_.reset(new TestingProfile());
-    profile_->CreateRequestContext();
     mock_browsing_data_cookie_helper_ =
         new MockBrowsingDataCookieHelper(profile_->GetRequestContext());
     mock_browsing_data_database_helper_ =
diff --git a/chrome/browser/captive_portal/captive_portal_detector_unittest.cc b/chrome/browser/captive_portal/captive_portal_detector_unittest.cc
index 00c2489..49bd2b9 100644
--- a/chrome/browser/captive_portal/captive_portal_detector_unittest.cc
+++ b/chrome/browser/captive_portal/captive_portal_detector_unittest.cc
@@ -6,10 +6,11 @@
 
 #include "base/basictypes.h"
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chrome/browser/captive_portal/testing_utils.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_fetcher.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -72,7 +73,7 @@
                    base::Unretained(&client)));
 
     ASSERT_TRUE(FetchingURL());
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
 
     CompleteURLFetch(net_error, status_code, response_headers);
 
@@ -96,7 +97,7 @@
                    base::Unretained(&client)));
 
     ASSERT_TRUE(FetchingURL());
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
 
     detector()->Cancel();
 
@@ -105,7 +106,7 @@
   }
 
  private:
-  base::MessageLoop message_loop_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   // Definition order does matter.
   TestingProfile profile_;
diff --git a/chrome/browser/captive_portal/captive_portal_service_unittest.cc b/chrome/browser/captive_portal/captive_portal_service_unittest.cc
index 17cba3a..7357b22 100644
--- a/chrome/browser/captive_portal/captive_portal_service_unittest.cc
+++ b/chrome/browser/captive_portal/captive_portal_service_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
 #include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
 #include "base/test/test_timeouts.h"
 #include "chrome/browser/captive_portal/testing_utils.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -20,6 +20,7 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -167,7 +168,7 @@
     EXPECT_FALSE(FetchingURL());
     ASSERT_TRUE(TimerRunning());
 
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     EXPECT_EQ(CaptivePortalService::STATE_CHECKING_FOR_PORTAL,
               service()->state());
     ASSERT_TRUE(FetchingURL());
@@ -199,7 +200,7 @@
     EXPECT_FALSE(FetchingURL());
     ASSERT_TRUE(TimerRunning());
 
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     EXPECT_FALSE(FetchingURL());
     EXPECT_FALSE(TimerRunning());
     EXPECT_EQ(1, observer.num_results_received());
@@ -274,7 +275,7 @@
   // after the test.
   const CaptivePortalService::TestingState old_captive_portal_testing_state_;
 
-  base::MessageLoop message_loop_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   // Note that the construction order of these matters.
   scoped_ptr<TestingProfile> profile_;
@@ -372,7 +373,7 @@
   // Needed to create the URLFetcher, even if it never returns any results.
   service()->DetectCaptivePortal();
 
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(FetchingURL());
   EXPECT_FALSE(TimerRunning());
 
@@ -381,7 +382,7 @@
   EXPECT_TRUE(TimerRunning());
   EXPECT_EQ(0, observer.num_results_received());
 
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(FetchingURL());
   EXPECT_FALSE(TimerRunning());
@@ -406,7 +407,7 @@
   EXPECT_TRUE(TimerRunning());
   EXPECT_EQ(0, observer.num_results_received());
 
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(FetchingURL());
   EXPECT_FALSE(TimerRunning());
@@ -432,7 +433,7 @@
   EXPECT_FALSE(FetchingURL());
   EXPECT_TRUE(TimerRunning());
 
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(FetchingURL());
   EXPECT_FALSE(TimerRunning());
 
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index b8e5204..5d316ee 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -62,6 +62,7 @@
 #include "chrome/browser/gpu/chrome_gpu_util.h"
 #include "chrome/browser/gpu/gl_string_manager.h"
 #include "chrome/browser/jankometer.h"
+#include "chrome/browser/language_usage_metrics.h"
 #include "chrome/browser/metrics/field_trial_synchronizer.h"
 #include "chrome/browser/metrics/metrics_log.h"
 #include "chrome/browser/metrics/metrics_service.h"
@@ -186,10 +187,6 @@
 #include "chrome/browser/mac/keystone_glue.h"
 #endif
 
-#if defined(ENABLE_LANGUAGE_DETECTION)
-#include "chrome/browser/language_usage_metrics.h"
-#endif
-
 #if defined(ENABLE_RLZ)
 #include "chrome/browser/rlz/rlz.h"
 #endif
@@ -1474,12 +1471,10 @@
   browser_process_->metrics_service()->RecordBreakpadHasDebugger(
       base::debug::BeingDebugged());
 
-#if defined(ENABLE_LANGUAGE_DETECTION)
   LanguageUsageMetrics::RecordAcceptLanguages(
       profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
   LanguageUsageMetrics::RecordApplicationLanguage(
       browser_process_->GetApplicationLocale());
-#endif
 
   // The extension service may be available at this point. If the command line
   // specifies --uninstall-extension, attempt the uninstall extension startup
@@ -1692,11 +1687,10 @@
   for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
     chrome_extra_parts_[i]->PostMainMessageLoopRun();
 
-  // Some tests don't set parameters.ui_task, so they started translate
-  // language fetch that was never completed so we need to cleanup here
+  // TranslateManager's URL fetchers should be destructed in the main thread
   // otherwise it will be done by the destructor in a wrong thread.
-  if (parameters().ui_task == NULL && translate_manager_ != NULL)
-    translate_manager_->CleanupPendingUlrFetcher();
+  if (translate_manager_ != NULL)
+    translate_manager_->CleanupPendingUrlFetcher();
 
   if (notify_result_ == ProcessSingleton::PROCESS_NONE)
     process_singleton_->Cleanup();
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 8aa4767..a166d59 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -935,7 +935,7 @@
   if (!profile)
     return false;
 
-  if (chrome::ShouldAssignURLToInstantRenderer(effective_url, profile))
+  if (chrome::ShouldUseProcessPerSiteForInstantURL(effective_url, profile))
     return true;
 
 #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index cdb907e..4967585 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -925,8 +925,8 @@
   // Sent when webui lock screen wallpaper is loaded and displayed.
   NOTIFICATION_LOCK_BACKGROUND_DISPLAYED,
 
-  // Sent when GAIA iframe has been loaded.
-  // First paint event after this fires NOTIFICATION_LOGIN_WEBUI_VISIBLE.
+  // Sent when GAIA iframe has been loaded. First paint event after this fires
+  // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
   // Possible scenarios:
   // 1. Boot into device that has user pods display disabled or no users.
   //    Note that booting with network not connected would first generate
@@ -942,26 +942,26 @@
   NOTIFICATION_LOGIN_WEBUI_LOADED,
 
   // Sent when the login screen has loaded in retail mode. The first paint event
-  // after this fires NOTIFICATION_LOGIN_WEBUI_VISIBLE.
+  // after this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
   NOTIFICATION_DEMO_WEBUI_LOADED,
 
   // Sent when the user images on the WebUI login screen have all been loaded.
   // "Normal boot" i.e. for the device with at least one user would generate
-  // this one on boot.
-  // First paint event after this fires NOTIFICATION_LOGIN_WEBUI_VISIBLE.
+  // this one on boot. First paint event after this fires
+  // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
   NOTIFICATION_LOGIN_USER_IMAGES_LOADED,
 
   // Sent when a network error message is displayed on the WebUI login screen.
-  // First paint event of this fires NOTIFICATION_LOGIN_WEBUI_VISIBLE.
+  // First paint event of this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
   NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
 
   // Sent when the first OOBE screen has been displayed. Note that the screen
-  // may not be fully rendered at this point.
-  // First paint event after this fires NOTIFICATION_LOGIN_WEBUI_VISIBLE.
+  // may not be fully rendered at this point. First paint event after this fires
+  // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
   NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN,
 
-  // Sent when the specific part of login WebUI is considered to be visible.
-  // That moment is tracked as the first paint event after one of the:
+  // Sent when the specific part of login/lock WebUI is considered to be
+  // visible. That moment is tracked as the first paint event after one of the:
   // 1. NOTIFICATION_LOGIN_USER_IMAGES_LOADED
   // 2. NOTIFICATION_LOGIN_WEBUI_LOADED
   // 3. NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
@@ -971,22 +971,22 @@
   // Possible series of notifications:
   // 1. Boot into fresh OOBE
   //    NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN
-  //    NOTIFICATION_LOGIN_WEBUI_VISIBLE
-  // 2. Boot into user pods list (normal boot)
+  //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
+  // 2. Boot into user pods list (normal boot). Same for lock screen.
   //    NOTIFICATION_LOGIN_USER_IMAGES_LOADED
-  //    NOTIFICATION_LOGIN_WEBUI_VISIBLE
+  //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 3. Boot into GAIA sign in UI (user pods display disabled or no users):
   //    if no network is connected or flaky network
   //    (NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN +
-  //     NOTIFICATION_LOGIN_WEBUI_VISIBLE)
+  //     NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE)
   //    NOTIFICATION_LOGIN_WEBUI_LOADED
-  //    NOTIFICATION_LOGIN_WEBUI_VISIBLE
+  //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 4. Boot into retail mode
   //    NOTIFICATION_DEMO_WEBUI_LOADED
-  //    NOTIFICATION_LOGIN_WEBUI_VISIBLE
+  //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 5. Boot into kiosk mode
   //    NOTIFICATION_KIOSK_APP_LAUNCHED
-  NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+  NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
 
   // Sent when proxy dialog is closed.
   NOTIFICATION_LOGIN_PROXY_CHANGED,
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index f6e412e..717112e 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -119,6 +119,63 @@
   std::queue<extensions::ExtensionResource> resources_;
 };
 
+void LoadChromeVoxExtension(Profile* profile, content::WebUI* login_web_ui) {
+  ExtensionService* extension_service =
+      extensions::ExtensionSystem::Get(profile)->extension_service();
+  base::FilePath path = base::FilePath(extension_misc::kChromeVoxExtensionPath);
+  std::string extension_id =
+      extension_service->component_loader()->Add(IDR_CHROMEVOX_MANIFEST,
+                                                 path);
+  if (login_web_ui) {
+    ExtensionService* extension_service =
+        extensions::ExtensionSystem::Get(profile)->extension_service();
+    const extensions::Extension* extension =
+        extension_service->extensions()->GetByID(extension_id);
+
+    RenderViewHost* render_view_host =
+        login_web_ui->GetWebContents()->GetRenderViewHost();
+    // Set a flag to tell ChromeVox that it's just been enabled,
+    // so that it won't interrupt our speech feedback enabled message.
+    ExtensionMsg_ExecuteCode_Params params;
+    params.request_id = 0;
+    params.extension_id = extension->id();
+    params.is_javascript = true;
+    params.code = "window.INJECTED_AFTER_LOAD = true;";
+    params.run_at = extensions::UserScript::DOCUMENT_IDLE;
+    params.all_frames = true;
+    params.in_main_world = false;
+    render_view_host->Send(new ExtensionMsg_ExecuteCode(
+        render_view_host->GetRoutingID(), params));
+
+    // Inject ChromeVox' content scripts.
+    ContentScriptLoader* loader = new ContentScriptLoader(
+        extension->id(), render_view_host->GetProcess()->GetID(),
+        render_view_host->GetRoutingID());
+
+    const extensions::UserScriptList& content_scripts =
+        extensions::ContentScriptsInfo::GetContentScripts(extension);
+    for (size_t i = 0; i < content_scripts.size(); i++) {
+      const extensions::UserScript& script = content_scripts[i];
+      for (size_t j = 0; j < script.js_scripts().size(); ++j) {
+        const extensions::UserScript::File &file = script.js_scripts()[j];
+        extensions::ExtensionResource resource = extension->GetResource(
+            file.relative_path());
+        loader->AppendScript(resource);
+      }
+    }
+    loader->Run();  // It cleans itself up when done.
+  }
+  DLOG(INFO) << "ChromeVox was Loaded.";
+}
+
+void UnloadChromeVoxExtension(Profile* profile) {
+  ExtensionService* extension_service =
+      extensions::ExtensionSystem::Get(profile)->extension_service();
+  base::FilePath path = base::FilePath(extension_misc::kChromeVoxExtensionPath);
+  extension_service->component_loader()->Remove(path);
+  DLOG(INFO) << "ChromeVox was Unloaded.";
+}
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -202,6 +259,8 @@
 
 AccessibilityManager::AccessibilityManager()
     : profile_(NULL),
+      chrome_vox_loaded_on_lock_screen_(false),
+      chrome_vox_loaded_on_user_screen_(false),
       large_cursor_pref_handler_(prefs::kLargeCursorEnabled),
       spoken_feedback_pref_handler_(prefs::kSpokenFeedbackEnabled),
       high_contrast_pref_handler_(prefs::kHighContrastEnabled),
@@ -210,8 +269,9 @@
       spoken_feedback_enabled_(false),
       high_contrast_enabled_(false),
       spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE) {
+
   notification_registrar_.Add(this,
-                              chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+                              chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                               content::NotificationService::AllSources());
   notification_registrar_.Add(this,
                               chrome::NOTIFICATION_SESSION_STARTED,
@@ -219,6 +279,9 @@
   notification_registrar_.Add(this,
                               chrome::NOTIFICATION_PROFILE_DESTROYED,
                               content::NotificationService::AllSources());
+  notification_registrar_.Add(this,
+                              chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
+                              content::NotificationService::AllSources());
 }
 
 AccessibilityManager::~AccessibilityManager() {
@@ -333,74 +396,77 @@
       enabled ? IDS_CHROMEOS_ACC_SPOKEN_FEEDBACK_ENABLED :
       IDS_CHROMEOS_ACC_SPOKEN_FEEDBACK_DISABLED).c_str());
 
-  // Determine whether an OOBE screen or the screen locker is currently being
-  // shown. If so, ChromeVox will be injected directly into that screen.
+  if (enabled)
+    LoadChromeVox();
+  else
+    UnloadChromeVox();
+}
+
+void AccessibilityManager::LoadChromeVox() {
+  ScreenLocker* screen_locker = ScreenLocker::default_screen_locker();
+  if (screen_locker && screen_locker->locked()) {
+    // If on the lock screen, loads ChromeVox only to the lock screen as for
+    // now. On unlock, it will be loaded to the user screen.
+    // (see. AccessibilityManager::Observe())
+    LoadChromeVoxToLockScreen();
+    return;
+  }
+
+  LoadChromeVoxToUserScreen();
+}
+
+void AccessibilityManager::LoadChromeVoxToUserScreen() {
+  if (chrome_vox_loaded_on_user_screen_)
+    return;
+
+  // Determine whether an OOBE screen is currently being shown. If so,
+  // ChromeVox will be injected directly into that screen.
   content::WebUI* login_web_ui = NULL;
-  LoginDisplayHost* login_display_host = LoginDisplayHostImpl::default_host();
-  if (login_display_host) {
-    WebUILoginView* web_ui_login_view = login_display_host->GetWebUILoginView();
-    if (web_ui_login_view)
-      login_web_ui = web_ui_login_view->GetWebUI();
-  }
-  if (!login_web_ui) {
-    ScreenLocker* screen_locker = ScreenLocker::default_screen_locker();
-    if (screen_locker && screen_locker->locked())
-      login_web_ui = screen_locker->GetAssociatedWebUI();
-  }
 
-  // Load/Unload ChromeVox
-  Profile* profile = login_web_ui ? Profile::FromWebUI(login_web_ui) :
-                                    ProfileManager::GetDefaultProfile();
-  ExtensionService* extension_service =
-      extensions::ExtensionSystem::Get(profile)->extension_service();
-  base::FilePath path = base::FilePath(extension_misc::kChromeVoxExtensionPath);
-  if (enabled) {  // Load ChromeVox
-    std::string extension_id =
-        extension_service->component_loader()->Add(IDR_CHROMEVOX_MANIFEST,
-                                                   path);
-    const extensions::Extension* extension =
-        extension_service->extensions()->GetByID(extension_id);
-
-    if (login_web_ui) {
-      RenderViewHost* render_view_host =
-          login_web_ui->GetWebContents()->GetRenderViewHost();
-      // Set a flag to tell ChromeVox that it's just been enabled,
-      // so that it won't interrupt our speech feedback enabled message.
-      ExtensionMsg_ExecuteCode_Params params;
-      params.request_id = 0;
-      params.extension_id = extension->id();
-      params.is_javascript = true;
-      params.code = "window.INJECTED_AFTER_LOAD = true;";
-      params.run_at = extensions::UserScript::DOCUMENT_IDLE;
-      params.all_frames = true;
-      params.in_main_world = false;
-      render_view_host->Send(new ExtensionMsg_ExecuteCode(
-          render_view_host->GetRoutingID(), params));
-
-      // Inject ChromeVox' content scripts.
-      ContentScriptLoader* loader = new ContentScriptLoader(
-          extension->id(), render_view_host->GetProcess()->GetID(),
-          render_view_host->GetRoutingID());
-
-      const extensions::UserScriptList& content_scripts =
-          extensions::ContentScriptsInfo::GetContentScripts(extension);
-      for (size_t i = 0; i < content_scripts.size(); i++) {
-        const extensions::UserScript& script = content_scripts[i];
-        for (size_t j = 0; j < script.js_scripts().size(); ++j) {
-          const extensions::UserScript::File &file = script.js_scripts()[j];
-          extensions::ExtensionResource resource = extension->GetResource(
-              file.relative_path());
-          loader->AppendScript(resource);
-        }
-      }
-      loader->Run();  // It cleans itself up when done.
+  if (ProfileHelper::IsSigninProfile(profile_)) {
+    LoginDisplayHost* login_display_host = LoginDisplayHostImpl::default_host();
+    if (login_display_host) {
+      WebUILoginView* web_ui_login_view =
+          login_display_host->GetWebUILoginView();
+      if (web_ui_login_view)
+        login_web_ui = web_ui_login_view->GetWebUI();
     }
-
-    DLOG(INFO) << "ChromeVox was Loaded.";
-  } else {  // Unload ChromeVox
-    extension_service->component_loader()->Remove(path);
-    DLOG(INFO) << "ChromeVox was Unloaded.";
   }
+
+  LoadChromeVoxExtension(profile_, login_web_ui);
+  chrome_vox_loaded_on_user_screen_ = true;
+}
+
+void AccessibilityManager::LoadChromeVoxToLockScreen() {
+  if (chrome_vox_loaded_on_lock_screen_)
+    return;
+
+  ScreenLocker* screen_locker = ScreenLocker::default_screen_locker();
+  if (screen_locker && screen_locker->locked()) {
+    content::WebUI* lock_web_ui = screen_locker->GetAssociatedWebUI();
+    if (lock_web_ui) {
+      Profile* profile = Profile::FromWebUI(lock_web_ui);
+      LoadChromeVoxExtension(profile, lock_web_ui);
+      chrome_vox_loaded_on_lock_screen_ = true;
+    }
+  }
+}
+
+void AccessibilityManager::UnloadChromeVox() {
+  if (chrome_vox_loaded_on_lock_screen_)
+    UnloadChromeVoxFromLockScreen();
+
+  if (chrome_vox_loaded_on_user_screen_) {
+    UnloadChromeVoxExtension(profile_);
+    chrome_vox_loaded_on_user_screen_ = false;
+  }
+}
+
+void AccessibilityManager::UnloadChromeVoxFromLockScreen() {
+  // Lock screen uses the signin progile.
+  Profile* signin_profile = ProfileHelper::GetSigninProfile();
+  UnloadChromeVoxExtension(signin_profile);
+  chrome_vox_loaded_on_lock_screen_ = false;
 }
 
 bool AccessibilityManager::IsSpokenFeedbackEnabled() {
@@ -564,7 +630,7 @@
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
   switch (type) {
-    case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
+    case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
       // Update |profile_| when entering the login screen.
       Profile* profile = ProfileManager::GetDefaultProfile();
       if (ProfileHelper::IsSigninProfile(profile))
@@ -582,6 +648,18 @@
         SetProfile(NULL);
       break;
     }
+    case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: {
+      bool is_screen_locked = *content::Details<bool>(details).ptr();
+      if (is_screen_locked) {
+        if (spoken_feedback_enabled_)
+          LoadChromeVoxToLockScreen();
+      } else {
+        UnloadChromeVoxFromLockScreen();
+
+        if (spoken_feedback_enabled_)
+          LoadChromeVoxToUserScreen();
+      }
+    }
   }
 }
 
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index cedfab6..c582130 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -101,6 +101,12 @@
   virtual ~AccessibilityManager();
 
  private:
+  void LoadChromeVox();
+  void LoadChromeVoxToUserScreen();
+  void LoadChromeVoxToLockScreen();
+  void UnloadChromeVox();
+  void UnloadChromeVoxFromLockScreen();
+
   void UpdateLargeCursorFromPref();
   void UpdateStickyKeysFromPref();
   void UpdateSpokenFeedbackFromPref();
@@ -116,7 +122,14 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+  // Profile which has the current a11y context.
   Profile* profile_;
+
+  // Profile which ChromeVox is currently loaded to. If NULL, ChromeVox is not
+  // loaded to any profile.
+  bool chrome_vox_loaded_on_lock_screen_;
+  bool chrome_vox_loaded_on_user_screen_;
+
   content::NotificationRegistrar notification_registrar_;
   scoped_ptr<PrefChangeRegistrar> pref_change_registrar_;
   scoped_ptr<PrefChangeRegistrar> local_state_pref_change_registrar_;
diff --git a/chrome/browser/chromeos/accessibility/magnification_manager.cc b/chrome/browser/chromeos/accessibility/magnification_manager.cc
index b4b3bcb..3051908 100644
--- a/chrome/browser/chromeos/accessibility/magnification_manager.cc
+++ b/chrome/browser/chromeos/accessibility/magnification_manager.cc
@@ -46,7 +46,7 @@
         type_(ash::kDefaultMagnifierType),
         enabled_(false) {
     registrar_.Add(this,
-                   chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+                   chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                    content::NotificationService::AllSources());
     registrar_.Add(this,
                    chrome::NOTIFICATION_SESSION_STARTED,
@@ -199,7 +199,7 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE {
     switch (type) {
-      case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
+      case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
         // Update |profile_| when entering the login screen.
         Profile* profile = ProfileManager::GetDefaultProfile();
         if (ProfileHelper::IsSigninProfile(profile))
diff --git a/chrome/browser/chromeos/drive/async_file_util.cc b/chrome/browser/chromeos/drive/async_file_util.cc
index e385033..a2b0e88 100644
--- a/chrome/browser/chromeos/drive/async_file_util.cc
+++ b/chrome/browser/chromeos/drive/async_file_util.cc
@@ -50,7 +50,8 @@
     const base::FilePath& file_path,
     const AsyncFileUtil::CreateOrOpenCallback& callback,
     base::PlatformFileError error,
-    base::PlatformFile file) {
+    base::PlatformFile file,
+    const base::Closure& close_callback_on_ui_thread) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   // It is necessary to make a closure, which runs on file closing here.
@@ -58,10 +59,9 @@
   // (crbug.com/259184).
   callback.Run(
       error, base::PassPlatformFile(&file),
-      base::Bind(&PostFileSystemCallback,
-                 file_system_getter,
-                 base::Bind(&fileapi_internal::CloseFile, file_path),
-                 base::Closure()));
+      base::Bind(&google_apis::RunTaskOnThread,
+                 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+                 close_callback_on_ui_thread));
 }
 
 // Runs CreateOrOpenFile when the error happens.
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 6ae980a..1af4edc 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -252,6 +252,9 @@
 }
 
 void DriveIntegrationService::OnPushNotificationEnabled(bool enabled) {
+  if (enabled)
+    drive_app_registry_->Update();
+
   const char* status = (enabled ? "enabled" : "disabled");
   util::Log("Push notification is %s", status);
 }
@@ -368,9 +371,11 @@
         drive_notification_manager->push_notification_registered();
     const char* status = (registered ? "registered" : "not registered");
     util::Log("Push notification is %s", status);
+
+    if (drive_notification_manager->push_notification_enabled())
+      drive_app_registry_->Update();
   }
 
-  drive_app_registry_->Update();
   AddDriveMountPoint();
 }
 
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.h b/chrome/browser/chromeos/drive/dummy_file_system.h
index e9b95b5..92e546f 100644
--- a/chrome/browser/chromeos/drive/dummy_file_system.h
+++ b/chrome/browser/chromeos/drive/dummy_file_system.h
@@ -28,8 +28,6 @@
   virtual void OpenFile(const base::FilePath& file_path,
                         OpenMode open_mode,
                         const OpenFileCallback& callback) OVERRIDE {}
-  virtual void CloseFile(const base::FilePath& file_path,
-                         const FileOperationCallback& callback) OVERRIDE {}
   virtual void Copy(const base::FilePath& src_file_path,
                     const base::FilePath& dest_file_path,
                     const FileOperationCallback& callback) OVERRIDE {}
@@ -85,7 +83,7 @@
       const GetFilesystemMetadataCallback& callback) OVERRIDE {}
   virtual void MarkCacheFileAsMounted(
       const base::FilePath& drive_file_path,
-      const OpenFileCallback& callback) OVERRIDE {}
+      const MarkMountedCallback& callback) OVERRIDE {}
   virtual void MarkCacheFileAsUnmounted(
       const base::FilePath& cache_file_path,
       const FileOperationCallback& callback) OVERRIDE {}
diff --git a/chrome/browser/chromeos/drive/fake_file_system.cc b/chrome/browser/chromeos/drive/fake_file_system.cc
index 7f49b9c..234aadb 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system.cc
@@ -74,11 +74,6 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
-void FakeFileSystem::CloseFile(const base::FilePath& file_path,
-                               const FileOperationCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
 void FakeFileSystem::Copy(const base::FilePath& src_file_path,
                           const base::FilePath& dest_file_path,
                           const FileOperationCallback& callback) {
@@ -210,7 +205,7 @@
 
 void FakeFileSystem::MarkCacheFileAsMounted(
     const base::FilePath& drive_file_path,
-    const OpenFileCallback& callback) {
+    const MarkMountedCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
diff --git a/chrome/browser/chromeos/drive/fake_file_system.h b/chrome/browser/chromeos/drive/fake_file_system.h
index 501cf14..c1320ad 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.h
+++ b/chrome/browser/chromeos/drive/fake_file_system.h
@@ -62,8 +62,6 @@
   virtual void OpenFile(const base::FilePath& file_path,
                         OpenMode open_mode,
                         const OpenFileCallback& callback) OVERRIDE;
-  virtual void CloseFile(const base::FilePath& file_path,
-                         const FileOperationCallback& callback) OVERRIDE;
   virtual void Copy(const base::FilePath& src_file_path,
                     const base::FilePath& dest_file_path,
                     const FileOperationCallback& callback) OVERRIDE;
@@ -117,7 +115,7 @@
       const GetFilesystemMetadataCallback& callback) OVERRIDE;
   virtual void MarkCacheFileAsMounted(
       const base::FilePath& drive_file_path,
-      const OpenFileCallback& callback) OVERRIDE;
+      const MarkMountedCallback& callback) OVERRIDE;
   virtual void MarkCacheFileAsUnmounted(
       const base::FilePath& cache_file_path,
       const FileOperationCallback& callback) OVERRIDE;
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index 4909ccd..b3b22b5 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/chromeos/drive/change_list_processor.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/file_cache.h"
-#include "chrome/browser/chromeos/drive/file_system/close_file_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/copy_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
@@ -105,11 +104,6 @@
   SetupChangeListLoader();
 
   file_system::OperationObserver* observer = this;
-  close_file_operation_.reset(
-      new file_system::CloseFileOperation(blocking_task_runner_.get(),
-                                          observer,
-                                          resource_metadata_,
-                                          &open_files_));
   copy_operation_.reset(
       new file_system::CopyOperation(blocking_task_runner_.get(),
                                      observer,
@@ -134,8 +128,7 @@
                                          scheduler_,
                                          resource_metadata_,
                                          cache_,
-                                         temporary_file_directory_,
-                                         &open_files_));
+                                         temporary_file_directory_));
   remove_operation_.reset(
       new file_system::RemoveOperation(blocking_task_runner_.get(),
                                        observer,
@@ -755,7 +748,7 @@
 
 void FileSystem::MarkCacheFileAsMounted(
     const base::FilePath& drive_file_path,
-    const OpenFileCallback& callback) {
+    const MarkMountedCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
@@ -766,7 +759,7 @@
 }
 
 void FileSystem::MarkCacheFileAsMountedAfterGetResourceEntry(
-    const OpenFileCallback& callback,
+    const MarkMountedCallback& callback,
     FileError error,
     scoped_ptr<ResourceEntry> entry) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -846,14 +839,6 @@
   open_file_operation_->OpenFile(file_path, open_mode, callback);
 }
 
-void FileSystem::CloseFile(const base::FilePath& file_path,
-                           const FileOperationCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!callback.is_null());
-
-  close_file_operation_->CloseFile(file_path, callback);
-}
-
 void FileSystem::CheckLocalModificationAndRun(
     scoped_ptr<ResourceEntry> entry,
     const GetResourceEntryCallback& callback) {
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h
index 2b469cc..351f637 100644
--- a/chrome/browser/chromeos/drive/file_system.h
+++ b/chrome/browser/chromeos/drive/file_system.h
@@ -43,7 +43,6 @@
 }  // namespace internal
 
 namespace file_system {
-class CloseFileOperation;
 class CopyOperation;
 class CreateDirectoryOperation;
 class CreateFileOperation;
@@ -95,8 +94,6 @@
   virtual void OpenFile(const base::FilePath& file_path,
                         OpenMode open_mode,
                         const OpenFileCallback& callback) OVERRIDE;
-  virtual void CloseFile(const base::FilePath& file_path,
-                         const FileOperationCallback& callback) OVERRIDE;
   virtual void Copy(const base::FilePath& src_file_path,
                     const base::FilePath& dest_file_path,
                     const FileOperationCallback& callback) OVERRIDE;
@@ -143,7 +140,7 @@
       const GetFilesystemMetadataCallback& callback) OVERRIDE;
   virtual void MarkCacheFileAsMounted(
       const base::FilePath& drive_file_path,
-      const OpenFileCallback& callback) OVERRIDE;
+      const MarkMountedCallback& callback) OVERRIDE;
   virtual void MarkCacheFileAsUnmounted(
       const base::FilePath& cache_file_path,
       const FileOperationCallback& callback) OVERRIDE;
@@ -291,7 +288,7 @@
   // Part of MarkCacheFileAsMounted. Called after GetResourceEntryByPath is
   // completed. |callback| must not be null.
   void MarkCacheFileAsMountedAfterGetResourceEntry(
-      const OpenFileCallback& callback,
+      const MarkMountedCallback& callback,
       FileError error,
       scoped_ptr<ResourceEntry> entry);
 
@@ -313,10 +310,6 @@
   // True if hosted documents should be hidden.
   bool hide_hosted_docs_;
 
-  // Map from opened file paths to the number how many the file is opened.
-  // The value should be incremented by OpenFile, and decremented by CloseFile.
-  std::map<base::FilePath, int> open_files_;
-
   scoped_ptr<PrefChangeRegistrar> pref_registrar_;
 
   scoped_ptr<internal::SyncClient> sync_client_;
@@ -331,7 +324,6 @@
   base::FilePath temporary_file_directory_;
 
   // Implementation of each file system operation.
-  scoped_ptr<file_system::CloseFileOperation> close_file_operation_;
   scoped_ptr<file_system::CopyOperation> copy_operation_;
   scoped_ptr<file_system::CreateDirectoryOperation> create_directory_operation_;
   scoped_ptr<file_system::CreateFileOperation> create_file_operation_;
diff --git a/chrome/browser/chromeos/drive/file_system/close_file_operation.cc b/chrome/browser/chromeos/drive/file_system/close_file_operation.cc
deleted file mode 100644
index dfd2a55..0000000
--- a/chrome/browser/chromeos/drive/file_system/close_file_operation.cc
+++ /dev/null
@@ -1,83 +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/drive/file_system/close_file_operation.h"
-
-#include "base/logging.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/sequenced_task_runner.h"
-#include "chrome/browser/chromeos/drive/drive.pb.h"
-#include "chrome/browser/chromeos/drive/file_errors.h"
-#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
-#include "chrome/browser/chromeos/drive/resource_metadata.h"
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
-
-namespace drive {
-namespace file_system {
-
-CloseFileOperation::CloseFileOperation(
-    base::SequencedTaskRunner* blocking_task_runner,
-    OperationObserver* observer,
-    internal::ResourceMetadata* metadata,
-    std::map<base::FilePath, int>* open_files)
-    : blocking_task_runner_(blocking_task_runner),
-      observer_(observer),
-      metadata_(metadata),
-      open_files_(open_files),
-      weak_ptr_factory_(this) {
-}
-
-CloseFileOperation::~CloseFileOperation() {
-}
-
-void CloseFileOperation::CloseFile(const base::FilePath& file_path,
-                                   const FileOperationCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!callback.is_null());
-
-  if (open_files_->find(file_path) == open_files_->end()) {
-    // The file is not being opened.
-    base::MessageLoopProxy::current()->PostTask(
-        FROM_HERE, base::Bind(callback, FILE_ERROR_NOT_FOUND));
-    return;
-  }
-
-  ResourceEntry* entry = new ResourceEntry;
-  base::PostTaskAndReplyWithResult(
-      blocking_task_runner_.get(),
-      FROM_HERE,
-      base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath,
-                 base::Unretained(metadata_), file_path, entry),
-      base::Bind(&CloseFileOperation::CloseFileAfterGetResourceEntry,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 file_path, callback, base::Owned(entry)));
-}
-
-void CloseFileOperation::CloseFileAfterGetResourceEntry(
-    const base::FilePath& file_path,
-    const FileOperationCallback& callback,
-    const ResourceEntry* entry,
-    FileError error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!callback.is_null());
-  DCHECK(entry);
-
-  if (error == FILE_ERROR_OK && entry->file_info().is_directory())
-    error = FILE_ERROR_NOT_FOUND;
-
-  DCHECK_GT((*open_files_)[file_path], 0);
-  if (--(*open_files_)[file_path] == 0) {
-    // All clients closes this file, so notify to upload the file.
-    open_files_->erase(file_path);
-    observer_->OnCacheFileUploadNeededByOperation(entry->resource_id());
-  }
-
-  // Then invokes the user-supplied callback function.
-  callback.Run(error);
-}
-
-}  // namespace file_system
-}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/close_file_operation.h b/chrome/browser/chromeos/drive/file_system/close_file_operation.h
deleted file mode 100644
index 005c9cf..0000000
--- a/chrome/browser/chromeos/drive/file_system/close_file_operation.h
+++ /dev/null
@@ -1,70 +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_DRIVE_FILE_SYSTEM_CLOSE_FILE_OPERATION_H_
-#define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_CLOSE_FILE_OPERATION_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/drive/file_errors.h"
-
-namespace base {
-class FilePath;
-class SequencedTaskRunner;
-}  // namespace base
-
-namespace drive {
-
-class ResourceEntry;
-
-namespace internal {
-class ResourceMetadata;
-}  // namespace internal
-
-namespace file_system {
-
-class OperationObserver;
-
-class CloseFileOperation {
- public:
-  CloseFileOperation(base::SequencedTaskRunner* blocking_task_runner,
-                     OperationObserver* observer,
-                     internal::ResourceMetadata* metadata,
-                     std::map<base::FilePath, int>* open_files);
-  ~CloseFileOperation();
-
-  // Closes the currently opened file |file_path|.
-  // |callback| must not be null.
-  void CloseFile(const base::FilePath& file_path,
-                 const FileOperationCallback& callback);
-
- private:
-  // Part of CloseFile(). Called after ResourceMetadata::GetResourceEntry().
-  void CloseFileAfterGetResourceEntry(const base::FilePath& file_path,
-                                      const FileOperationCallback& callback,
-                                      const ResourceEntry* entry,
-                                      FileError error);
-
-  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
-  OperationObserver* observer_;
-  internal::ResourceMetadata* metadata_;
-
-  // The map from paths for opened file to the number how many the file is
-  // opened. The instance is owned by FileSystem and shared with
-  // OpenFileOperation.
-  std::map<base::FilePath, int>* open_files_;
-
-  // 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<CloseFileOperation> weak_ptr_factory_;
-  DISALLOW_COPY_AND_ASSIGN(CloseFileOperation);
-};
-
-}  // namespace file_system
-}  // namespace drive
-
-#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_CLOSE_FILE_OPERATION_H_
diff --git a/chrome/browser/chromeos/drive/file_system/close_file_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/close_file_operation_unittest.cc
deleted file mode 100644
index 2fe4d88..0000000
--- a/chrome/browser/chromeos/drive/file_system/close_file_operation_unittest.cc
+++ /dev/null
@@ -1,105 +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/drive/file_system/close_file_operation.h"
-
-#include <set>
-
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/chromeos/drive/drive.pb.h"
-#include "chrome/browser/chromeos/drive/file_errors.h"
-#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
-#include "chrome/browser/google_apis/test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace drive {
-namespace file_system {
-
-class CloseFileOperationTest : public OperationTestBase {
- protected:
-  virtual void SetUp() {
-    OperationTestBase::SetUp();
-
-    operation_.reset(new CloseFileOperation(
-        blocking_task_runner(), observer(), metadata(), &open_files_));
-  }
-
-  std::map<base::FilePath, int> open_files_;
-  scoped_ptr<CloseFileOperation> operation_;
-};
-
-TEST_F(CloseFileOperationTest, CloseFile) {
-  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
-  ResourceEntry src_entry;
-  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
-
-  open_files_[file_in_root] = 1;
-  FileError error = FILE_ERROR_FAILED;
-  operation_->CloseFile(
-      file_in_root,
-      google_apis::test_util::CreateCopyResultCallback(&error));
-  test_util::RunBlockingPoolTask();
-
-  EXPECT_EQ(FILE_ERROR_OK, error);
-  EXPECT_TRUE(open_files_.empty());
-  EXPECT_EQ(
-      1U,
-      observer()->upload_needed_resource_ids().count(src_entry.resource_id()));
-}
-
-TEST_F(CloseFileOperationTest, NotOpenedFile) {
-  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
-  ResourceEntry src_entry;
-  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
-
-  FileError error = FILE_ERROR_FAILED;
-  operation_->CloseFile(
-      file_in_root,
-      google_apis::test_util::CreateCopyResultCallback(&error));
-  test_util::RunBlockingPoolTask();
-
-  // Even if the file is actually exists, NOT_FOUND should be returned if the
-  // file is not opened.
-  EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
-}
-
-TEST_F(CloseFileOperationTest, CloseFileTwice) {
-  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
-  ResourceEntry src_entry;
-  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
-
-  // Set the number of opening clients is two.
-  open_files_[file_in_root] = 2;
-
-  // The first CloseFile.
-  FileError error = FILE_ERROR_FAILED;
-  operation_->CloseFile(
-      file_in_root,
-      google_apis::test_util::CreateCopyResultCallback(&error));
-  test_util::RunBlockingPoolTask();
-
-  EXPECT_EQ(FILE_ERROR_OK, error);
-  EXPECT_EQ(1, open_files_[file_in_root]);
-
-  // There still remains a client opening the file, so it shouldn't be
-  // uploaded yet.
-  EXPECT_TRUE(observer()->upload_needed_resource_ids().empty());
-
-  // The second CloseFile.
-  operation_->CloseFile(
-      file_in_root,
-      google_apis::test_util::CreateCopyResultCallback(&error));
-  test_util::RunBlockingPoolTask();
-
-  EXPECT_EQ(FILE_ERROR_OK, error);
-  EXPECT_TRUE(open_files_.empty());
-  // Here, all the clients close the file, so it should be uploaded then.
-  EXPECT_EQ(
-      1U,
-      observer()->upload_needed_resource_ids().count(src_entry.resource_id()));
-}
-
-}  // namespace file_system
-}  // namespace drive
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 e5a1bfa..4a49830 100644
--- a/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
+#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
 #include "chrome/browser/chromeos/drive/file_system_interface.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -42,18 +43,16 @@
     JobScheduler* scheduler,
     internal::ResourceMetadata* metadata,
     internal::FileCache* cache,
-    const base::FilePath& temporary_file_directory,
-    std::map<base::FilePath, int>* open_files)
+    const base::FilePath& temporary_file_directory)
     : blocking_task_runner_(blocking_task_runner),
+      observer_(observer),
       cache_(cache),
       create_file_operation_(new CreateFileOperation(
           blocking_task_runner, observer, scheduler, metadata, cache)),
       download_operation_(new DownloadOperation(
           blocking_task_runner, observer, scheduler,
           metadata, cache, temporary_file_directory)),
-      open_files_(open_files),
       weak_ptr_factory_(this) {
-  DCHECK(open_files);
 }
 
 OpenFileOperation::~OpenFileOperation() {
@@ -97,7 +96,7 @@
   DCHECK(!callback.is_null());
 
   if (error != FILE_ERROR_OK) {
-    callback.Run(error, base::FilePath());
+    callback.Run(error, base::FilePath(), base::Closure());
     return;
   }
 
@@ -108,11 +107,10 @@
       google_apis::GetContentCallback(),
       base::Bind(
           &OpenFileOperation::OpenFileAfterFileDownloaded,
-          weak_ptr_factory_.GetWeakPtr(), file_path, callback));
+          weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
 void OpenFileOperation::OpenFileAfterFileDownloaded(
-    const base::FilePath& file_path,
     const OpenFileCallback& callback,
     FileError error,
     const base::FilePath& local_file_path,
@@ -129,7 +127,7 @@
   }
 
   if (error != FILE_ERROR_OK) {
-    callback.Run(error, base::FilePath());
+    callback.Run(error, base::FilePath(), base::Closure());
     return;
   }
 
@@ -146,22 +144,39 @@
                  new_local_file_path),
       base::Bind(&OpenFileOperation::OpenFileAfterUpdateLocalState,
                  weak_ptr_factory_.GetWeakPtr(),
-                 file_path,
+                 entry->resource_id(),
                  callback,
                  base::Owned(new_local_file_path)));
 }
 
 void OpenFileOperation::OpenFileAfterUpdateLocalState(
-    const base::FilePath& file_path,
+    const std::string& resource_id,
     const OpenFileCallback& callback,
     const base::FilePath* local_file_path,
     FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  if (error == FILE_ERROR_OK)
-    ++(*open_files_)[file_path];
-  callback.Run(error, *local_file_path);
+  if (error != FILE_ERROR_OK) {
+    callback.Run(error, base::FilePath(), base::Closure());
+    return;
+  }
+
+  ++open_files_[resource_id];
+  callback.Run(error, *local_file_path,
+               base::Bind(&OpenFileOperation::CloseFile,
+                          weak_ptr_factory_.GetWeakPtr(), resource_id));
+}
+
+void OpenFileOperation::CloseFile(const std::string& resource_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_GT(open_files_[resource_id], 0);
+
+  if (--open_files_[resource_id] == 0) {
+    // All clients closes this file, so notify to upload the file.
+    open_files_.erase(resource_id);
+    observer_->OnCacheFileUploadNeededByOperation(resource_id);
+  }
 }
 
 }  // namespace file_system
diff --git a/chrome/browser/chromeos/drive/file_system/open_file_operation.h b/chrome/browser/chromeos/drive/file_system/open_file_operation.h
index 8aea8ad..f656d2f 100644
--- a/chrome/browser/chromeos/drive/file_system/open_file_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/open_file_operation.h
@@ -42,8 +42,7 @@
                     JobScheduler* scheduler,
                     internal::ResourceMetadata* metadata,
                     internal::FileCache* cache,
-                    const base::FilePath& temporary_file_directory,
-                    std::map<base::FilePath, int>* open_files);
+                    const base::FilePath& temporary_file_directory);
   ~OpenFileOperation();
 
   // Opens the file at |file_path|.
@@ -63,28 +62,30 @@
                                FileError error);
 
   // Part of OpenFile(). Called after file downloading is completed.
-  void OpenFileAfterFileDownloaded(const base::FilePath& file_path,
-                                   const OpenFileCallback& callback,
+  void OpenFileAfterFileDownloaded(const OpenFileCallback& callback,
                                    FileError error,
                                    const base::FilePath& local_file_path,
                                    scoped_ptr<ResourceEntry> entry);
 
   // Part of OpenFile(). Called after the updating of the local state.
-  void OpenFileAfterUpdateLocalState(const base::FilePath& file_path,
+  void OpenFileAfterUpdateLocalState(const std::string& resource_id,
                                      const OpenFileCallback& callback,
                                      const base::FilePath* local_file_path,
                                      FileError error);
 
+  // Closes the file with |resource_id|.
+  void CloseFile(const std::string& resource_id);
+
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+  OperationObserver* observer_;
   internal::FileCache* cache_;
 
   scoped_ptr<CreateFileOperation> create_file_operation_;
   scoped_ptr<DownloadOperation> download_operation_;
 
-  // The map from paths for opened file to the number how many the file is
-  // opened. The instance is owned by FileSystem and shared with
-  // CloseFileOperation.
-  std::map<base::FilePath, int>* open_files_;
+  // The map from resource id for an opened file to the number how many times
+  // the file is opened.
+  std::map<std::string, int> open_files_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
diff --git a/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc
index 4e22efe..3628166 100644
--- a/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc
@@ -25,10 +25,9 @@
 
     operation_.reset(new OpenFileOperation(
         blocking_task_runner(), observer(), scheduler(), metadata(), cache(),
-        temp_dir(), &open_files_));
+        temp_dir()));
   }
 
-  std::map<base::FilePath, int> open_files_;
   scoped_ptr<OpenFileOperation> operation_;
 };
 
@@ -41,10 +40,12 @@
 
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   operation_->OpenFile(
       file_in_root,
       OPEN_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
 
   EXPECT_EQ(FILE_ERROR_OK, error);
@@ -53,8 +54,11 @@
   ASSERT_TRUE(file_util::GetFileSize(file_path, &local_file_size));
   EXPECT_EQ(file_size, local_file_size);
 
-  // The file_path should be added into the set.
-  EXPECT_EQ(1, open_files_[file_in_root]);
+  ASSERT_FALSE(close_callback.is_null());
+  close_callback.Run();
+  EXPECT_EQ(
+      1U,
+      observer()->upload_needed_resource_ids().count(src_entry.resource_id()));
 }
 
 TEST_F(OpenFileOperationTest, OpenNonExistingFile) {
@@ -63,15 +67,15 @@
 
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   operation_->OpenFile(
       file_in_root,
       OPEN_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
-
-  // The file shouldn't be in the set of opened files.
-  EXPECT_EQ(0U, open_files_.count(file_in_root));
+  EXPECT_TRUE(close_callback.is_null());
 }
 
 TEST_F(OpenFileOperationTest, CreateExistingFile) {
@@ -82,16 +86,16 @@
 
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   operation_->OpenFile(
       file_in_root,
       CREATE_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
 
   EXPECT_EQ(FILE_ERROR_EXISTS, error);
-
-  // The file shouldn't be in the set of opened files.
-  EXPECT_EQ(0U, open_files_.count(file_in_root));
+  EXPECT_TRUE(close_callback.is_null());
 }
 
 TEST_F(OpenFileOperationTest, CreateNonExistingFile) {
@@ -100,10 +104,12 @@
 
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   operation_->OpenFile(
       file_in_root,
       CREATE_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
 
   EXPECT_EQ(FILE_ERROR_OK, error);
@@ -112,8 +118,11 @@
   ASSERT_TRUE(file_util::GetFileSize(file_path, &local_file_size));
   EXPECT_EQ(0, local_file_size);  // Should be an empty file.
 
-  // The file_path should be added into the set.
-  EXPECT_EQ(1, open_files_[file_in_root]);
+  ASSERT_FALSE(close_callback.is_null());
+  close_callback.Run();
+  // Here we don't know about the resource id, so just make sure
+  // OnCacheFileUploadNeededByOperation is called actually.
+  EXPECT_EQ(1U, observer()->upload_needed_resource_ids().size());
 }
 
 TEST_F(OpenFileOperationTest, OpenOrCreateExistingFile) {
@@ -125,10 +134,12 @@
 
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   operation_->OpenFile(
       file_in_root,
       OPEN_OR_CREATE_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
 
   EXPECT_EQ(FILE_ERROR_OK, error);
@@ -137,8 +148,11 @@
   ASSERT_TRUE(file_util::GetFileSize(file_path, &local_file_size));
   EXPECT_EQ(file_size, local_file_size);
 
-  // The file_path should be added into the set.
-  EXPECT_EQ(1, open_files_[file_in_root]);
+  ASSERT_FALSE(close_callback.is_null());
+  close_callback.Run();
+  EXPECT_EQ(
+      1U,
+      observer()->upload_needed_resource_ids().count(src_entry.resource_id()));
 }
 
 TEST_F(OpenFileOperationTest, OpenOrCreateNonExistingFile) {
@@ -147,10 +161,12 @@
 
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   operation_->OpenFile(
       file_in_root,
       OPEN_OR_CREATE_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
 
   EXPECT_EQ(FILE_ERROR_OK, error);
@@ -159,8 +175,11 @@
   ASSERT_TRUE(file_util::GetFileSize(file_path, &local_file_size));
   EXPECT_EQ(0, local_file_size);  // Should be an empty file.
 
-  // The file_path should be added into the set.
-  EXPECT_EQ(1, open_files_[file_in_root]);
+  ASSERT_FALSE(close_callback.is_null());
+  close_callback.Run();
+  // Here we don't know about the resource id, so just make sure
+  // OnCacheFileUploadNeededByOperation is called actually.
+  EXPECT_EQ(1U, observer()->upload_needed_resource_ids().size());
 }
 
 TEST_F(OpenFileOperationTest, OpenFileTwice) {
@@ -172,10 +191,12 @@
 
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   operation_->OpenFile(
       file_in_root,
       OPEN_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
 
   EXPECT_EQ(FILE_ERROR_OK, error);
@@ -184,15 +205,14 @@
   ASSERT_TRUE(file_util::GetFileSize(file_path, &local_file_size));
   EXPECT_EQ(file_size, local_file_size);
 
-  // The file_path should be added into the set.
-  EXPECT_EQ(1, open_files_[file_in_root]);
-
   // Open again.
   error = FILE_ERROR_FAILED;
+  base::Closure close_callback2;
   operation_->OpenFile(
       file_in_root,
       OPEN_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback2));
   test_util::RunBlockingPoolTask();
 
   EXPECT_EQ(FILE_ERROR_OK, error);
@@ -200,8 +220,21 @@
   ASSERT_TRUE(file_util::GetFileSize(file_path, &local_file_size));
   EXPECT_EQ(file_size, local_file_size);
 
-  // The file_path should be added into the set.
-  EXPECT_EQ(2, open_files_[file_in_root]);
+  ASSERT_FALSE(close_callback.is_null());
+  ASSERT_FALSE(close_callback2.is_null());
+
+  close_callback.Run();
+
+  // There still remains a client opening the file, so it shouldn't be
+  // uploaded yet.
+  EXPECT_TRUE(observer()->upload_needed_resource_ids().empty());
+
+  close_callback2.Run();
+
+  // Here, all the clients close the file, so it should be uploaded then.
+  EXPECT_EQ(
+      1U,
+      observer()->upload_needed_resource_ids().count(src_entry.resource_id()));
 }
 
 }  // namespace file_system
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h
index 0c2b40b..98ccf11 100644
--- a/chrome/browser/chromeos/drive/file_system_interface.h
+++ b/chrome/browser/chromeos/drive/file_system_interface.h
@@ -98,8 +98,14 @@
 
 // Used to open files from the file system. |file_path| is the path on the local
 // file system for the opened file.
+// If |close_callback| is not null, it must be called when the
+// modification to the cache is done. Otherwise, Drive file system does not
+// pick up the file for uploading.
+// |close_callback| must not be called more than once.
 typedef base::Callback<void(FileError error,
-                            const base::FilePath& file_path)> OpenFileCallback;
+                            const base::FilePath& file_path,
+                            const base::Closure& close_callback)>
+    OpenFileCallback;
 
 // Used to get available space for the account from Drive.
 typedef base::Callback<void(FileError error,
@@ -110,6 +116,11 @@
 typedef base::Callback<void(const FileSystemMetadata&)>
     GetFilesystemMetadataCallback;
 
+// Used to mark cached files mounted.
+typedef base::Callback<void(FileError error,
+                            const base::FilePath& file_path)>
+    MarkMountedCallback;
+
 // The mode of opening a file.
 enum OpenMode {
   // Open the file if exists. If not, failed.
@@ -193,21 +204,11 @@
   // returned to |callback|. After opening the file, both read and write
   // on the file can be done with normal local file operations.
   //
-  // |CloseFile| must be called when the modification to the cache is done.
-  // Otherwise, Drive file system does not pick up the file for uploading.
-  //
   // |callback| must not be null.
   virtual void OpenFile(const base::FilePath& file_path,
                         OpenMode open_mode,
                         const OpenFileCallback& callback) = 0;
 
-  // Closes a file at the virtual path |file_path| on the Drive file system,
-  // which is opened via OpenFile(). It commits the dirty flag on the cache.
-  //
-  // |callback| must not be null.
-  virtual void CloseFile(const base::FilePath& file_path,
-                         const FileOperationCallback& callback) = 0;
-
   // Copies |src_file_path| to |dest_file_path| on the file system.
   // |src_file_path| can be a hosted document (see limitations below).
   // |dest_file_path| is expected to be of the same type of |src_file_path|
@@ -390,7 +391,7 @@
   // If succeeded, the cached file path will be passed to the |callback|.
   // |callback| must not be null.
   virtual void MarkCacheFileAsMounted(const base::FilePath& drive_file_path,
-                                    const OpenFileCallback& callback) = 0;
+                                      const MarkMountedCallback& callback) = 0;
 
   // Marks the cached file as unmounted, and runs |callback| upon completion.
   // Note that this method expects that the |cached_file_path| is the path
diff --git a/chrome/browser/chromeos/drive/file_system_unittest.cc b/chrome/browser/chromeos/drive/file_system_unittest.cc
index 9a043c7..a5a7922 100644
--- a/chrome/browser/chromeos/drive/file_system_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system_unittest.cc
@@ -741,10 +741,12 @@
   // Open kFileInRoot ("drive/root/File 1.txt").
   FileError error = FILE_ERROR_FAILED;
   base::FilePath file_path;
+  base::Closure close_callback;
   file_system_->OpenFile(
       kFileInRoot,
       OPEN_FILE,
-      google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &file_path, &close_callback));
   test_util::RunBlockingPoolTask();
   const base::FilePath opened_file_path = file_path;
 
@@ -780,9 +782,8 @@
                                                         kNewContent));
 
   // Close kFileInRoot ("drive/root/File 1.txt").
-  file_system_->CloseFile(
-      kFileInRoot,
-      google_apis::test_util::CreateCopyResultCallback(&error));
+  ASSERT_FALSE(close_callback.is_null());
+  close_callback.Run();
   test_util::RunBlockingPoolTask();
 
   // Verify that the file was properly closed.
@@ -805,17 +806,6 @@
   ASSERT_EQ(2u, mock_directory_observer_->changed_directories().size());
   EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive/root")),
             mock_directory_observer_->changed_directories()[1]);
-
-  // Try to close the same file twice.
-  file_system_->CloseFile(
-      kFileInRoot,
-      google_apis::test_util::CreateCopyResultCallback(&error));
-  test_util::RunBlockingPoolTask();
-
-  // It must fail.
-  EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
-  // There should be no new directory change.
-  ASSERT_EQ(2u, mock_directory_observer_->changed_directories().size());
 }
 
 TEST_F(FileSystemTest, MarkCacheFileAsMountedAndUnmounted) {
diff --git a/chrome/browser/chromeos/drive/file_write_helper.cc b/chrome/browser/chromeos/drive/file_write_helper.cc
index c48262c..b5623ed 100644
--- a/chrome/browser/chromeos/drive/file_write_helper.cc
+++ b/chrome/browser/chromeos/drive/file_write_helper.cc
@@ -4,26 +4,16 @@
 
 #include "chrome/browser/chromeos/drive/file_write_helper.h"
 
+#include "base/bind.h"
+#include "base/callback.h"
 #include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/chromeos/drive/file_system_interface.h"
 #include "content/public/browser/browser_thread.h"
 
 using content::BrowserThread;
 
 namespace drive {
 
-namespace {
-
-// Emits debug log when FileSystem::CloseFile() is complete.
-void EmitDebugLogForCloseFile(const base::FilePath& file_path,
-                              FileError file_error) {
-  if (file_error != FILE_ERROR_OK) {
-    LOG(WARNING) << "CloseFile failed: " << file_path.AsUTF8Unsafe() << ": "
-                 << file_error;
-  }
-}
-
-}  // namespace
-
 FileWriteHelper::FileWriteHelper(FileSystemInterface* file_system)
     : file_system_(file_system),
       weak_ptr_factory_(this) {
@@ -52,7 +42,8 @@
     const base::FilePath& file_path,
     const OpenFileCallback& callback,
     FileError error,
-    const base::FilePath& local_cache_path) {
+    const base::FilePath& local_cache_path,
+    const base::Closure& close_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
@@ -66,16 +57,7 @@
   content::BrowserThread::GetBlockingPool()->PostTaskAndReply(
       FROM_HERE,
       base::Bind(callback, FILE_ERROR_OK, local_cache_path),
-      base::Bind(&FileWriteHelper::PrepareWritableFileAndRunAfterCallback,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 file_path));
-}
-
-void FileWriteHelper::PrepareWritableFileAndRunAfterCallback(
-    const base::FilePath& file_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  file_system_->CloseFile(file_path,
-                          base::Bind(&EmitDebugLogForCloseFile, file_path));
+      close_callback);
 }
 
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_write_helper.h b/chrome/browser/chromeos/drive/file_write_helper.h
index 6b60a69..8a440ef 100644
--- a/chrome/browser/chromeos/drive/file_write_helper.h
+++ b/chrome/browser/chromeos/drive/file_write_helper.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_CHROMEOS_DRIVE_FILE_WRITE_HELPER_H_
 #define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_WRITE_HELPER_H_
 
+#include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
-#include "chrome/browser/chromeos/drive/file_system_interface.h"
 
 namespace base {
 class FilePath;
@@ -15,10 +15,17 @@
 
 namespace drive {
 
+class FileSystemInterface;
+
 // This class provides higher level operations for writing to Drive files over
 // FileSystemInterface.
 class FileWriteHelper {
  public:
+  // Callback for PrepareWritableFileAndRun.
+  typedef base::Callback<void(FileError error,
+                              const base::FilePath& file_path)>
+      OpenFileCallback;
+
   explicit FileWriteHelper(FileSystemInterface* file_system);
   ~FileWriteHelper();
 
@@ -34,13 +41,13 @@
  private:
   // Part of PrepareWritableFilePathAndRun(). It tries CreateFile for the case
   // file does not exist yet, does OpenFile to download and mark the file as
-  // dirty, runs |callback|, and finally calls CloseFile.
+  // dirty, runs |callback|, and finally closes the file.
   void PrepareWritableFileAndRunAfterOpenFile(
       const base::FilePath& file_path,
       const OpenFileCallback& callback,
       FileError result,
-      const base::FilePath& local_cache_path);
-  void PrepareWritableFileAndRunAfterCallback(const base::FilePath& file_path);
+      const base::FilePath& local_cache_path,
+      const base::Closure& close_callback);
 
   FileSystemInterface* file_system_;  // Owned by DriveIntegrationService.
 
diff --git a/chrome/browser/chromeos/drive/file_write_helper_unittest.cc b/chrome/browser/chromeos/drive/file_write_helper_unittest.cc
index af7bf9d..4270349 100644
--- a/chrome/browser/chromeos/drive/file_write_helper_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_write_helper_unittest.cc
@@ -23,6 +23,11 @@
 
 class TestFileSystem : public DummyFileSystem {
  public:
+  TestFileSystem() : num_closed_(0) {
+  }
+
+  int num_closed() const { return num_closed_; }
+
   // Mimics OpenFile. It fails if the |file_path| points to a hosted document.
   virtual void OpenFile(const base::FilePath& file_path,
                         OpenMode open_mode,
@@ -31,17 +36,23 @@
 
     // Emulate a case of opening a hosted document.
     if (file_path == base::FilePath(kInvalidPath)) {
-      callback.Run(FILE_ERROR_INVALID_OPERATION, base::FilePath());
+      callback.Run(FILE_ERROR_INVALID_OPERATION, base::FilePath(),
+                   base::Closure());
       return;
     }
 
-    callback.Run(FILE_ERROR_OK, base::FilePath(kLocalPath));
+    callback.Run(FILE_ERROR_OK, base::FilePath(kLocalPath),
+                 base::Bind(&TestFileSystem::CloseFile,
+                            base::Unretained(this)));
   }
 
-  virtual void CloseFile(const base::FilePath& file_path,
-                         const FileOperationCallback& callback) OVERRIDE {
-    callback.Run(FILE_ERROR_OK);
+ private:
+
+  void CloseFile() {
+    ++num_closed_;
   }
+
+  int num_closed_;
 };
 
 }  // namespace
@@ -69,6 +80,9 @@
 
   EXPECT_EQ(FILE_ERROR_OK, error);
   EXPECT_EQ(kLocalPath, path.value());
+
+  // Make sure that the file is actually closed.
+  EXPECT_EQ(1, test_file_system_->num_closed());
 }
 
 TEST_F(FileWriteHelperTest, PrepareFileForWritingCreateFail) {
diff --git a/chrome/browser/chromeos/drive/fileapi_worker.cc b/chrome/browser/chromeos/drive/fileapi_worker.cc
index 9f59917..3b952e9 100644
--- a/chrome/browser/chromeos/drive/fileapi_worker.cc
+++ b/chrome/browser/chromeos/drive/fileapi_worker.cc
@@ -136,28 +136,32 @@
 void RunCreateWritableSnapshotFileCallback(
     const CreateWritableSnapshotFileCallback& callback,
     FileError error,
-    const base::FilePath& local_path) {
+    const base::FilePath& local_path,
+    const base::Closure& close_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  callback.Run(FileErrorToPlatformError(error), local_path);
+  callback.Run(FileErrorToPlatformError(error), local_path, close_callback);
 }
 
 // Runs |callback| with |error| and |platform_file|.
 void RunOpenFileCallback(const OpenFileCallback& callback,
+                         const base::Closure& close_callback,
                          base::PlatformFileError* error,
                          base::PlatformFile platform_file) {
-  callback.Run(*error, platform_file);
+  callback.Run(*error, platform_file, close_callback);
 }
 
 // Part of OpenFile(). Called after FileSystem::OpenFile().
 void OpenFileAfterFileSystemOpenFile(int file_flags,
                                      const OpenFileCallback& callback,
                                      FileError error,
-                                     const base::FilePath& local_path) {
+                                     const base::FilePath& local_path,
+                                     const base::Closure& close_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   if (error != FILE_ERROR_OK) {
     callback.Run(FileErrorToPlatformError(error),
-                 base::kInvalidPlatformFileValue);
+                 base::kInvalidPlatformFileValue,
+                 base::Closure());
     return;
   }
 
@@ -183,16 +187,11 @@
       BrowserThread::GetBlockingPool(), FROM_HERE,
       base::Bind(&base::CreatePlatformFile,
                  local_path, file_flags, static_cast<bool*>(NULL), result),
-      base::Bind(&RunOpenFileCallback, callback, base::Owned(result)));
+      base::Bind(&RunOpenFileCallback,
+                 callback, close_callback, base::Owned(result)));
   DCHECK(posted);
 }
 
-// Emits debug log when FileSystem::CloseFile() is complete.
-void EmitDebugLogForCloseFile(const base::FilePath& local_path,
-                              FileError file_error) {
-  DVLOG(1) << "Closed: " << local_path.AsUTF8Unsafe() << ": " << file_error;
-}
-
 }  // namespace
 
 void RunFileSystemCallback(
@@ -336,7 +335,8 @@
         FROM_HERE,
         base::Bind(callback,
                    base::PLATFORM_FILE_ERROR_FAILED,
-                   base::kInvalidPlatformFileValue));
+                   base::kInvalidPlatformFileValue,
+                   base::Closure()));
     return;
   }
 
@@ -345,13 +345,6 @@
       base::Bind(&OpenFileAfterFileSystemOpenFile, file_flags, callback));
 }
 
-void CloseFile(const base::FilePath& file_path,
-               FileSystemInterface* file_system) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  file_system->CloseFile(file_path,
-                         base::Bind(&EmitDebugLogForCloseFile, file_path));
-}
-
 void TouchFile(const base::FilePath& file_path,
                const base::Time& last_access_time,
                const base::Time& last_modified_time,
diff --git a/chrome/browser/chromeos/drive/fileapi_worker.h b/chrome/browser/chromeos/drive/fileapi_worker.h
index d26c65e..bef86f9 100644
--- a/chrome/browser/chromeos/drive/fileapi_worker.h
+++ b/chrome/browser/chromeos/drive/fileapi_worker.h
@@ -61,23 +61,25 @@
     CreateSnapshotFileCallback;
 typedef base::Callback<
     void(base::PlatformFileError result,
-         const base::FilePath& snapshot_file_path)>
+         const base::FilePath& snapshot_file_path,
+         const base::Closure& close_callback)>
     CreateWritableSnapshotFileCallback;
 typedef base::Callback<
     void(base::PlatformFileError result,
-         base::PlatformFile platform_file)> OpenFileCallback;
+         base::PlatformFile platform_file,
+         const base::Closure& close_callback)> OpenFileCallback;
 
 // Runs |file_system_getter| to obtain the instance of FileSystemInstance,
 // and then runs |callback| with it.
-// If |file_system_getter| returns NULL, runs |on_error_callback| instead.
+// If |file_system_getter| returns NULL, runs |error_callback| instead.
 // This function must be called on UI thread.
 // |file_system_getter| and |callback| must not be null, but
-// |on_error_callback| can be null (if no operation is necessary for error
+// |error_callback| can be null (if no operation is necessary for error
 // case).
 void RunFileSystemCallback(
     const FileSystemGetter& file_system_getter,
     const base::Callback<void(FileSystemInterface*)>& callback,
-    const base::Closure& on_error_callback);
+    const base::Closure& error_callback);
 
 // Returns the metadata info of the file at |file_path|.
 // Called from FileSystemProxy::GetFileInfo().
@@ -148,7 +150,7 @@
                         FileSystemInterface* file_system);
 
 // Creates a writable snapshot for the file at |file_path|.
-// After writing operation is done, CloseFile is needed to be called.
+// After writing operation is done, |close_callback| must be called.
 void CreateWritableSnapshotFile(
     const base::FilePath& file_path,
     const CreateWritableSnapshotFileCallback& callback,
@@ -161,12 +163,6 @@
               const OpenFileCallback& callback,
               FileSystemInterface* file_system);
 
-// Closes the file at |file_path|.
-// Called from FileSystemProxy::NotifyCloseFile and
-// FileSystemProxy::CloseWRitableSnapshotFile.
-void CloseFile(const base::FilePath& file_path,
-               FileSystemInterface* file_system);
-
 // Changes timestamp of the file at |file_path| to |last_access_time| and
 // |last_modified_time|. Called from FileSystemProxy::TouchFile().
 void TouchFile(const base::FilePath& file_path,
diff --git a/chrome/browser/chromeos/drive/search_metadata.cc b/chrome/browser/chromeos/drive/search_metadata.cc
index b49f47f..9e5b30c 100644
--- a/chrome/browser/chromeos/drive/search_metadata.cc
+++ b/chrome/browser/chromeos/drive/search_metadata.cc
@@ -152,12 +152,12 @@
 }
 
 // Implements SearchMetadata().
-scoped_ptr<MetadataSearchResultVector> SearchMetadataOnBlockingPool(
-    ResourceMetadata* resource_metadata,
-    FileCache* cache,
-    const std::string& query_text,
-    int options,
-    int at_most_num_matches) {
+FileError SearchMetadataOnBlockingPool(ResourceMetadata* resource_metadata,
+                                       FileCache* cache,
+                                       const std::string& query_text,
+                                       int options,
+                                       int at_most_num_matches,
+                                       MetadataSearchResultVector* results) {
   ScopedPriorityQueue<MetadataSearchResult,
                       MetadataSearchResultComparator> result_candidates;
 
@@ -175,8 +175,6 @@
   }
 
   // Prepare the result.
-  scoped_ptr<MetadataSearchResultVector> results(
-      new MetadataSearchResultVector);
   for (; !result_candidates.empty(); result_candidates.pop()) {
     // The path field of entries in result_candidates are empty at this point,
     // because we don't want to run the expensive metadata DB look up except for
@@ -184,7 +182,7 @@
     base::FilePath path = resource_metadata->GetFilePath(
         result_candidates.top()->entry.resource_id());
     if (path.empty())
-      continue;
+      return FILE_ERROR_FAILED;
     results->push_back(*result_candidates.top());
     results->back().path = path;
   }
@@ -193,8 +191,17 @@
   // uninteresting candidate at the top.
   std::reverse(results->begin(), results->end());
 
-  return results.Pass();
+  return FILE_ERROR_OK;
 }
+
+void RunSearchMetadataCallback(const SearchMetadataCallback& callback,
+                               scoped_ptr<MetadataSearchResultVector> results,
+                               FileError error) {
+  if (error != FILE_ERROR_OK)
+    results.reset();
+  callback.Run(error, results.Pass());
+}
+
 }  // namespace
 
 void SearchMetadata(
@@ -209,8 +216,9 @@
   DCHECK_LE(0, at_most_num_matches);
   DCHECK(!callback.is_null());
 
-  // TODO(hashimoto): Report error code from ResourceMetadata::IterateEntries
-  // and stop binding FILE_ERROR_OK to |callback|.
+  scoped_ptr<MetadataSearchResultVector> results(
+      new MetadataSearchResultVector);
+  MetadataSearchResultVector* results_ptr = results.get();
   base::PostTaskAndReplyWithResult(blocking_task_runner.get(),
                                    FROM_HERE,
                                    base::Bind(&SearchMetadataOnBlockingPool,
@@ -218,8 +226,11 @@
                                               cache,
                                               query,
                                               options,
-                                              at_most_num_matches),
-                                   base::Bind(callback, FILE_ERROR_OK));
+                                              at_most_num_matches,
+                                              results_ptr),
+                                   base::Bind(&RunSearchMetadataCallback,
+                                              callback,
+                                              base::Passed(&results)));
 }
 
 bool FindAndHighlight(
diff --git a/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.cc b/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.cc
index 94e8e80..3363340 100644
--- a/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.cc
+++ b/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.cc
@@ -37,23 +37,8 @@
           base::Bind(&fileapi_internal::CreateWritableSnapshotFile,
                      drive_path, google_apis::CreateRelayCallback(callback)),
           google_apis::CreateRelayCallback(base::Bind(
-              callback, base::PLATFORM_FILE_ERROR_FAILED, base::FilePath()))));
-}
-
-// Closes the writable snapshot file opened by CreateWritableSnapshotFile.
-// TODO(hidehiko): Get rid of this function. crbug.com/259184.
-void CloseFile(
-    const WebkitFileStreamWriterImpl::FileSystemGetter& file_system_getter,
-    const base::FilePath& drive_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&fileapi_internal::RunFileSystemCallback,
-                 file_system_getter,
-                 base::Bind(&fileapi_internal::CloseFile, drive_path),
-                 base::Closure()));
+              callback, base::PLATFORM_FILE_ERROR_FAILED, base::FilePath(),
+              base::Closure()))));
 }
 
 }  // namespace
@@ -75,7 +60,10 @@
     // If the file is opened, close it at destructor.
     // It is necessary to close the local file in advance.
     local_file_writer_.reset();
-    CloseFile(file_system_getter_, file_path_);
+    DCHECK(!close_callback_on_ui_thread_.is_null());
+    BrowserThread::PostTask(BrowserThread::UI,
+                            FROM_HERE,
+                            close_callback_on_ui_thread_);
   }
 }
 
@@ -146,7 +134,8 @@
     net::IOBuffer* buf,
     int buf_len,
     base::PlatformFileError open_result,
-    const base::FilePath& local_path) {
+    const base::FilePath& local_path,
+    const base::Closure& close_callback_on_ui_thread) {
   DCHECK(!local_file_writer_);
 
   if (!pending_cancel_callback_.is_null()) {
@@ -156,8 +145,10 @@
     if (open_result == base::PLATFORM_FILE_OK) {
       // Here the file is internally created. To revert the operation, close
       // the file.
-      DCHECK(!local_path.empty());
-      CloseFile(file_system_getter_, file_path_);
+      DCHECK(!close_callback_on_ui_thread.is_null());
+      BrowserThread::PostTask(BrowserThread::UI,
+                              FROM_HERE,
+                              close_callback_on_ui_thread);
     }
 
     base::ResetAndReturn(&pending_cancel_callback_).Run(net::OK);
@@ -169,10 +160,14 @@
   const net::CompletionCallback callback =
       base::ResetAndReturn(&pending_write_callback_);
   if (open_result != base::PLATFORM_FILE_OK) {
+    DCHECK(close_callback_on_ui_thread.is_null());
     callback.Run(net::PlatformFileErrorToNetError(open_result));
     return;
   }
 
+  // Keep |close_callback| to close the file when the stream is destructed.
+  DCHECK(!close_callback_on_ui_thread.is_null());
+  close_callback_on_ui_thread_ = close_callback_on_ui_thread;
   local_file_writer_.reset(new fileapi::LocalFileStreamWriter(
       file_task_runner_.get(), local_path, offset_));
   int result = local_file_writer_->Write(buf, buf_len, callback);
diff --git a/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.h b/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.h
index 1ddadba..e72a692 100644
--- a/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.h
+++ b/chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.h
@@ -58,7 +58,8 @@
       net::IOBuffer* buf,
       int buf_len,
       base::PlatformFileError open_result,
-      const base::FilePath& local_path);
+      const base::FilePath& local_path,
+      const base::Closure& close_callback_on_ui_thread);
 
   FileSystemGetter file_system_getter_;
   scoped_refptr<base::TaskRunner> file_task_runner_;
@@ -66,6 +67,7 @@
   const int64 offset_;
 
   scoped_ptr<fileapi::FileStreamWriter> local_file_writer_;
+  base::Closure close_callback_on_ui_thread_;
   net::CompletionCallback pending_write_callback_;
   net::CompletionCallback pending_cancel_callback_;
 
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
index e98365c..f72c165 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
@@ -8,7 +8,6 @@
 #include "ash/wm/window_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
-#include "content/public/test/test_browser_thread.h"
 #include "ui/aura/root_window.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
@@ -16,14 +15,6 @@
 namespace {
 
 class WallpaperPrivateApiUnittest : public ash::test::AshTestBase {
- public:
-  WallpaperPrivateApiUnittest()
-      : ui_thread_(content::BrowserThread::UI, message_loop()) {}
-
- private:
-  content::TestBrowserThread ui_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateApiUnittest);
 };
 
 class TestMinimizeFunction
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
index 12c633f..2ef9454 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
@@ -190,8 +190,26 @@
     return false;
   if (!dict.GetString(extension_manifest_keys::kName, &out->display_name))
     return false;
-  if (!dict.GetString(extension_manifest_keys::kLanguage, &out->language_code))
-    return false;
+
+  std::set<std::string> languages;
+  const base::Value* language_value = NULL;
+  if (dict.Get(extension_manifest_keys::kLanguage, &language_value)) {
+    if (language_value->GetType() == base::Value::TYPE_STRING) {
+      std::string language_str;
+      language_value->GetAsString(&language_str);
+      languages.insert(language_str);
+    } else if (language_value->GetType() == base::Value::TYPE_LIST) {
+      const base::ListValue* language_list = NULL;
+      language_value->GetAsList(&language_list);
+      for (size_t j = 0; j < language_list->GetSize(); ++j) {
+        std::string language_str;
+        if (language_list->GetString(j, &language_str))
+          languages.insert(language_str);
+      }
+    }
+  }
+  DCHECK(!languages.empty());
+  out->language_codes.assign(languages.begin(), languages.end());
 
   const ListValue* layouts = NULL;
   if (!dict.GetList(extension_manifest_keys::kLayouts, &layouts))
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index fcb8919..7f2fa95 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -110,6 +110,12 @@
 
 }  // namespace
 
+bool InputMethodManagerImpl::IsFullLatinKeyboard(
+    const std::string& layout) const {
+  const std::string& lang = util_.GetLanguageCodeFromInputMethodId(layout);
+  return full_latin_keyboard_checker.IsFullLatinKeyboard(layout, lang);
+}
+
 InputMethodManagerImpl::InputMethodManagerImpl(
     scoped_ptr<InputMethodDelegate> delegate)
     : delegate_(delegate.Pass()),
@@ -207,6 +213,11 @@
   return result.Pass();
 }
 
+const std::vector<std::string>&
+InputMethodManagerImpl::GetActiveInputMethodIds() const {
+  return active_input_method_ids_;
+}
+
 size_t InputMethodManagerImpl::GetNumActiveInputMethods() const {
   return active_input_method_ids_.size();
 }
@@ -250,6 +261,46 @@
   ChangeInputMethod(initial_layout);  // you can pass empty |initial_layout|.
 }
 
+// Adds new input method to given list.
+bool InputMethodManagerImpl::EnableInputMethodImpl(
+    const std::string& input_method_id,
+    std::vector<std::string>& new_active_input_method_ids) const {
+  if (!util_.IsValidInputMethodId(input_method_id)) {
+    DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id;
+    return false;
+  }
+
+  if (!Contains(new_active_input_method_ids, input_method_id))
+    new_active_input_method_ids.push_back(input_method_id);
+
+  return true;
+}
+
+// Starts or stops the system input method framework as needed.
+void InputMethodManagerImpl::ReconfigureIMFramework() {
+  if (component_extension_ime_manager_->IsInitialized())
+    LoadNecessaryComponentExtensions();
+
+  if (ContainsOnlyKeyboardLayout(active_input_method_ids_)) {
+    // Do NOT call ibus_controller_->Stop(); here to work around a crash issue
+    // at crbug.com/27051.
+    // TODO(yusukes): We can safely call Stop(); here once crbug.com/26443
+    // is implemented.
+  } else {
+    MaybeInitializeCandidateWindowController();
+    IBusDaemonController::GetInstance()->Start();
+  }
+}
+
+bool InputMethodManagerImpl::EnableInputMethod(
+    const std::string& input_method_id) {
+  if (!EnableInputMethodImpl(input_method_id, active_input_method_ids_))
+    return false;
+
+  ReconfigureIMFramework();
+  return true;
+}
+
 bool InputMethodManagerImpl::EnableInputMethods(
     const std::vector<std::string>& new_active_input_method_ids) {
   if (state_ == STATE_TERMINATING)
@@ -258,13 +309,9 @@
   // Filter unknown or obsolete IDs.
   std::vector<std::string> new_active_input_method_ids_filtered;
 
-  for (size_t i = 0; i < new_active_input_method_ids.size(); ++i) {
-    const std::string& input_method_id = new_active_input_method_ids[i];
-    if (util_.IsValidInputMethodId(input_method_id))
-      new_active_input_method_ids_filtered.push_back(input_method_id);
-    else
-      DVLOG(1) << "EnableInputMethods: Invalid ID: " << input_method_id;
-  }
+  for (size_t i = 0; i < new_active_input_method_ids.size(); ++i)
+    EnableInputMethodImpl(new_active_input_method_ids[i],
+                          new_active_input_method_ids_filtered);
 
   if (new_active_input_method_ids_filtered.empty()) {
     DVLOG(1) << "EnableInputMethods: No valid input method ID";
@@ -280,18 +327,7 @@
   }
   active_input_method_ids_.swap(new_active_input_method_ids_filtered);
 
-  if (component_extension_ime_manager_->IsInitialized())
-    LoadNecessaryComponentExtensions();
-
-  if (ContainOnlyKeyboardLayout(active_input_method_ids_)) {
-    // Do NOT call ibus_controller_->Stop(); here to work around a crash issue
-    // at crosbug.com/27051.
-    // TODO(yusukes): We can safely call Stop(); here once crosbug.com/26443
-    // is implemented.
-  } else {
-    MaybeInitializeCandidateWindowController();
-    IBusDaemonController::GetInstance()->Start();
-  }
+  ReconfigureIMFramework();
 
   // If |current_input_method| is no longer in |active_input_method_ids_|,
   // ChangeInputMethod() picks the first one in |active_input_method_ids_|.
@@ -564,7 +600,7 @@
     active_input_method_ids_.erase(i);
   extra_input_methods_.erase(id);
 
-  if (ContainOnlyKeyboardLayout(active_input_method_ids_)) {
+  if (ContainsOnlyKeyboardLayout(active_input_method_ids_)) {
     // Do NOT call ibus_controller_->Stop(); here to work around a crash issue
     // at crosbug.com/27051.
     // TODO(yusukes): We can safely call Stop(); here once crosbug.com/26443
@@ -662,7 +698,8 @@
   return true;
 }
 
-bool InputMethodManagerImpl::SwitchToPreviousInputMethod() {
+bool InputMethodManagerImpl::SwitchToPreviousInputMethod(
+    const ui::Accelerator& accelerator) {
   // Sanity check.
   if (active_input_method_ids_.empty()) {
     DVLOG(1) << "active input method is empty";
@@ -674,6 +711,9 @@
   if (active_input_method_ids_.size() == 1)
     return false;
 
+  if (accelerator.type() == ui::ET_KEY_RELEASED)
+    return true;
+
   if (previous_input_method_.id().empty() ||
       previous_input_method_.id() == current_input_method_.id()) {
     return SwitchToNextInputMethod();
@@ -918,7 +958,7 @@
   return Contains(active_input_method_ids_, input_method_id);
 }
 
-bool InputMethodManagerImpl::ContainOnlyKeyboardLayout(
+bool InputMethodManagerImpl::ContainsOnlyKeyboardLayout(
     const std::vector<std::string>& value) {
   for (size_t i = 0; i < value.size(); ++i) {
     if (!InputMethodUtil::IsKeyboardLayout(value[i]))
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.h b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
index 521e04a..1d0d417 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.h
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
@@ -14,6 +14,7 @@
 #include "base/threading/thread_checker.h"
 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
 #include "chrome/browser/chromeos/input_method/ibus_controller.h"
+#include "chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chromeos/ime/ibus_daemon_controller.h"
 #include "chromeos/ime/input_method_manager.h"
@@ -58,11 +59,15 @@
       GetSupportedInputMethods() const OVERRIDE;
   virtual scoped_ptr<InputMethodDescriptors>
       GetActiveInputMethods() const OVERRIDE;
+  virtual const std::vector<std::string>& GetActiveInputMethodIds() const
+      OVERRIDE;
   virtual size_t GetNumActiveInputMethods() const OVERRIDE;
   virtual void EnableLayouts(const std::string& language_code,
                              const std::string& initial_layout) OVERRIDE;
   virtual bool EnableInputMethods(
       const std::vector<std::string>& new_active_input_method_ids) OVERRIDE;
+  virtual bool EnableInputMethod(const std::string& new_active_input_method_id)
+      OVERRIDE;
   virtual bool MigrateOldInputMethods(
       std::vector<std::string>* input_method_ids) OVERRIDE;
   virtual bool MigrateKoreanKeyboard(
@@ -86,7 +91,8 @@
       InputMethodDescriptors* result) OVERRIDE;
   virtual void SetEnabledExtensionImes(std::vector<std::string>* ids) OVERRIDE;
   virtual bool SwitchToNextInputMethod() OVERRIDE;
-  virtual bool SwitchToPreviousInputMethod() OVERRIDE;
+  virtual bool SwitchToPreviousInputMethod(
+      const ui::Accelerator& accelerator) OVERRIDE;
   virtual bool SwitchInputMethod(const ui::Accelerator& accelerator) OVERRIDE;
   virtual InputMethodDescriptor GetCurrentInputMethod() const OVERRIDE;
   virtual InputMethodPropertyList
@@ -95,6 +101,7 @@
   virtual InputMethodUtil* GetInputMethodUtil() OVERRIDE;
   virtual ComponentExtensionIMEManager*
       GetComponentExtensionIMEManager() OVERRIDE;
+  virtual bool IsFullLatinKeyboard(const std::string& layout) const OVERRIDE;
 
   // Sets |ibus_controller_|.
   void SetIBusControllerForTesting(IBusController* ibus_controller);
@@ -135,7 +142,7 @@
 
   // Returns true if the given input method config value is a string list
   // that only contains an input method ID of a keyboard layout.
-  bool ContainOnlyKeyboardLayout(const std::vector<std::string>& value);
+  bool ContainsOnlyKeyboardLayout(const std::vector<std::string>& value);
 
   // Returns true if the connection to ibus-daemon is established.
   bool IsIBusConnectionAlive();
@@ -165,6 +172,15 @@
   // TODO(nona): Support dynamical unloading.
   void LoadNecessaryComponentExtensions();
 
+  // Adds new input method to given list if possible
+  bool EnableInputMethodImpl(
+      const std::string& input_method_id,
+      std::vector<std::string>& new_active_input_method_ids) const;
+
+  // Starts or stops the system input method framework as needed.
+  // (after list of enabled input methods has been updated)
+  void ReconfigureIMFramework();
+
   scoped_ptr<InputMethodDelegate> delegate_;
 
   // The current browser status.
@@ -223,6 +239,10 @@
 
   base::WeakPtrFactory<InputMethodManagerImpl> weak_ptr_factory_;
 
+  // Check if input method id allows full latin input (for entering passwords on
+  // login screen)
+  FullLatinKeyboardLayoutChecker full_latin_keyboard_checker;
+
   DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImpl);
 };
 
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc
new file mode 100644
index 0000000..7bf850c
--- /dev/null
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc
@@ -0,0 +1,124 @@
+// 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/input_method/input_method_manager_impl_ll.h"
+
+#include <string.h>
+
+#include <limits>
+
+namespace chromeos {
+namespace input_method {
+
+struct KBDList {
+  const char* const* layouts;
+  size_t size;
+};
+
+namespace {
+
+// A language may have some special layout that allows full latin input.
+static const char* const kJPFullLatinKeyboardLayouts[] = {
+  "xkb:jp::jpn"
+};
+
+static const KBDList kJPFullLatinKeyboards = {
+  kJPFullLatinKeyboardLayouts, arraysize(kJPFullLatinKeyboardLayouts)
+};
+
+// A list of languages and their layouts having full 26 latin letter set on
+// keyboard.
+
+// If permitted_layouts is NULL, then all keyboard layouts for the
+// language are "Full Latin Input" and can be used to input passwords on
+// login screen.
+
+// If permitted_layouts is not NULL, it must contain all layouts for the
+// language, that can be used at login screen.
+//
+static const struct SomeLatinKeyboardLanguageList {
+  const char* lang;
+  const KBDList* permitted_layouts;
+} kHasLatinKeyboardLanguageList[] = {
+  {"ca" /* Catalan            */, NULL},
+  {"cs" /* Czech              */, NULL},
+  {"da" /* Danish             */, NULL},
+  {"de" /* German             */, NULL},
+  {"en" /* English            */, NULL},
+  {"es" /* Spanish            */, NULL},
+  {"et" /* Estonian           */, NULL},
+  {"fi" /* Finnish            */, NULL},
+  {"fr" /* French             */, NULL},
+  {"ja" /* Japanese           */, &kJPFullLatinKeyboards},
+  {"hr" /* Croatian           */, NULL},
+  {"hu" /* Hungarian          */, NULL},
+  {"is" /* Icelandic          */, NULL},
+  {"it" /* Italian            */, NULL},
+  {"lt" /* Lithuanian         */, NULL},
+  {"lv" /* Latvian            */, NULL},
+  {"nb" /* Norwegian (Bokmal) */, NULL},
+  {"nl" /* Dutch              */, NULL},
+  {"pl" /* Polish             */, NULL},
+  {"pt" /* Portuguese         */, NULL},
+  {"ro" /* Romanian           */, NULL},
+  {"sk" /* Slovak             */, NULL},
+  {"sl" /* Slovenian          */, NULL},
+  {"sv" /* Swedish            */, NULL},
+  {"tr" /* Turkish            */, NULL},
+};
+
+}  // namespace
+
+bool FullLatinKeyboardLayoutChecker::IsFullLatinKeyboard(
+    const std::string& layout,
+    const std::string& lang) const {
+  if (lang.size() < 2) {
+    return false;
+  }
+
+  const TwoLetterLanguageCode ll(lang.c_str());
+  const std::vector<TwoLetterLanguageCode2KBDList>::const_iterator pos =
+      std::lower_bound(full_latin_keyboard_languages_.begin(),
+                       full_latin_keyboard_languages_.end(),
+                       ll);
+
+  if (pos == full_latin_keyboard_languages_.end())
+    return false;
+
+  if (pos->lang != ll)
+    return false;
+
+  const KBDList* kbdlist =
+      kHasLatinKeyboardLanguageList[pos->index].permitted_layouts;
+
+  if (kbdlist == NULL)
+    return true;
+
+  for (size_t i = 0; i < kbdlist->size; ++i)
+    if (strcmp(layout.c_str(), kbdlist->layouts[i]) == 0)
+      return true;
+
+  return false;
+}
+
+FullLatinKeyboardLayoutChecker::FullLatinKeyboardLayoutChecker() {
+  DCHECK(arraysize(kHasLatinKeyboardLanguageList) <
+         std::numeric_limits<uint16_t>::max());
+
+  full_latin_keyboard_languages_.reserve(
+      arraysize(kHasLatinKeyboardLanguageList));
+
+  for (size_t i = 0; i < arraysize(kHasLatinKeyboardLanguageList); ++i)
+    full_latin_keyboard_languages_.push_back(TwoLetterLanguageCode2KBDList(
+        kHasLatinKeyboardLanguageList[i].lang, i));
+
+  std::sort(full_latin_keyboard_languages_.begin(),
+            full_latin_keyboard_languages_.end());
+}
+
+FullLatinKeyboardLayoutChecker::~FullLatinKeyboardLayoutChecker() {
+}
+
+}  // namespace input_method
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h
new file mode 100644
index 0000000..f670abc
--- /dev/null
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h
@@ -0,0 +1,67 @@
+// 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_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_LL_H_
+#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_LL_H_
+
+// "Latin Layout" checker: checks if given keyboard layout is "Full Latin Input"
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_util.h"
+
+namespace chromeos {
+namespace input_method {
+
+class TwoLetterLanguageCode {
+ public:
+  TwoLetterLanguageCode() : val(0) {}
+  explicit TwoLetterLanguageCode(const char* lang)
+      : val(base::ToLowerASCII(lang[0]) * 256 + base::ToLowerASCII(lang[1])) {}
+
+  bool operator<(const TwoLetterLanguageCode& r) const { return val < r.val; }
+  bool operator!=(const TwoLetterLanguageCode& r) const { return val != r.val; }
+
+ private:
+  uint16_t val;
+};
+
+// To keep index small, sizeof(TwoLetterLanguageCode2KBDList) = 4.
+class TwoLetterLanguageCode2KBDList {
+ public:
+  TwoLetterLanguageCode2KBDList() : index(0) {}
+  TwoLetterLanguageCode2KBDList(const char* l, const uint16_t i)
+      : lang(l), index(i) {}
+
+  bool operator<(const TwoLetterLanguageCode2KBDList& r) const {
+    return lang < r.lang;
+  }
+  bool operator<(const TwoLetterLanguageCode& r) const { return lang < r; }
+
+  TwoLetterLanguageCode lang;
+
+  // index in kHasLatinKeyboardLanguageList[]
+  uint16_t index;
+};
+
+// For fast lookup "whether this language and layout are among listed in
+// kHasLatinKeyboardLanguageList[] or not".
+class FullLatinKeyboardLayoutChecker {
+ public:
+  FullLatinKeyboardLayoutChecker();
+  ~FullLatinKeyboardLayoutChecker();
+
+  bool IsFullLatinKeyboard(const std::string& layout,
+                           const std::string& lang) const;
+
+ private:
+  // Sorted vector for fast lookup.
+  std::vector<TwoLetterLanguageCode2KBDList> full_latin_keyboard_languages_;
+};
+
+}  // namespace input_method
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_LL_H_
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index d6d610f..978007e 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -84,14 +84,14 @@
     ComponentExtensionEngine ext1_engine1;
     ext1_engine1.engine_id = "nacl_mozc_us";
     ext1_engine1.display_name = "ext1_engine_1_display_name";
-    ext1_engine1.language_code = "ja";
+    ext1_engine1.language_codes.push_back("ja");
     ext1_engine1.layouts.push_back("us");
     ext1.engines.push_back(ext1_engine1);
 
     ComponentExtensionEngine ext1_engine2;
     ext1_engine2.engine_id = "nacl_mozc_jp";
     ext1_engine2.display_name = "ext1_engine_1_display_name";
-    ext1_engine2.language_code = "ja";
+    ext1_engine2.language_codes.push_back("ja");
     ext1_engine2.layouts.push_back("jp");
     ext1.engines.push_back(ext1_engine2);
 
@@ -105,14 +105,14 @@
     ComponentExtensionEngine ext2_engine1;
     ext2_engine1.engine_id = "ext2_engine1_engine_id";
     ext2_engine1.display_name = "ext2_engine_1_display_name";
-    ext2_engine1.language_code = "en";
+    ext2_engine1.language_codes.push_back("en");
     ext2_engine1.layouts.push_back("us");
     ext2.engines.push_back(ext2_engine1);
 
     ComponentExtensionEngine ext2_engine2;
     ext2_engine2.engine_id = "ext2_engine2_engine_id";
     ext2_engine2.display_name = "ext2_engine_2_display_name";
-    ext2_engine2.language_code = "en";
+    ext2_engine2.language_codes.push_back("en");
     ext2_engine2.layouts.push_back("us(dvorak)");
     ext2.engines.push_back(ext2_engine2);
 
@@ -778,39 +778,50 @@
   manager_->AddObserver(&observer);
   InitComponentExtension();
   InitIBusBus();
+
+  ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
+  keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
+  ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
+  keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
+
   manager_->EnableLayouts("en-US", "xkb:us::eng");
   EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us", xkeyboard_->last_layout_);
-  manager_->SwitchToNextInputMethod();
+  EXPECT_TRUE(manager_->SwitchToNextInputMethod());
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us", xkeyboard_->last_layout_);
-  manager_->SwitchToNextInputMethod();
+  EXPECT_TRUE(manager_->SwitchToNextInputMethod());
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
-  manager_->SwitchToNextInputMethod();
+  EXPECT_TRUE(manager_->SwitchToNextInputMethod());
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
   EXPECT_TRUE(observer.last_show_message_);
   EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
@@ -818,6 +829,31 @@
   manager_->RemoveObserver(&observer);
 }
 
+TEST_F(InputMethodManagerImplTest,
+       TestSwitchToPreviousInputMethodForOneActiveInputMethod) {
+  TestObserver observer;
+  manager_->AddObserver(&observer);
+  InitComponentExtension();
+  InitIBusBus();
+
+  ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
+  keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
+  ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
+  keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
+
+  std::vector<std::string> ids;
+  ids.push_back("xkb:us:dvorak:eng");
+  EXPECT_TRUE(manager_->EnableInputMethods(ids));
+  EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
+
+  // Ctrl+Space accelerator should not be consumed if there is only one active
+  // input method.
+  EXPECT_FALSE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_FALSE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
+
+  manager_->RemoveObserver(&observer);
+}
+
 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithUsLayouts) {
   TestObserver observer;
   manager_->AddObserver(&observer);
@@ -855,6 +891,12 @@
   // Enable "xkb:jp::jpn" and press Muhenkan/ZenkakuHankaku.
   InitComponentExtension();
   InitIBusBus();
+
+  ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
+  keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
+  ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
+  keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
+
   manager_->EnableLayouts("ja", "xkb:us::eng");
   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
@@ -863,14 +905,16 @@
       ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("jp", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us", xkeyboard_->last_layout_);
   EXPECT_TRUE(manager_->SwitchInputMethod(
       ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("jp", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
+  EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us", xkeyboard_->last_layout_);
   EXPECT_TRUE(manager_->SwitchInputMethod(
diff --git a/chrome/browser/chromeos/input_method/input_method_persistence.cc b/chrome/browser/chromeos/input_method/input_method_persistence.cc
index 9562b23..49809fe 100644
--- a/chrome/browser/chromeos/input_method/input_method_persistence.cc
+++ b/chrome/browser/chromeos/input_method/input_method_persistence.cc
@@ -4,11 +4,13 @@
 
 #include "chrome/browser/chromeos/input_method/input_method_persistence.h"
 
+#include "base/chromeos/chromeos_version.h"
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/pref_names.h"
@@ -25,7 +27,62 @@
         language_prefs::kPreferredKeyboardLayout, input_method);
 }
 
-void PersistUserInputMethod(const std::string& input_method) {
+// Update user LRU keyboard layout for login screen
+static void SetUserLRUInputMethod(
+    const std::string& input_method,
+    const chromeos::input_method::InputMethodManager* const manager) {
+  // Skip if it's not a keyboard layout. Drop input methods including
+  // extension ones.
+  if (!InputMethodUtil::IsKeyboardLayout(input_method))
+    return;
+
+  PrefService* const local_state = g_browser_process->local_state();
+
+  Profile* const profile = ProfileManager::GetDefaultProfile();
+
+  if (profile == NULL)
+    return;
+
+  if (!manager->IsFullLatinKeyboard(input_method))
+    return;
+
+  const std::string username = profile->GetProfileName();
+  if (base::chromeos::IsRunningOnChromeOS() && !username.empty() &&
+      !local_state->ReadOnly()) {
+    bool update_succeed = false;
+    {
+      // Updater may have side-effects, therefore we do not replace
+      // entry while updater exists.
+      DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
+      base::DictionaryValue* const users_lru_input_methods = updater.Get();
+      if (users_lru_input_methods) {
+        users_lru_input_methods->SetStringWithoutPathExpansion(username,
+                                                               input_method);
+        update_succeed = true;
+      }
+    }
+    if (!update_succeed) {
+      // Somehow key kUsersLRUInputMethod has value of invalid type.
+      // Replace and retry.
+      local_state->Set(prefs::kUsersLRUInputMethod, base::DictionaryValue());
+
+      DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
+      base::DictionaryValue* const users_lru_input_methods = updater.Get();
+      if (users_lru_input_methods) {
+        users_lru_input_methods->SetStringWithoutPathExpansion(username,
+                                                               input_method);
+        update_succeed = true;
+      }
+    }
+    if (!update_succeed) {
+      DVLOG(1) << "Failed to replace local_state.kUsersLRUInputMethod: '"
+               << prefs::kUsersLRUInputMethod << "' for '" << username << "'";
+    }
+  }
+}
+
+void PersistUserInputMethod(const std::string& input_method,
+                            InputMethodManager* const manager) {
   PrefService* user_prefs = NULL;
   Profile* profile = ProfileManager::GetDefaultProfile();
   if (profile)
@@ -33,6 +90,8 @@
   if (!user_prefs)
     return;
 
+  SetUserLRUInputMethod(input_method, manager);
+
   const std::string current_input_method_on_pref =
       user_prefs->GetString(prefs::kLanguageCurrentInputMethod);
   if (current_input_method_on_pref == input_method)
@@ -73,7 +132,7 @@
       PersistSystemInputMethod(current_input_method);
       return;
     case InputMethodManager::STATE_BROWSER_SCREEN:
-      PersistUserInputMethod(current_input_method);
+      PersistUserInputMethod(current_input_method, manager);
       return;
     case InputMethodManager::STATE_LOCK_SCREEN:
       // We use a special set of input methods on the screen. Do not update.
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc
index 3258cda..da9a85e 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -70,6 +70,14 @@
   { "m17n:zh:quick", "\xe9\x80\x9f" },  // U+901F
   // For Hangul input method.
   { "mozc-hangul", "\xed\x95\x9c" },  // U+D55C
+  { "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_2set", "\xed\x95\x9c" },
+  { "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3set390",
+    "\xed\x95\x9c" },
+  { "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3setfinal",
+    "\xed\x95\x9c" },
+  { "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3setnoshift",
+    "\xed\x95\x9c" },
+  { "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_romaja", "\xed\x95\x9c" },
 };
 
 const size_t kMappingFromIdToIndicatorTextLen =
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
index ad18c70..4aeef61 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
@@ -11,6 +11,7 @@
     : add_observer_count_(0),
       remove_observer_count_(0),
       util_(&delegate_, whitelist_.GetSupportedInputMethods()) {
+  active_input_method_ids_.push_back("xkb:us::eng");
 }
 
 MockInputMethodManager::~MockInputMethodManager() {
@@ -50,6 +51,11 @@
   return result.Pass();
 }
 
+const std::vector<std::string>&
+MockInputMethodManager::GetActiveInputMethodIds() const {
+  return active_input_method_ids_;
+}
+
 size_t MockInputMethodManager::GetNumActiveInputMethods() const {
   return 1;
 }
@@ -63,6 +69,11 @@
   return true;
 }
 
+bool MockInputMethodManager::EnableInputMethod(
+    const std::string& new_active_input_method_id) {
+  return true;
+}
+
 bool MockInputMethodManager::MigrateOldInputMethods(
     std::vector<std::string>* input_method_ids) {
   return false;
@@ -113,7 +124,8 @@
   return true;
 }
 
-bool MockInputMethodManager::SwitchToPreviousInputMethod() {
+bool MockInputMethodManager::SwitchToPreviousInputMethod(
+    const ui::Accelerator& accelerator) {
   return true;
 }
 
@@ -162,5 +174,9 @@
   delegate_.set_hardware_keyboard_layout(value);
 }
 
+bool MockInputMethodManager::IsFullLatinKeyboard(
+    const std::string& layout) const {
+  return true;
+}
 }  // namespace input_method
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.h b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
index e373707..5db4950 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.h
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
@@ -31,11 +31,15 @@
       GetSupportedInputMethods() const OVERRIDE;
   virtual scoped_ptr<InputMethodDescriptors>
       GetActiveInputMethods() const OVERRIDE;
+  virtual const std::vector<std::string>& GetActiveInputMethodIds() const
+      OVERRIDE;
   virtual size_t GetNumActiveInputMethods() const OVERRIDE;
   virtual void EnableLayouts(const std::string& language_code,
                              const std::string& initial_layout) OVERRIDE;
   virtual bool EnableInputMethods(
       const std::vector<std::string>& new_active_input_method_ids) OVERRIDE;
+  virtual bool EnableInputMethod(
+      const std::string& new_active_input_method_id) OVERRIDE;
   virtual bool MigrateOldInputMethods(
       std::vector<std::string>* input_method_ids) OVERRIDE;
   virtual bool MigrateKoreanKeyboard(
@@ -59,7 +63,8 @@
       InputMethodDescriptors* result) OVERRIDE;
   virtual void SetEnabledExtensionImes(std::vector<std::string>* ids) OVERRIDE;
   virtual bool SwitchToNextInputMethod() OVERRIDE;
-  virtual bool SwitchToPreviousInputMethod() OVERRIDE;
+  virtual bool SwitchToPreviousInputMethod(
+      const ui::Accelerator& accelerator) OVERRIDE;
   virtual bool SwitchInputMethod(const ui::Accelerator& accelerator) OVERRIDE;
   virtual InputMethodDescriptor GetCurrentInputMethod() const OVERRIDE;
   virtual InputMethodPropertyList
@@ -68,6 +73,7 @@
   virtual InputMethodUtil* GetInputMethodUtil() OVERRIDE;
   virtual ComponentExtensionIMEManager*
       GetComponentExtensionIMEManager() OVERRIDE;
+  virtual bool IsFullLatinKeyboard(const std::string& layout) const OVERRIDE;
 
   // Sets an input method ID which will be returned by GetCurrentInputMethod().
   void SetCurrentInputMethodId(const std::string& input_method_id) {
@@ -91,6 +97,9 @@
   InputMethodUtil util_;
   MockXKeyboard xkeyboard_;
 
+  // The active input method ids cache (actually default only)
+  std::vector<std::string> active_input_method_ids_;
+
   DISALLOW_COPY_AND_ASSIGN(MockInputMethodManager);
 };
 
diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc b/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc
index 7c451d2..7e254ab 100644
--- a/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc
+++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc
@@ -14,9 +14,7 @@
 
 namespace {
 
-const int kModifierMask = (ui::EF_CONTROL_DOWN |
-                           ui::EF_ALT_DOWN |
-                           ui::EF_SHIFT_DOWN);
+const int kModifierMask = ui::EF_SHIFT_DOWN;
 
 // Returns true if and only if it is on login screen (i.e. user is not logged
 // in) and the keyboard driven flag in the OEM manifest is on.
diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
index fb32552..c197400 100644
--- a/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
+++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
@@ -133,10 +133,8 @@
 }
 
 TEST_F(KeyboardDrivenEventRewriterTest, Rewrite) {
-  const int kModifierMask = (ui::EF_CONTROL_DOWN |
-                             ui::EF_ALT_DOWN |
-                             ui::EF_SHIFT_DOWN);
-  const unsigned int kXState = (ControlMask | Mod1Mask | ShiftMask);
+  const int kModifierMask = ui::EF_SHIFT_DOWN;
+  const unsigned int kXState = ShiftMask;
 
   struct {
     ui::KeyboardCode ui_keycode;
diff --git a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout_unittest.cc b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout_unittest.cc
index 6699856..e722eff 100644
--- a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout_unittest.cc
+++ b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout_unittest.cc
@@ -17,18 +17,14 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 namespace chromeos {
 
 class KioskModeIdleLogoutTest : public ash::test::AshTestBase {
  public:
   KioskModeIdleLogoutTest()
-      : ui_thread_(BrowserThread::UI, message_loop()),
-        idle_logout_(NULL) {
+      : idle_logout_(NULL) {
   }
 
   virtual void SetUp() OVERRIDE {
@@ -53,8 +49,6 @@
         idle_logout_);
   }
 
-  content::TestBrowserThread ui_thread_;
-
   ScopedDeviceSettingsTestHelper device_settings_test_helper_;
 
   KioskModeIdleLogout* idle_logout_;
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index c8f27b9..5604c22 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -115,7 +115,7 @@
  private:
   // ChromeBrowserMainExtraParts implementation.
   virtual void PreEarlyInitialization() OVERRIDE {
-    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                    content::NotificationService::AllSources());
     registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APPS_LOADED,
                    content::NotificationService::AllSources());
@@ -127,8 +127,8 @@
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE {
-    if (type == chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE) {
-      LOG(INFO) << "NOTIFICATION_LOGIN_WEBUI_VISIBLE";
+    if (type == chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE) {
+      LOG(INFO) << "NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE";
       SetupSigninScreen();
     } else if (type == chrome::NOTIFICATION_KIOSK_APPS_LOADED) {
       LOG(INFO) << "chrome::NOTIFICATION_KIOSK_APPS_LOADED";
@@ -282,7 +282,7 @@
  private:
   // ChromeBrowserMainExtraParts implementation.
   virtual void PreEarlyInitialization() OVERRIDE {
-    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                    content::NotificationService::AllSources());
     registrar_.Add(this, chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE,
                    content::NotificationService::AllSources());
@@ -298,8 +298,8 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE {
     switch (type) {
-      case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
-        LOG(INFO) << "NOTIFICATION_LOGIN_WEBUI_VISIBLE";
+      case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
+        LOG(INFO) << "NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE";
         SetupSigninScreen();
         content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>(
             chromeos::LoginDisplayHostImpl::default_host())->
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc
index 7a228aa..c1aa932 100644
--- a/chrome/browser/chromeos/login/login_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -96,7 +96,7 @@
 
   // ChromeBrowserMainExtraParts implementation.
   virtual void PreEarlyInitialization() OVERRIDE {
-    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                    content::NotificationService::AllSources());
   }
 
diff --git a/chrome/browser/chromeos/login/login_display_host_impl.cc b/chrome/browser/chromeos/login/login_display_host_impl.cc
index 96d92a4..dea6f11 100644
--- a/chrome/browser/chromeos/login/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/login_display_host_impl.cc
@@ -246,7 +246,7 @@
   // these notifications.
   if ((waiting_for_user_pods_ || waiting_for_wallpaper_load_)
       && initialize_webui_hidden_) {
-    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                    content::NotificationService::AllSources());
     registrar_.Add(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
                    content::NotificationService::AllSources());
@@ -558,7 +558,7 @@
     registrar_.Remove(this,
                       chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED,
                       content::NotificationService::AllSources());
-  } else if (chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE == type ||
+  } else if (chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE == type ||
              chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN == type) {
     LOG(WARNING) << "Login WebUI >> WEBUI_VISIBLE";
     if (waiting_for_user_pods_ && initialize_webui_hidden_) {
@@ -570,7 +570,7 @@
       ShowWebUI();
     }
     registrar_.Remove(this,
-                      chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+                      chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                       content::NotificationService::AllSources());
     registrar_.Remove(this,
                       chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
diff --git a/chrome/browser/chromeos/login/online_attempt_unittest.cc b/chrome/browser/chromeos/login/online_attempt_unittest.cc
index 5692686..24f6f17 100644
--- a/chrome/browser/chromeos/login/online_attempt_unittest.cc
+++ b/chrome/browser/chromeos/login/online_attempt_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/login/auth_attempt_state.h"
 #include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h"
@@ -15,7 +15,8 @@
 #include "chrome/browser/chromeos/login/test_attempt_state.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/mock_url_fetcher_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -33,23 +34,12 @@
 class OnlineAttemptTest : public testing::Test {
  public:
   OnlineAttemptTest()
-      : message_loop_(base::MessageLoop::TYPE_UI),
-        ui_thread_(BrowserThread::UI, &message_loop_),
-        state_(UserContext(), "", "", "", User::USER_TYPE_REGULAR, false),
-        resolver_(new MockAuthAttemptStateResolver) {
-  }
-
-  virtual ~OnlineAttemptTest() {}
-
-  virtual void SetUp() {
-    attempt_.reset(new OnlineAttempt(&state_, resolver_.get()));
-  }
-
-  virtual void TearDown() {
+      : state_(UserContext(), "", "", "", User::USER_TYPE_REGULAR, false),
+        attempt_(new OnlineAttempt(&state_, &resolver_)) {
   }
 
   void RunFailureTest(const GoogleServiceAuthError& error) {
-    EXPECT_CALL(*(resolver_.get()), Resolve())
+    EXPECT_CALL(resolver_, Resolve())
         .Times(1)
         .RetiresOnSaturation();
 
@@ -59,7 +49,7 @@
                    attempt_->weak_factory_.GetWeakPtr(),
                    error));
     // Force UI thread to finish tasks so I can verify |state_|.
-    message_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     EXPECT_TRUE(error == state_.online_outcome().error());
   }
 
@@ -70,19 +60,9 @@
                    auth->weak_factory_.GetWeakPtr()));
   }
 
-  static void Quit() {
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
-  }
-
-  static void RunThreadTest() {
-    base::MessageLoop::current()->RunUntilIdle();
-  }
-
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   TestAttemptState state_;
-  scoped_ptr<MockAuthAttemptStateResolver> resolver_;
+  MockAuthAttemptStateResolver resolver_;
   scoped_ptr<OnlineAttempt> attempt_;
 
   // Initializes / shuts down a stub NetworkLibrary.
@@ -90,7 +70,7 @@
 };
 
 TEST_F(OnlineAttemptTest, LoginSuccess) {
-  EXPECT_CALL(*(resolver_.get()), Resolve())
+  EXPECT_CALL(resolver_, Resolve())
       .Times(1)
       .RetiresOnSaturation();
 
@@ -100,15 +80,16 @@
                  attempt_->weak_factory_.GetWeakPtr(),
                  GaiaAuthConsumer::ClientLoginResult()));
   // Force UI thread to finish tasks so I can verify |state_|.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(OnlineAttemptTest, LoginCancelRetry) {
   GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
   TestingProfile profile;
 
-  EXPECT_CALL(*(resolver_.get()), Resolve())
-      .WillOnce(Invoke(OnlineAttemptTest::Quit))
+  base::RunLoop run_loop;
+  EXPECT_CALL(resolver_, Resolve())
+      .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
       .RetiresOnSaturation();
 
   // This is how we inject fake URLFetcher objects, with a factory.
@@ -117,11 +98,8 @@
   MockURLFetcherFactory<GotCanceledFetcher> factory;
 
   attempt_->Initiate(&profile);
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&OnlineAttemptTest::RunThreadTest));
 
-  base::MessageLoop::current()->Run();
+  run_loop.Run();
 
   EXPECT_TRUE(error == state_.online_outcome().error());
   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
@@ -132,8 +110,9 @@
   LoginFailure error(LoginFailure::LOGIN_TIMED_OUT);
   TestingProfile profile;
 
-  EXPECT_CALL(*(resolver_.get()), Resolve())
-      .WillOnce(Invoke(OnlineAttemptTest::Quit))
+  base::RunLoop run_loop;
+  EXPECT_CALL(resolver_, Resolve())
+      .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
       .RetiresOnSaturation();
 
   // This is how we inject fake URLFetcher objects, with a factory.
@@ -142,14 +121,11 @@
   MockURLFetcherFactory<ExpectCanceledFetcher> factory;
 
   attempt_->Initiate(&profile);
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&OnlineAttemptTest::RunThreadTest));
 
   // Post a task to cancel the login attempt.
   CancelLogin(attempt_.get());
 
-  base::MessageLoop::current()->Run();
+  run_loop.Run();
 
   EXPECT_EQ(LoginFailure::LOGIN_TIMED_OUT, state_.online_outcome().reason());
 }
@@ -161,8 +137,9 @@
               GoogleServiceAuthError::HOSTED_NOT_ALLOWED)));
   TestingProfile profile;
 
-  EXPECT_CALL(*(resolver_.get()), Resolve())
-      .WillOnce(Invoke(OnlineAttemptTest::Quit))
+  base::RunLoop run_loop;
+  EXPECT_CALL(resolver_, Resolve())
+      .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
       .RetiresOnSaturation();
 
   // This is how we inject fake URLFetcher objects, with a factory.
@@ -170,13 +147,10 @@
 
   TestAttemptState local_state(UserContext(), "", "", "",
                                User::USER_TYPE_REGULAR, true);
-  attempt_.reset(new OnlineAttempt(&local_state, resolver_.get()));
+  attempt_.reset(new OnlineAttempt(&local_state, &resolver_));
   attempt_->Initiate(&profile);
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&OnlineAttemptTest::RunThreadTest));
 
-  base::MessageLoop::current()->Run();
+  run_loop.Run();
 
   EXPECT_EQ(error, local_state.online_outcome());
   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
@@ -186,8 +160,9 @@
 TEST_F(OnlineAttemptTest, FullLogin) {
   TestingProfile profile;
 
-  EXPECT_CALL(*(resolver_.get()), Resolve())
-      .WillOnce(Invoke(OnlineAttemptTest::Quit))
+  base::RunLoop run_loop;
+  EXPECT_CALL(resolver_, Resolve())
+      .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
       .RetiresOnSaturation();
 
   // This is how we inject fake URLFetcher objects, with a factory.
@@ -195,13 +170,10 @@
 
   TestAttemptState local_state(UserContext(), "", "", "",
                                User::USER_TYPE_REGULAR, true);
-  attempt_.reset(new OnlineAttempt(&local_state, resolver_.get()));
+  attempt_.reset(new OnlineAttempt(&local_state, &resolver_));
   attempt_->Initiate(&profile);
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&OnlineAttemptTest::RunThreadTest));
 
-  base::MessageLoop::current()->Run();
+  run_loop.Run();
 
   EXPECT_EQ(LoginFailure::LoginFailureNone(), local_state.online_outcome());
 }
@@ -241,7 +213,7 @@
 }
 
 TEST_F(OnlineAttemptTest, TwoFactorSuccess) {
-  EXPECT_CALL(*(resolver_.get()), Resolve())
+  EXPECT_CALL(resolver_, Resolve())
       .Times(1)
       .RetiresOnSaturation();
   GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR);
@@ -252,7 +224,7 @@
                  error));
 
   // Force UI thread to finish tasks so I can verify |state_|.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(GoogleServiceAuthError::AuthErrorNone() ==
               state_.online_outcome().error());
 }
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc
index 3ee0c8d..b07497d 100644
--- a/chrome/browser/chromeos/login/oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -47,7 +47,7 @@
 
   // ChromeBrowserMainExtraParts implementation.
   virtual void PreEarlyInitialization() OVERRIDE {
-    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                    content::NotificationService::AllSources());
     registrar_.Add(this, chrome::NOTIFICATION_SESSION_STARTED,
                    content::NotificationService::AllSources());
@@ -62,8 +62,8 @@
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE {
-    if (type == chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE) {
-      LOG(INFO) << "NOTIFICATION_LOGIN_WEBUI_VISIBLE";
+    if (type == chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE) {
+      LOG(INFO) << "NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE";
       webui_visible_ = true;
       if (browsing_data_removed_ && !signin_screen_shown_) {
         signin_screen_shown_ = true;
diff --git a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
index f0fd212..9875995 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
@@ -27,7 +27,7 @@
 #include "chromeos/cryptohome/mock_cryptohome_library.h"
 #include "chromeos/dbus/fake_cryptohome_client.h"
 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/mock_url_fetcher_factory.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_request_status.h"
@@ -36,13 +36,9 @@
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "url/gurl.h"
 
-using ::testing::AnyNumber;
-using ::testing::DoAll;
 using ::testing::Invoke;
 using ::testing::Return;
-using ::testing::SetArgPointee;
 using ::testing::_;
-using content::BrowserThread;
 
 namespace chromeos {
 
@@ -57,15 +53,10 @@
 class ParallelAuthenticatorTest : public testing::Test {
  public:
   ParallelAuthenticatorTest()
-      : message_loop_(base::MessageLoop::TYPE_UI),
-        ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_),
-        io_thread_(BrowserThread::IO),
-        username_("me@nowhere.org"),
+      : username_("me@nowhere.org"),
         password_("fakepass"),
+        hash_ascii_("0a010000000000a0" + std::string(16, '0')),
         user_manager_enabler_(new MockUserManager) {
-    hash_ascii_.assign("0a010000000000a0");
-    hash_ascii_.append(std::string(16, '0'));
   }
 
   virtual ~ParallelAuthenticatorTest() {
@@ -79,8 +70,6 @@
     mock_cryptohome_library_ .reset(new MockCryptohomeLibrary());
     CryptohomeLibrary::SetForTest(mock_cryptohome_library_.get());
 
-    io_thread_.Start();
-
     auth_ = new ParallelAuthenticator(&consumer_);
     state_.reset(new TestAttemptState(UserContext(username_,
                                                   password_,
@@ -177,7 +166,7 @@
 
   void RunResolve(ParallelAuthenticator* auth) {
     auth->Resolve();
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   void SetAttemptState(ParallelAuthenticator* auth, TestAttemptState* state) {
@@ -198,10 +187,7 @@
     auth_->set_online_attempt(new TestOnlineAttempt(state_.get(), auth_.get()));
   }
 
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   std::string username_;
   std::string password_;
@@ -390,7 +376,7 @@
       .RetiresOnSaturation();
 
   auth_->LoginOffTheRecord();
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, DriveGuestLoginButFail) {
@@ -405,7 +391,7 @@
       .RetiresOnSaturation();
 
   auth_->LoginOffTheRecord();
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, DriveRetailModeUserLogin) {
@@ -420,7 +406,7 @@
       .RetiresOnSaturation();
 
   auth_->LoginRetailMode();
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, DriveRetailModeLoginButFail) {
@@ -435,7 +421,7 @@
       .RetiresOnSaturation();
 
   auth_->LoginRetailMode();
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, DriveDataResync) {
@@ -464,7 +450,7 @@
   SetAttemptState(auth_.get(), state_.release());
 
   auth_->ResyncEncryptedData();
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, DriveResyncFail) {
@@ -480,7 +466,7 @@
   SetAttemptState(auth_.get(), state_.release());
 
   auth_->ResyncEncryptedData();
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, DriveRequestOldPassword) {
@@ -521,7 +507,7 @@
   SetAttemptState(auth_.get(), state_.release());
 
   auth_->RecoverEncryptedData(std::string());
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, DriveDataRecoverButFail) {
@@ -541,7 +527,7 @@
   SetAttemptState(auth_.get(), state_.release());
 
   auth_->RecoverEncryptedData(std::string());
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(ParallelAuthenticatorTest, ResolveNoMount) {
@@ -652,7 +638,7 @@
   auth_->AuthenticateToUnlock(UserContext(username_,
                                           std::string(),
                                           std::string()));
-  message_loop_.Run();
+  base::MessageLoop::current()->Run();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index 5dea61c..874e865 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -1126,13 +1126,14 @@
 
 void UserManagerImpl::GuestUserLoggedIn() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  WallpaperManager::Get()->SetInitialUserWallpaper(UserManager::kGuestUserName,
-                                                   false);
   active_user_ = User::CreateGuestUser();
   // TODO(nkostylev): Add support for passing guest session cryptohome
   // mount point. Legacy (--login-profile) value will be used for now.
   // http://crosbug.com/230859
   active_user_->SetStubImage(User::kInvalidImageIndex, false);
+  // Initializes wallpaper after active_user_ is set.
+  WallpaperManager::Get()->SetInitialUserWallpaper(UserManager::kGuestUserName,
+                                                   false);
 }
 
 void UserManagerImpl::RegularUserLoggedIn(const std::string& email,
@@ -1234,9 +1235,9 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(policy::IsKioskAppUser(username));
 
-  WallpaperManager::Get()->SetInitialUserWallpaper(username, false);
   active_user_ = User::CreateKioskAppUser(username);
   active_user_->SetStubImage(User::kInvalidImageIndex, false);
+  WallpaperManager::Get()->SetInitialUserWallpaper(username, false);
 
   // TODO(bartfab): Add KioskAppUsers to the users_ list and keep metadata like
   // the kiosk_app_id in these objects, removing the need to re-parse the
diff --git a/chrome/browser/chromeos/login/user_manager_unittest.cc b/chrome/browser/chromeos/login/user_manager_unittest.cc
index 5ae5ae6..c26a764 100644
--- a/chrome/browser/chromeos/login/user_manager_unittest.cc
+++ b/chrome/browser/chromeos/login/user_manager_unittest.cc
@@ -6,7 +6,6 @@
 #include <cstring>
 
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/testing_pref_service.h"
 #include "base/run_loop.h"
@@ -22,19 +21,13 @@
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
 
 class UserManagerTest : public testing::Test {
- public:
-  UserManagerTest()
-      : message_loop_(base::MessageLoop::TYPE_UI),
-        ui_thread_(content::BrowserThread::UI, &message_loop_),
-        file_thread_(content::BrowserThread::FILE, &message_loop_) {
-  }
-
+ protected:
   virtual void SetUp() OVERRIDE {
     cros_settings_ = CrosSettings::Get();
 
@@ -126,9 +119,7 @@
   }
 
  protected:
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   CrosSettings* cros_settings_;
   CrosSettingsProvider* device_settings_provider_;
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.cc b/chrome/browser/chromeos/login/wallpaper_manager.cc
index 8957ecc..854a529 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.cc
+++ b/chrome/browser/chromeos/login/wallpaper_manager.cc
@@ -129,7 +129,7 @@
                  chrome::NOTIFICATION_LOGIN_USER_CHANGED,
                  content::NotificationService::AllSources());
   registrar_.Add(this,
-                 chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+                 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                  content::NotificationService::AllSources());
   registrar_.Add(this,
                  chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED,
@@ -267,6 +267,14 @@
     return;
   }
 
+  if (CommandLine::ForCurrentProcess()->
+          HasSwitch(chromeos::switches::kGuestSession)) {
+    // Guest wallpaper should be initialized when guest login.
+    // Note: This maybe called before login. So IsLoggedInAsGuest can not be
+    // used here to determine if current user is guest.
+    return;
+  }
+
   if (!user_manager->IsUserLoggedIn()) {
     if (!StartupUtils::IsDeviceRegistered())
       SetDefaultWallpaper();
@@ -286,7 +294,7 @@
       ClearWallpaperCache();
       break;
     }
-    case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
+    case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
       if (!CommandLine::ForCurrentProcess()->
           HasSwitch(switches::kDisableBootAnimation)) {
         BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/login/webui_login_view.cc b/chrome/browser/chromeos/login/webui_login_view.cc
index 1c3b509..590a943 100644
--- a/chrome/browser/chromeos/login/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/webui_login_view.cc
@@ -150,7 +150,7 @@
       should_emit_login_prompt_visible_(true),
       forward_keyboard_event_(true) {
   registrar_.Add(this,
-                 chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+                 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                  content::NotificationService::AllSources());
   registrar_.Add(this,
                  chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
@@ -372,7 +372,7 @@
                              const content::NotificationSource& source,
                              const content::NotificationDetails& details) {
   switch (type) {
-    case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE:
+    case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE:
     case chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN: {
       OnLoginPromptVisible();
       registrar_.RemoveAll();
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
index 2b6b410..320ee4a 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
@@ -5,7 +5,7 @@
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "chrome/browser/captive_portal/captive_portal_detector.h"
 #include "chrome/browser/captive_portal/testing_utils.h"
 #include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
@@ -15,6 +15,7 @@
 #include "chromeos/dbus/shill_service_client.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "dbus/object_path.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -40,10 +41,7 @@
 class NetworkPortalDetectorImplTest
     : public testing::Test,
       public captive_portal::CaptivePortalDetectorTestBase {
- public:
-  NetworkPortalDetectorImplTest() {}
-  virtual ~NetworkPortalDetectorImplTest() {}
-
+ protected:
   virtual void SetUp() {
     DBusThreadManager::InitializeWithStub();
     SetupNetworkHandler();
@@ -170,13 +168,13 @@
         dbus::ObjectPath(service_path),
         flimflam::kStateProperty, base::StringValue(flimflam::kStatePortal),
         base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   void SetNetworkDeviceEnabled(const std::string& type, bool enabled) {
     NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
         type, enabled, network_handler::ErrorCallback());
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   void SetConnected(const std::string& service_path) {
@@ -184,12 +182,12 @@
         dbus::ObjectPath(service_path),
         flimflam::kStateProperty, base::StringValue(flimflam::kStateOnline),
         base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
  private:
   void SetupDefaultShillState() {
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     ShillServiceClient::TestInterface* service_test =
         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
     service_test->ClearServices();
@@ -218,7 +216,7 @@
     NetworkHandler::Initialize();
   }
 
-  base::MessageLoop message_loop_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
   scoped_ptr<NetworkPortalDetectorImpl> network_portal_detector_;
 };
@@ -381,7 +379,7 @@
   ASSERT_EQ(0, attempt_count());
 
   SetConnected(kStubWireless1);
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // First portal detection timeouts, next portal detection is
   // scheduled.
@@ -444,7 +442,7 @@
   ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::OK, 204, NULL);
   ASSERT_TRUE(is_state_idle());
@@ -470,7 +468,7 @@
   ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::OK, 503, retry_after);
   ASSERT_TRUE(is_state_portal_detection_pending());
@@ -478,7 +476,7 @@
   ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::OK, 503, retry_after);
   ASSERT_TRUE(is_state_idle());
@@ -499,7 +497,7 @@
                    kStubWireless1);
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::OK, 407, NULL);
   ASSERT_EQ(2, attempt_count());
@@ -508,7 +506,7 @@
                    kStubWireless1);
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::OK, 407, NULL);
   ASSERT_EQ(3, attempt_count());
@@ -532,7 +530,7 @@
   ASSERT_TRUE(is_state_portal_detection_pending());
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::ERR_CONNECTION_CLOSED,
                    net::URLFetcher::RESPONSE_CODE_INVALID,
@@ -541,7 +539,7 @@
   ASSERT_TRUE(is_state_portal_detection_pending());
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::ERR_CONNECTION_CLOSED,
                    net::URLFetcher::RESPONSE_CODE_INVALID,
@@ -581,7 +579,7 @@
       kStubWireless1);
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::OK, 204, NULL);
 
@@ -592,7 +590,7 @@
       kStubWireless1);
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   disable_lazy_detection();
 
@@ -623,7 +621,7 @@
                    kStubWireless1);
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::ERR_CONNECTION_CLOSED,
                    net::URLFetcher::RESPONSE_CODE_INVALID,
@@ -634,7 +632,7 @@
                    kStubWireless1);
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   CompleteURLFetch(net::OK, 200, NULL);
   ASSERT_EQ(3, attempt_count());
@@ -643,7 +641,7 @@
                    kStubWireless1);
 
   // To run CaptivePortalDetector::DetectCaptivePortal().
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   disable_lazy_detection();
 
@@ -693,7 +691,7 @@
   ASSERT_TRUE(is_state_portal_detection_pending());
   ASSERT_FALSE(start_detection_if_idle());
 
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(is_state_checking_for_portal());
   CompleteURLFetch(net::OK, 200, NULL);
 
@@ -716,13 +714,13 @@
 
   // Second portal detection attempt for cellular1 uses 10sec timeout.
   ASSERT_TRUE(is_state_portal_detection_pending());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   CheckRequestTimeoutAndCompleteAttempt(2, 10, net::ERR_CONNECTION_CLOSED,
                                         net::URLFetcher::RESPONSE_CODE_INVALID);
 
   // Third portal detection attempt for cellular1 uses 15sec timeout.
   ASSERT_TRUE(is_state_portal_detection_pending());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   CheckRequestTimeoutAndCompleteAttempt(3, 15, net::ERR_CONNECTION_CLOSED,
                                         net::URLFetcher::RESPONSE_CODE_INVALID);
 
@@ -731,7 +729,7 @@
   // Check that in lazy detection for cellular1 15sec timeout is used.
   enable_lazy_detection();
   ASSERT_TRUE(is_state_portal_detection_pending());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   disable_lazy_detection();
   CheckRequestTimeoutAndCompleteAttempt(3, 15, net::ERR_CONNECTION_CLOSED,
                                         net::URLFetcher::RESPONSE_CODE_INVALID);
@@ -746,14 +744,14 @@
 
   // Second portal detection attempt for wifi1 also uses 5sec timeout.
   ASSERT_TRUE(is_state_portal_detection_pending());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   CheckRequestTimeoutAndCompleteAttempt(2, 10, net::OK, 204);
   ASSERT_TRUE(is_state_idle());
 
   // Check that in lazy detection for wifi1 5sec timeout is used.
   enable_lazy_detection();
   ASSERT_TRUE(is_state_portal_detection_pending());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   disable_lazy_detection();
   CheckRequestTimeoutAndCompleteAttempt(3, 15, net::OK, 204);
   ASSERT_TRUE(is_state_idle());
@@ -768,13 +766,13 @@
   CheckRequestTimeoutAndCompleteAttempt(1, 5, net::ERR_CONNECTION_CLOSED,
                                         net::URLFetcher::RESPONSE_CODE_INVALID);
   ASSERT_TRUE(is_state_portal_detection_pending());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Second portal detection attempt for wifi1 uses 10sec timeout.
   CheckRequestTimeoutAndCompleteAttempt(2, 10, net::ERR_CONNECTION_CLOSED,
                                         net::URLFetcher::RESPONSE_CODE_INVALID);
   ASSERT_TRUE(is_state_portal_detection_pending());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Second portal detection attempt for wifi1 uses 15sec timeout.
   CheckRequestTimeoutAndCompleteAttempt(3, 15, net::ERR_CONNECTION_CLOSED,
@@ -785,7 +783,7 @@
   ASSERT_TRUE(is_state_portal_detection_pending());
 
   // First portal detection attempt for wifi1 uses 5sec timeout.
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   CheckRequestTimeoutAndCompleteAttempt(1, 5, net::OK, 204);
   ASSERT_TRUE(is_state_idle());
 }
diff --git a/chrome/browser/chromeos/net/onc_utils.cc b/chrome/browser/chromeos/net/onc_utils.cc
index f897272..80ec98c 100644
--- a/chrome/browser/chromeos/net/onc_utils.cc
+++ b/chrome/browser/chromeos/net/onc_utils.cc
@@ -170,7 +170,11 @@
     const std::string& hashed_username,
     base::ListValue* network_configs) {
   const chromeos::User* user = GetLoggedInUserByHash(hashed_username);
-  DCHECK(user);
+  if (!user) {
+    // In tests no user may be logged in. It's not harmful if we just don't
+    // expand the strings.
+    return;
+  }
   UserStringSubstitution substitution(user);
   chromeos::onc::ExpandStringsInNetworks(substitution, network_configs);
 }
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index 8de2ba7..b52eccb 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -11,6 +11,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/network_property_ui_data.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
+#include "chrome/browser/chromeos/login/user.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/options/vpn_config_view.h"
 #include "chrome/browser/chromeos/options/wifi_config_view.h"
 #include "chrome/browser/chromeos/options/wimax_config_view.h"
@@ -19,6 +21,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
+#include "chromeos/network/managed_network_configuration_handler.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
@@ -290,8 +293,11 @@
 const base::DictionaryValue* NetworkConfigView::FindPolicyForActiveUser(
     const Network* network,
     onc::ONCSource* onc_source) {
-  *onc_source = network->ui_data().onc_source();
-  return NetworkLibrary::Get()->FindOncForNetwork(network->unique_id());
+  const User* user = UserManager::Get()->GetActiveUser();
+  std::string username_hash = user ? user->username_hash() : std::string();
+  std::string guid = network->unique_id();
+  return NetworkHandler::Get()->managed_network_configuration_handler()
+      ->FindPolicyByGUID(username_hash, guid, onc_source);
 }
 
 void ControlledSettingIndicatorView::Layout() {
diff --git a/chrome/browser/chromeos/policy/power_policy_browsertest.cc b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
index 37a0ca1..842321f 100644
--- a/chrome/browser/chromeos/policy/power_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
@@ -261,7 +261,7 @@
 
   // Wait for the login screen to be shown.
   content::WindowedNotificationObserver(
-      chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+      chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
       content::NotificationService::AllSources()).Wait();
 }
 
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
index 53c3c82..7c3d9df 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
@@ -33,7 +33,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/url_request/test_url_fetcher_factory.h"
@@ -75,9 +75,7 @@
 class UserCloudPolicyManagerChromeOSTest : public testing::Test {
  protected:
   UserCloudPolicyManagerChromeOSTest()
-      : ui_thread_(content::BrowserThread::UI, &loop_),
-        io_thread_(content::BrowserThread::IO, &loop_),
-        store_(NULL),
+      : store_(NULL),
         profile_(NULL),
         signin_profile_(NULL) {}
 
@@ -90,14 +88,13 @@
     profile_ = profile_manager_->CreateTestingProfile(
         chrome::kInitialProfile, scoped_ptr<PrefServiceSyncable>(),
         UTF8ToUTF16("testing_profile"), 0);
-    signin_profile_ = profile_manager_->CreateTestingProfile("signin_profile");
+    signin_profile_ = profile_manager_->CreateTestingProfile(kSigninProfile);
     signin_profile_->set_incognito(true);
     // Usually the signin Profile and the main Profile are separate, but since
     // the signin Profile is an OTR Profile then for this test it suffices to
     // attach it to the main Profile.
     profile_->SetOffTheRecordProfile(signin_profile_);
     signin_profile_->SetOriginalProfile(profile_);
-    signin_profile_->CreateRequestContext();
     ASSERT_EQ(signin_profile_, chromeos::ProfileHelper::GetSigninProfile());
 
     chrome::RegisterLocalState(prefs_.registry());
@@ -136,7 +133,10 @@
       manager_->RemoveObserver(&observer_);
       manager_->Shutdown();
     }
-    signin_profile_->ResetRequestContext();
+    signin_profile_ = NULL;
+    profile_ = NULL;
+    profile_manager_->DeleteTestingProfile(kSigninProfile);
+    profile_manager_->DeleteTestingProfile(chrome::kInitialProfile);
   }
 
   void CreateManager(bool wait_for_fetch) {
@@ -265,11 +265,9 @@
     EXPECT_TRUE(manager_->policies().Equals(expected_bundle_));
   }
 
-  // Required by the refresh scheduler that's created by the manager.
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
-  // Required to cleanup the URLRequestContextGetter of the |signin_profile_|.
-  content::TestBrowserThread io_thread_;
+  // Required by the refresh scheduler that's created by the manager and
+  // for the cleanup of URLRequestContextGetter in the |signin_profile_|.
+  content::TestBrowserThreadBundle thread_bundle_;
 
   // Convenience policy objects.
   em::PolicyData policy_data_;
@@ -292,10 +290,15 @@
   TestingProfile* profile_;
   TestingProfile* signin_profile_;
 
+  static const char kSigninProfile[];
+
  private:
   DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyManagerChromeOSTest);
 };
 
+const char UserCloudPolicyManagerChromeOSTest::kSigninProfile[] =
+    "signin_profile";
+
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFirstFetch) {
   // Tests the initialization of a manager whose Profile is waiting for the
   // initial fetch, when the policy cache is empty.
diff --git a/chrome/browser/chromeos/power/power_prefs.cc b/chrome/browser/chromeos/power/power_prefs.cc
index c2081bb..c05f074 100644
--- a/chrome/browser/chromeos/power/power_prefs.cc
+++ b/chrome/browser/chromeos/power/power_prefs.cc
@@ -28,7 +28,7 @@
     : power_policy_controller_(power_policy_controller),
       profile_(NULL) {
   notification_registrar_.Add(this,
-                              chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+                              chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                               content::NotificationService::AllSources());
   notification_registrar_.Add(this,
                               chrome::NOTIFICATION_SESSION_STARTED,
@@ -75,7 +75,7 @@
                          const content::NotificationSource& source,
                          const content::NotificationDetails& details) {
   switch (type) {
-    case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
+    case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
       // Update |profile_| when entering the login screen.
       ProfileManager* profile_manager = g_browser_process->profile_manager();
       if (!profile_manager || !profile_manager->IsLoggedIn())
diff --git a/chrome/browser/chromeos/power/power_prefs_unittest.cc b/chrome/browser/chromeos/power/power_prefs_unittest.cc
index e5cd2d3..6b3cd2d 100644
--- a/chrome/browser/chromeos/power/power_prefs_unittest.cc
+++ b/chrome/browser/chromeos/power/power_prefs_unittest.cc
@@ -165,7 +165,7 @@
   login_profile->set_incognito(true);
 
   // Inform power_prefs_ that the login screen is being shown.
-  power_prefs_->Observe(chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+  power_prefs_->Observe(chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                         content::Source<PowerPrefsTest>(this),
                         content::NotificationService::NoDetails());
 
@@ -236,7 +236,7 @@
             GetCurrentAllowScreenWakeLocks());
 
   // Simulate the login screen coming up as part of screen locking.
-  power_prefs_->Observe(chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+  power_prefs_->Observe(chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                         content::Source<PowerPrefsTest>(this),
                         content::NotificationService::NoDetails());
 
diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
index 8c2fdb4..a7f7ed9 100644
--- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
+++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
@@ -785,13 +785,12 @@
       ShowNetworkSettings(network_id);
   }
 
-  virtual void AddBluetoothDevice() OVERRIDE {
-    // Open the Bluetooth device dialog, which automatically starts the
-    // discovery process.
+  virtual void ManageBluetoothDevices() OVERRIDE {
     content::RecordAction(
-        content::UserMetricsAction("OpenAddBluetoothDeviceDialog"));
-    chrome::ShowSettingsSubPage(GetAppropriateBrowser(),
-                                chrome::kBluetoothAddDeviceSubPage);
+        content::UserMetricsAction("ShowBluetoothSettingsPage"));
+    std::string sub_page = std::string(chrome::kSearchSubPage) + "#" +
+        l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH);
+    chrome::ShowSettingsSubPage(GetAppropriateBrowser(), sub_page);
   }
 
   virtual void ToggleBluetooth() OVERRIDE {
diff --git a/chrome/browser/geolocation/geolocation_infobar_queue_controller.cc b/chrome/browser/content_settings/permission_queue_controller.cc
similarity index 78%
rename from chrome/browser/geolocation/geolocation_infobar_queue_controller.cc
rename to chrome/browser/content_settings/permission_queue_controller.cc
index 69eb13e..84a5592 100644
--- a/chrome/browser/geolocation/geolocation_infobar_queue_controller.cc
+++ b/chrome/browser/content_settings/permission_queue_controller.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 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/geolocation/geolocation_infobar_queue_controller.h"
+#include "chrome/browser/content_settings/permission_queue_controller.h"
 
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -21,11 +21,9 @@
 #include "content/public/browser/web_contents.h"
 
 
-// Utilities ------------------------------------------------------------------
-
 namespace {
 
-InfoBarService* GetInfoBarService(const GeolocationPermissionRequestID& id) {
+InfoBarService* GetInfoBarService(const PermissionRequestID& id) {
   content::WebContents* web_contents =
       tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id());
   return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL;
@@ -34,11 +32,9 @@
 }
 
 
-// GeolocationInfoBarQueueController::PendingInfoBarRequest -------------------
-
-class GeolocationInfoBarQueueController::PendingInfoBarRequest {
+class PermissionQueueController::PendingInfoBarRequest {
  public:
-  PendingInfoBarRequest(const GeolocationPermissionRequestID& id,
+  PendingInfoBarRequest(const PermissionRequestID& id,
                         const GURL& requesting_frame,
                         const GURL& embedder,
                         PermissionDecidedCallback callback);
@@ -47,17 +43,17 @@
   bool IsForPair(const GURL& requesting_frame,
                  const GURL& embedder) const;
 
-  const GeolocationPermissionRequestID& id() const { return id_; }
+  const PermissionRequestID& id() const { return id_; }
   const GURL& requesting_frame() const { return requesting_frame_; }
   bool has_infobar() const { return !!infobar_; }
   InfoBarDelegate* infobar() { return infobar_; }
 
   void RunCallback(bool allowed);
-  void CreateInfoBar(GeolocationInfoBarQueueController* controller,
+  void CreateInfoBar(PermissionQueueController* controller,
                      const std::string& display_languages);
 
  private:
-  GeolocationPermissionRequestID id_;
+  PermissionRequestID id_;
   GURL requesting_frame_;
   GURL embedder_;
   PermissionDecidedCallback callback_;
@@ -66,8 +62,8 @@
   // Purposefully do not disable copying, as this is stored in STL containers.
 };
 
-GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest(
-    const GeolocationPermissionRequestID& id,
+PermissionQueueController::PendingInfoBarRequest::PendingInfoBarRequest(
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
     PermissionDecidedCallback callback)
@@ -78,42 +74,41 @@
       infobar_(NULL) {
 }
 
-GeolocationInfoBarQueueController::PendingInfoBarRequest::
-    ~PendingInfoBarRequest() {
+PermissionQueueController::PendingInfoBarRequest::~PendingInfoBarRequest() {
 }
 
-bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForPair(
+bool PermissionQueueController::PendingInfoBarRequest::IsForPair(
     const GURL& requesting_frame,
     const GURL& embedder) const {
   return (requesting_frame_ == requesting_frame) && (embedder_ == embedder);
 }
 
-void GeolocationInfoBarQueueController::PendingInfoBarRequest::RunCallback(
+void PermissionQueueController::PendingInfoBarRequest::RunCallback(
     bool allowed) {
   callback_.Run(allowed);
 }
 
-void GeolocationInfoBarQueueController::PendingInfoBarRequest::
-    CreateInfoBar(GeolocationInfoBarQueueController* controller,
-                  const std::string& display_languages) {
+void PermissionQueueController::PendingInfoBarRequest::CreateInfoBar(
+    PermissionQueueController* controller,
+    const std::string& display_languages) {
+  // TODO(toyoshim): Remove following dependency on geolocation.
   infobar_ = GeolocationInfoBarDelegate::Create(
       GetInfoBarService(id_), controller, id_, requesting_frame_,
       display_languages);
 }
 
 
-// GeolocationInfoBarQueueController ------------------------------------------
-
-GeolocationInfoBarQueueController::GeolocationInfoBarQueueController(
-    Profile* profile)
-    : profile_(profile) {
+PermissionQueueController::PermissionQueueController(
+    Profile* profile, ContentSettingsType type)
+    : profile_(profile),
+      type_(type) {
 }
 
-GeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() {
+PermissionQueueController::~PermissionQueueController() {
 }
 
-void GeolocationInfoBarQueueController::CreateInfoBarRequest(
-    const GeolocationPermissionRequestID& id,
+void PermissionQueueController::CreateInfoBarRequest(
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
     PermissionDecidedCallback callback) {
@@ -131,8 +126,8 @@
     ShowQueuedInfoBarForTab(id);
 }
 
-void GeolocationInfoBarQueueController::CancelInfoBarRequest(
-    const GeolocationPermissionRequestID& id) {
+void PermissionQueueController::CancelInfoBarRequest(
+    const PermissionRequestID& id) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
   for (PendingInfoBarRequests::iterator i(pending_infobar_requests_.begin());
@@ -147,8 +142,8 @@
   }
 }
 
-void GeolocationInfoBarQueueController::OnPermissionSet(
-    const GeolocationPermissionRequestID& id,
+void PermissionQueueController::OnPermissionSet(
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
     bool update_content_setting,
@@ -197,7 +192,7 @@
     i->RunCallback(allowed);
 }
 
-void GeolocationInfoBarQueueController::Observe(
+void PermissionQueueController::Observe(
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
@@ -216,7 +211,7 @@
   for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
        i != pending_infobar_requests_.end(); ++i) {
     if (i->infobar() == infobar) {
-      GeolocationPermissionRequestID id(i->id());
+      PermissionRequestID id(i->id());
       pending_infobar_requests_.erase(i);
       ShowQueuedInfoBarForTab(id);
       return;
@@ -224,8 +219,8 @@
   }
 }
 
-bool GeolocationInfoBarQueueController::AlreadyShowingInfoBarForTab(
-    const GeolocationPermissionRequestID& id) const {
+bool PermissionQueueController::AlreadyShowingInfoBarForTab(
+    const PermissionRequestID& id) const {
   for (PendingInfoBarRequests::const_iterator i(
            pending_infobar_requests_.begin());
        i != pending_infobar_requests_.end(); ++i) {
@@ -235,8 +230,8 @@
   return false;
 }
 
-void GeolocationInfoBarQueueController::ShowQueuedInfoBarForTab(
-    const GeolocationPermissionRequestID& id) {
+void PermissionQueueController::ShowQueuedInfoBarForTab(
+    const PermissionRequestID& id) {
   DCHECK(!AlreadyShowingInfoBarForTab(id));
 
   InfoBarService* infobar_service = GetInfoBarService(id);
@@ -264,8 +259,8 @@
   UnregisterForInfoBarNotifications(infobar_service);
 }
 
-void GeolocationInfoBarQueueController::ClearPendingInfoBarRequestsForTab(
-    const GeolocationPermissionRequestID& id) {
+void PermissionQueueController::ClearPendingInfoBarRequestsForTab(
+    const PermissionRequestID& id) {
   for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
        i != pending_infobar_requests_.end(); ) {
     if (i->id().IsForSameTabAs(id)) {
@@ -277,7 +272,7 @@
   }
 }
 
-void GeolocationInfoBarQueueController::RegisterForInfoBarNotifications(
+void PermissionQueueController::RegisterForInfoBarNotifications(
     InfoBarService* infobar_service) {
   if (!registrar_.IsRegistered(
       this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
@@ -288,7 +283,7 @@
   }
 }
 
-void GeolocationInfoBarQueueController::UnregisterForInfoBarNotifications(
+void PermissionQueueController::UnregisterForInfoBarNotifications(
     InfoBarService* infobar_service) {
   if (registrar_.IsRegistered(
       this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
@@ -299,7 +294,7 @@
   }
 }
 
-void GeolocationInfoBarQueueController::UpdateContentSetting(
+void PermissionQueueController::UpdateContentSetting(
     const GURL& requesting_frame,
     const GURL& embedder,
     bool allowed) {
@@ -315,7 +310,7 @@
   profile_->GetHostContentSettingsMap()->SetContentSetting(
       ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()),
       ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()),
-      CONTENT_SETTINGS_TYPE_GEOLOCATION,
+      type_,
       std::string(),
       content_setting);
 }
diff --git a/chrome/browser/geolocation/geolocation_infobar_queue_controller.h b/chrome/browser/content_settings/permission_queue_controller.h
similarity index 69%
rename from chrome/browser/geolocation/geolocation_infobar_queue_controller.h
rename to chrome/browser/content_settings/permission_queue_controller.h
index cc87cba..3da215b 100644
--- a/chrome/browser/geolocation/geolocation_infobar_queue_controller.h
+++ b/chrome/browser/content_settings/permission_queue_controller.h
@@ -1,48 +1,49 @@
-// Copyright (c) 2012 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_GEOLOCATION_GEOLOCATION_INFOBAR_QUEUE_CONTROLLER_H_
-#define CHROME_BROWSER_GEOLOCATION_GEOLOCATION_INFOBAR_QUEUE_CONTROLLER_H_
+#ifndef CHROME_BROWSER_CONTENT_SETTINGS_PERMISSION_QUEUE_CONTROLLER_H_
+#define CHROME_BROWSER_CONTENT_SETTINGS_PERMISSION_QUEUE_CONTROLLER_H_
 
 #include "base/bind.h"
+#include "chrome/common/content_settings_types.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
 class GURL;
-class GeolocationPermissionRequestID;
+class PermissionRequestID;
 class InfoBarService;
 class Profile;
 
-// This class controls the geolocation infobar queue per profile, and it's
-// used by GeolocationPermissionContext.
+// This class controls an infobar queue per profile, and it's used by
+// GeolocationPermissionContext, and so on.
 // An alternate approach would be to have this queue per tab, and use
 // notifications to broadcast when permission is set / listen to notification to
 // cancel pending requests. This may be specially useful if there are other
 // things listening for such notifications.
 // For the time being this class is self-contained and it doesn't seem pulling
 // the notification infrastructure would simplify.
-class GeolocationInfoBarQueueController : content::NotificationObserver {
+class PermissionQueueController : content::NotificationObserver {
  public:
   typedef base::Callback<void(bool /* allowed */)> PermissionDecidedCallback;
 
-  explicit GeolocationInfoBarQueueController(Profile* profile);
-  virtual ~GeolocationInfoBarQueueController();
+  PermissionQueueController(Profile* profile, ContentSettingsType type);
+  virtual ~PermissionQueueController();
 
   // The InfoBar will be displayed immediately if the tab is not already
   // displaying one, otherwise it'll be queued.
-  void CreateInfoBarRequest(const GeolocationPermissionRequestID& id,
+  void CreateInfoBarRequest(const PermissionRequestID& id,
                             const GURL& requesting_frame,
                             const GURL& embedder,
                             PermissionDecidedCallback callback);
 
   // Cancels a specific infobar request.
-  void CancelInfoBarRequest(const GeolocationPermissionRequestID& id);
+  void CancelInfoBarRequest(const PermissionRequestID& id);
 
   // Called by the InfoBarDelegate to notify permission has been set.
   // It'll notify and dismiss any other pending InfoBar request for the same
   // |requesting_frame| and embedder.
-  void OnPermissionSet(const GeolocationPermissionRequestID& id,
+  void OnPermissionSet(const PermissionRequestID& id,
                        const GURL& requesting_frame,
                        const GURL& embedder,
                        bool update_content_setting,
@@ -62,18 +63,16 @@
 
   // Returns true if a geolocation infobar is already visible for the tab
   // corresponding to |id|.
-  bool AlreadyShowingInfoBarForTab(
-      const GeolocationPermissionRequestID& id) const;
+  bool AlreadyShowingInfoBarForTab(const PermissionRequestID& id) const;
 
   // Shows the next pending infobar for the tab corresponding to |id|, if any.
   // Note that this may not be the pending request whose ID is |id| if other
   // requests are higher in the queue.  If we can't show infobars because there
   // is no InfoBarService for this tab, removes all queued requests for this
   // tab.
-  void ShowQueuedInfoBarForTab(const GeolocationPermissionRequestID& id);
+  void ShowQueuedInfoBarForTab(const PermissionRequestID& id);
 
-  void ClearPendingInfoBarRequestsForTab(
-      const GeolocationPermissionRequestID& id);
+  void ClearPendingInfoBarRequestsForTab(const PermissionRequestID& id);
 
   void RegisterForInfoBarNotifications(InfoBarService* infobar_service);
   void UnregisterForInfoBarNotifications(InfoBarService* infobar_service);
@@ -84,9 +83,10 @@
   content::NotificationRegistrar registrar_;
 
   Profile* const profile_;
+  ContentSettingsType type_;
   PendingInfoBarRequests pending_infobar_requests_;
 
-  DISALLOW_COPY_AND_ASSIGN(GeolocationInfoBarQueueController);
+  DISALLOW_COPY_AND_ASSIGN(PermissionQueueController);
 };
 
-#endif  // CHROME_BROWSER_GEOLOCATION_GEOLOCATION_INFOBAR_QUEUE_CONTROLLER_H_
+#endif  // CHROME_BROWSER_CONTENT_SETTINGS_PERMISSION_QUEUE_CONTROLLER_H_
diff --git a/chrome/browser/geolocation/geolocation_infobar_queue_controller_unittest.cc b/chrome/browser/content_settings/permission_queue_controller_unittest.cc
similarity index 77%
rename from chrome/browser/geolocation/geolocation_infobar_queue_controller_unittest.cc
rename to chrome/browser/content_settings/permission_queue_controller_unittest.cc
index 10f563c..8ff0a21 100644
--- a/chrome/browser/geolocation/geolocation_infobar_queue_controller_unittest.cc
+++ b/chrome/browser/content_settings/permission_queue_controller_unittest.cc
@@ -1,12 +1,13 @@
-// Copyright (c) 2012 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/geolocation/geolocation_infobar_queue_controller.h"
+#include "chrome/browser/content_settings/permission_queue_controller.h"
 
 #include "base/synchronization/waitable_event.h"
-#include "chrome/browser/geolocation/geolocation_permission_request_id.h"
+#include "chrome/browser/content_settings/permission_request_id.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/common/content_settings_types.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/web_contents.h"
@@ -14,24 +15,22 @@
 #include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-class GeolocationInfoBarQueueControllerTests
-    : public ChromeRenderViewHostTestHarness {
+class PermissionQueueControllerTests : public ChromeRenderViewHostTestHarness {
  protected:
   virtual void SetUp() OVERRIDE {
     ChromeRenderViewHostTestHarness::SetUp();
     InfoBarService::CreateForWebContents(web_contents());
   }
 
-  GeolocationPermissionRequestID RequestID(int bridge_id) {
-    return GeolocationPermissionRequestID(
+  PermissionRequestID RequestID(int bridge_id) {
+    return PermissionRequestID(
         web_contents()->GetRenderProcessHost()->GetID(),
         web_contents()->GetRenderViewHost()->GetRoutingID(),
         bridge_id);
   }
 };
 
-class ObservationCountingQueueController :
-    public GeolocationInfoBarQueueController {
+class ObservationCountingQueueController : public PermissionQueueController {
  public:
   explicit ObservationCountingQueueController(Profile* profile);
 
@@ -40,12 +39,12 @@
  private:
   int call_count_;
 
-  // GeolocationInfoBarQueueController
+  // PermissionQueueController
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  static void NotifyPermissionSet(const GeolocationPermissionRequestID& id,
+  static void NotifyPermissionSet(const PermissionRequestID& id,
                                   const GURL& requesting_frame,
                                   base::Callback<void(bool)> callback,
                                   bool allowed);
@@ -53,8 +52,7 @@
 
 ObservationCountingQueueController::ObservationCountingQueueController(
     Profile* profile)
-    : GeolocationInfoBarQueueController(
-          profile),
+    : PermissionQueueController(profile, CONTENT_SETTINGS_TYPE_GEOLOCATION),
       call_count_(0) {
 }
 
@@ -63,18 +61,18 @@
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
   ++call_count_;
-  GeolocationInfoBarQueueController::Observe(type, source, details);
+  PermissionQueueController::Observe(type, source, details);
 }
 
 void ObservationCountingQueueController::NotifyPermissionSet(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     base::Callback<void(bool)> callback,
     bool allowed) {
 }
 
 
-TEST_F(GeolocationInfoBarQueueControllerTests,
+TEST_F(PermissionQueueControllerTests,
        OneObservationPerInfoBarCancelled) {
   // When an infobar is cancelled, the infobar helper sends a notification to
   // the controller. If the controller has another infobar queued, it should
diff --git a/chrome/browser/content_settings/permission_request_id.cc b/chrome/browser/content_settings/permission_request_id.cc
new file mode 100644
index 0000000..ec47459
--- /dev/null
+++ b/chrome/browser/content_settings/permission_request_id.cc
@@ -0,0 +1,34 @@
+// 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/content_settings/permission_request_id.h"
+
+#include "base/strings/stringprintf.h"
+
+
+PermissionRequestID::PermissionRequestID(int render_process_id,
+                                         int render_view_id,
+                                         int bridge_id)
+    : render_process_id_(render_process_id),
+      render_view_id_(render_view_id),
+      bridge_id_(bridge_id) {
+}
+
+PermissionRequestID::~PermissionRequestID() {
+}
+
+bool PermissionRequestID::Equals(const PermissionRequestID& other) const {
+  return IsForSameTabAs(other) && (bridge_id_ == other.bridge_id_);
+}
+
+bool PermissionRequestID::IsForSameTabAs(
+    const PermissionRequestID& other) const {
+  return (render_process_id_ == other.render_process_id_) &&
+      (render_view_id_ == other.render_view_id_);
+}
+
+std::string PermissionRequestID::ToString() const {
+  return base::StringPrintf("%d,%d,%d", render_process_id_, render_view_id_,
+                            bridge_id_);
+}
diff --git a/chrome/browser/content_settings/permission_request_id.h b/chrome/browser/content_settings/permission_request_id.h
new file mode 100644
index 0000000..14bc274
--- /dev/null
+++ b/chrome/browser/content_settings/permission_request_id.h
@@ -0,0 +1,32 @@
+// 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_CONTENT_SETTINGS_PERMISSION_REQUEST_ID_H_
+#define CHROME_BROWSER_CONTENT_SETTINGS_PERMISSION_REQUEST_ID_H_
+
+#include <string>
+
+// Uniquely identifies a particular permission request.
+class PermissionRequestID {
+ public:
+  PermissionRequestID(int render_process_id, int render_view_id, int bridge_id);
+  ~PermissionRequestID();
+
+  int render_process_id() const { return render_process_id_; }
+  int render_view_id() const { return render_view_id_; }
+  int bridge_id() const { return bridge_id_; }
+
+  bool Equals(const PermissionRequestID& other) const;
+  bool IsForSameTabAs(const PermissionRequestID& other) const;
+  std::string ToString() const;
+
+ private:
+  int render_process_id_;
+  int render_view_id_;
+  int bridge_id_;
+
+  // Purposefully do not disable copying, as this is stored in STL containers.
+};
+
+#endif  // CHROME_BROWSER_CONTENT_SETTINGS_PERMISSION_REQUEST_ID_H_
diff --git a/chrome/browser/crash_upload_list.cc b/chrome/browser/crash_upload_list.cc
index 12a069c..911fec4 100644
--- a/chrome/browser/crash_upload_list.cc
+++ b/chrome/browser/crash_upload_list.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/crash_upload_list.h"
 
 #include "base/files/file_path.h"
-#include "base/message_loop/message_loop_proxy.h"
 #include "base/path_service.h"
 #include "chrome/common/chrome_paths.h"
 #if defined(OS_WIN)
@@ -30,8 +29,6 @@
 
 CrashUploadList::CrashUploadList(Delegate* delegate,
                                  const base::FilePath& upload_log_path)
-    : base::UploadList(delegate,
-                       upload_log_path,
-                       base::MessageLoopProxy::current()) {}
+    : UploadList(delegate, upload_log_path) {}
 
 CrashUploadList::~CrashUploadList() {}
diff --git a/chrome/browser/crash_upload_list.h b/chrome/browser/crash_upload_list.h
index b7ff6cf..f0b201c 100644
--- a/chrome/browser/crash_upload_list.h
+++ b/chrome/browser/crash_upload_list.h
@@ -5,10 +5,10 @@
 #ifndef CHROME_BROWSER_CRASH_UPLOAD_LIST_H_
 #define CHROME_BROWSER_CRASH_UPLOAD_LIST_H_
 
-#include "base/upload_list.h"
+#include "chrome/browser/upload_list.h"
 
 // An upload list manager for crash reports from breakpad.
-class CrashUploadList : public base::UploadList {
+class CrashUploadList : public UploadList {
  public:
   // Static factory method that creates the platform-specific implementation
   // of the crash upload list with the given callback delegate.
diff --git a/chrome/browser/devtools/adb/android_usb_device.cc b/chrome/browser/devtools/adb/android_usb_device.cc
index 0f662d5..9408328 100644
--- a/chrome/browser/devtools/adb/android_usb_device.cc
+++ b/chrome/browser/devtools/adb/android_usb_device.cc
@@ -22,9 +22,6 @@
 
 namespace {
 
-void Noop() {}
-void BoolNoop(bool success) {}
-
 const size_t kHeaderSize = 24;
 
 const int kAdbClass = 0xff;
@@ -38,7 +35,7 @@
 
 static const char kHostConnectMessage[] = "host::";
 
-typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
+typedef std::vector<scoped_refptr<UsbDeviceHandle> > UsbDevices;
 
 base::LazyInstance<AndroidUsbDevices>::Leaky g_devices =
     LAZY_INSTANCE_INITIALIZER;
@@ -93,26 +90,9 @@
   return std::string();
 }
 
-static void InterfaceClaimed(crypto::RSAPrivateKey* rsa_key,
-                             scoped_refptr<UsbDevice> usb_device,
-                             int inbound_address,
-                             int outbound_address,
-                             int zero_mask,
-                             AndroidUsbDevices* devices,
-                             bool success) {
-  if (!success)
-    return;
-
-  std::string serial = ReadSerialNumSync(usb_device->handle());
-  scoped_refptr<AndroidUsbDevice> device =
-      new AndroidUsbDevice(rsa_key, usb_device, serial, inbound_address,
-                           outbound_address, zero_mask);
-  devices->push_back(device);
-}
-
 static void ClaimInterface(
     crypto::RSAPrivateKey* rsa_key,
-    scoped_refptr<UsbDevice> usb_device,
+    scoped_refptr<UsbDeviceHandle> usb_device,
     const UsbInterface* interface,
     AndroidUsbDevices* devices) {
   if (interface->GetNumAltSettings() == 0)
@@ -147,24 +127,14 @@
   if (inbound_address == 0 || outbound_address == 0)
     return;
 
-  usb_device->ClaimInterface(1, base::Bind(&InterfaceClaimed,
-                                           rsa_key, usb_device,
-                                           inbound_address, outbound_address,
-                                           zero_mask, devices));
-}
-
-static void InterfacesListed(
-    crypto::RSAPrivateKey* rsa_key,
-    scoped_refptr<UsbDevice> usb_device,
-    scoped_refptr<UsbConfigDescriptor> config,
-    AndroidUsbDevices* devices,
-    bool success) {
-  if (!success)
+  if (!usb_device->ClaimInterface(1))
     return;
-  for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
-    ClaimInterface(rsa_key, usb_device, config->GetInterface(j),
-                   devices);
-  }
+
+  std::string serial = ReadSerialNumSync(usb_device->handle());
+  scoped_refptr<AndroidUsbDevice> device =
+      new AndroidUsbDevice(rsa_key, usb_device, serial, inbound_address,
+                           outbound_address, zero_mask);
+  devices->push_back(device);
 }
 
 static uint32 Checksum(const std::string& data) {
@@ -231,12 +201,12 @@
 
   // GC Android devices with no actual usb device.
   AndroidUsbDevices::iterator it = g_devices.Get().begin();
-  std::set<UsbDevice*> claimed_devices;
+  std::set<UsbDeviceHandle*> claimed_devices;
   while (it != g_devices.Get().end()) {
     bool found_device = false;
     for (UsbDevices::iterator it2 = usb_devices.begin();
          it2 != usb_devices.end() && !found_device; ++it2) {
-      UsbDevice* usb_device = it2->get();
+      UsbDeviceHandle* usb_device = it2->get();
       AndroidUsbDevice* device = it->get();
       if (usb_device == device->usb_device_) {
         found_device = true;
@@ -253,20 +223,23 @@
   // Add new devices.
   for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
        ++it) {
-    scoped_refptr<UsbDevice> usb_device = *it;
+    scoped_refptr<UsbDeviceHandle> usb_device = *it;
     if (claimed_devices.find(usb_device.get()) != claimed_devices.end())
       continue;
     scoped_refptr<UsbConfigDescriptor> config = new UsbConfigDescriptor();
-    usb_device->ListInterfaces(config.get(),
-                               base::Bind(&InterfacesListed, rsa_key,
-                                          usb_device, config,
-                                          &g_devices.Get()));
+    bool success = usb_device->ListInterfaces(config.get());
+    if (!success)
+      continue;
+    for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
+      ClaimInterface(rsa_key, usb_device, config->GetInterface(j),
+                     &g_devices.Get());
+    }
   }
   callback.Run(g_devices.Get());
 }
 
 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
-                                   scoped_refptr<UsbDevice> usb_device,
+                                   scoped_refptr<UsbDeviceHandle> usb_device,
                                    const std::string& serial,
                                    int inbound_address,
                                    int outbound_address,
@@ -533,8 +506,8 @@
     it->second->Terminated();
   }
 
-  usb_device_->ReleaseInterface(1, base::Bind(&BoolNoop));
-  usb_device_->Close(base::Bind(&Noop));
+  usb_device_->ReleaseInterface(1);
+  usb_device_->Close();
 }
 
 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) {
diff --git a/chrome/browser/devtools/adb/android_usb_device.h b/chrome/browser/devtools/adb/android_usb_device.h
index 6a8292d..5578ea1 100644
--- a/chrome/browser/devtools/adb/android_usb_device.h
+++ b/chrome/browser/devtools/adb/android_usb_device.h
@@ -9,7 +9,7 @@
 #include <queue>
 #include <vector>
 #include "base/memory/ref_counted.h"
-#include "chrome/browser/usb/usb_device.h"
+#include "chrome/browser/usb/usb_device_handle.h"
 
 namespace base {
 class MessageLoop;
@@ -72,7 +72,7 @@
                         const AndroidUsbDevicesCallback& callback);
 
   AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
-                   scoped_refptr<UsbDevice> device,
+                   scoped_refptr<UsbDeviceHandle> device,
                    const std::string& serial,
                    int inbound_address,
                    int outbound_address,
@@ -127,7 +127,7 @@
   scoped_ptr<crypto::RSAPrivateKey> rsa_key_;
 
   // Device info
-  scoped_refptr<UsbDevice> usb_device_;
+  scoped_refptr<UsbDeviceHandle> usb_device_;
   std::string serial_;
   int inbound_address_;
   int outbound_address_;
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 7331349..e1e1f42 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -34,12 +34,12 @@
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/common/extensions/extension.h"
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/download_item.h"
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/notification_source.h"
+#include "extensions/common/constants.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/drive/download_handler.h"
@@ -231,7 +231,7 @@
   // TODO(asanka): This determination is done based on |path|, while
   // ShouldOpenDownload() detects extension downloads based on the
   // characteristics of the download. Reconcile this. http://crbug.com/167702
-  if (extensions::Extension::IsExtension(path))
+  if (path.MatchesExtension(extensions::kExtensionFileExtension))
     return false;
   return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path);
 }
@@ -525,23 +525,28 @@
   if (item->GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
       item->GetDangerType() ==
       content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) {
+    content::DownloadDangerType danger_type =
+        content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
     switch (result) {
       case DownloadProtectionService::SAFE:
         // Do nothing.
         break;
       case DownloadProtectionService::DANGEROUS:
-        item->OnContentCheckCompleted(
-            content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT);
+        danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
         break;
       case DownloadProtectionService::UNCOMMON:
-        item->OnContentCheckCompleted(
-            content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT);
+        danger_type = content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
         break;
       case DownloadProtectionService::DANGEROUS_HOST:
-        item->OnContentCheckCompleted(
-            content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST);
+        danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
+        break;
+      case DownloadProtectionService::POTENTIALLY_UNWANTED:
+        danger_type = content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
         break;
     }
+
+    if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
+      item->OnContentCheckCompleted(danger_type);
   }
 
   SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
diff --git a/chrome/browser/download/download_danger_prompt.cc b/chrome/browser/download/download_danger_prompt.cc
index d75c6cc..95ec322 100644
--- a/chrome/browser/download/download_danger_prompt.cc
+++ b/chrome/browser/download/download_danger_prompt.cc
@@ -124,10 +124,18 @@
       return l10n_util::GetStringFUTF16(
           IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
           download_->GetFileNameToReportUser().LossyDisplayName());
-    default:
-      NOTREACHED();
-      return string16();
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+      return l10n_util::GetStringFUTF16(
+          IDS_PROMPT_POTENTIALLY_UNWANTED_DOWNLOAD,
+          download_->GetFileNameToReportUser().LossyDisplayName());
+    case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
+    case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
+    case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
+    case content::DOWNLOAD_DANGER_TYPE_MAX:
+      break;
   }
+  NOTREACHED();
+  return string16();
 }
 
 string16 DownloadDangerPromptImpl::GetAcceptButtonTitle() {
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index f8dc3db..22c14ff 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -301,6 +301,8 @@
                                            int base_width) const {
   // Should only be called if IsDangerous().
   DCHECK(IsDangerous());
+  string16 elided_filename =
+      ui::ElideFilename(download_->GetFileNameToReportUser(), font, base_width);
   switch (download_->GetDangerType()) {
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
       return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
@@ -310,31 +312,30 @@
         return l10n_util::GetStringUTF16(
             IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
       } else {
-        return l10n_util::GetStringFUTF16(
-            IDS_PROMPT_DANGEROUS_DOWNLOAD,
-            ui::ElideFilename(download_->GetFileNameToReportUser(),
-                              font, base_width));
+        return l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
+                                          elided_filename);
       }
 
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
-      return l10n_util::GetStringFUTF16(
-          IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
-          ui::ElideFilename(download_->GetFileNameToReportUser(),
-                            font, base_width));
+      return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+                                        elided_filename);
 
     case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+      return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
+                                        elided_filename);
+
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
       return l10n_util::GetStringFUTF16(
-          IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
-          ui::ElideFilename(download_->GetFileNameToReportUser(),
-                            font, base_width));
+          IDS_PROMPT_POTENTIALLY_UNWANTED_DOWNLOAD, elided_filename);
 
     case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
     case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
     case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
     case content::DOWNLOAD_DANGER_TYPE_MAX:
-      NOTREACHED();
+      break;
   }
+  NOTREACHED();
   return string16();
 }
 
@@ -378,6 +379,7 @@
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
     case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
       return true;
 
     case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc
index 794886f..02429b4 100644
--- a/chrome/browser/download/download_target_determiner.cc
+++ b/chrome/browser/download/download_target_determiner.cc
@@ -17,12 +17,12 @@
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/feature_switch.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/download_interrupt_reasons.h"
+#include "extensions/common/constants.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -551,7 +551,7 @@
   //    don't bother asking where to keep it.
   if (download_prefs_->PromptForDownload() &&
       !download_crx_util::IsExtensionDownload(*download_) &&
-      !extensions::Extension::IsExtension(filename) &&
+      !filename.MatchesExtension(extensions::kExtensionFileExtension) &&
       !download_prefs_->IsAutoOpenEnabledBasedOnExtension(filename))
     return true;
 
diff --git a/chrome/browser/extensions/activity_log/api_name_constants.h b/chrome/browser/extensions/activity_log/api_name_constants.h
index 0fe950d..77367a3 100644
--- a/chrome/browser/extensions/activity_log/api_name_constants.h
+++ b/chrome/browser/extensions/activity_log/api_name_constants.h
@@ -196,7 +196,8 @@
     "system.cpu.getInfo",
     "system.display.getInfo",
     "system.display.onDisplayChanged",
-    "system.display.setDisplayProperties"
+    "system.display.setDisplayProperties",
+    "system.memory.getInfo"
 };
 
 }  // namespace activity_log_api_name_constants
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 8d24989..aa526ed 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -920,15 +920,9 @@
 
 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
     ClearPrexistingDirectoryContent(const base::FilePath& project_path) {
-  if (!base::DeleteFile(project_path, true/*recursive*/)) {
-    SetError("Error in copying files from sync filesystem.");
-    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
-        base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
-                       SendResponse,
-                   this,
-                   false));
-    return;
-  }
+
+  // Clear the project directory before copying new files.
+  base::DeleteFile(project_path, true/*recursive*/);
 
   pendingCopyOperationsCount_ = 1;
 
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 0ebe8c5..03d6613 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -106,6 +106,7 @@
 const char kDangerKey[] = "danger";
 const char kDangerSafe[] = "safe";
 const char kDangerUncommon[] = "uncommon";
+const char kDangerUnwanted[] = "unwanted";
 const char kDangerAccepted[] = "accepted";
 const char kDangerHost[] = "host";
 const char kDangerUrl[] = "url";
@@ -146,6 +147,7 @@
   kDangerUncommon,
   kDangerAccepted,
   kDangerHost,
+  kDangerUnwanted
 };
 COMPILE_ASSERT(arraysize(kDangerStrings) == content::DOWNLOAD_DANGER_TYPE_MAX,
                download_danger_type_enum_changed);
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc
index d0a5800..8dd4197 100644
--- a/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -34,6 +34,10 @@
 namespace {
 
 const char kResultKey[] = "result";
+const char kUnexpectedProgressValueForNonProgressType[] =
+    "The progress value should not be specified for non-progress notification";
+const char kInvalidProgressValue[] =
+    "The progress value should range from 0 to 100";
 
 // Converts an object with width, height, and data in RGBA format into an
 // gfx::Image (in ARGB format).
@@ -276,6 +280,20 @@
     if (has_list_items != (type == message_center::NOTIFICATION_TYPE_MULTIPLE))
       return false;
 
+    if (options->progress.get() != NULL) {
+      // We should have progress if and only if the type is a progress type.
+      if (type != message_center::NOTIFICATION_TYPE_PROGRESS) {
+        SetError(kUnexpectedProgressValueForNonProgressType);
+        return false;
+      }
+      optional_fields.progress = *options->progress;
+      // Progress value should range from 0 to 100.
+      if (optional_fields.progress < 0 || optional_fields.progress > 100) {
+        SetError(kInvalidProgressValue);
+        return false;
+      }
+    }
+
     if (has_list_items) {
       using api::notifications::NotificationItem;
       std::vector<linked_ptr<NotificationItem> >::iterator i;
@@ -333,6 +351,8 @@
       return message_center::NOTIFICATION_TYPE_IMAGE;
     case api::notifications::TEMPLATE_TYPE_LIST:
       return message_center::NOTIFICATION_TYPE_MULTIPLE;
+    case api::notifications::TEMPLATE_TYPE_PROGRESS:
+      return message_center::NOTIFICATION_TYPE_PROGRESS;
     default:
       // Gracefully handle newer application code that is running on an older
       // runtime that doesn't recognize the requested template.
diff --git a/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
index 3a6e2b2..5ea2a9f 100644
--- a/chrome/browser/extensions/api/notifications/notifications_apitest.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -388,3 +388,117 @@
     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   }
 }
+
+
+#if defined(OS_LINUX)
+#define MAYBE_TestProgressNotification DISABLED_TestProgressNotification
+#else
+#define MAYBE_TestProgressNotification TestProgressNotification
+#endif
+
+IN_PROC_BROWSER_TEST_F(NotificationsApiTest, MAYBE_TestProgressNotification) {
+  scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension());
+
+  {
+    scoped_refptr<extensions::NotificationsCreateFunction>
+        notification_create_function(
+            new extensions::NotificationsCreateFunction());
+    notification_create_function->set_extension(empty_extension.get());
+    notification_create_function->set_has_callback(true);
+
+    scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
+        notification_create_function.get(),
+        "[\"\", "
+        "{"
+        "\"type\": \"progress\","
+        "\"iconUrl\": \"an/image/that/does/not/exist.png\","
+        "\"title\": \"Test!\","
+        "\"message\": \"This is a progress notification.\","
+        "\"priority\": 1,"
+        "\"eventTime\": 1234567890.12345678,"
+        "\"progress\": 30"
+        "}]",
+        browser(),
+        utils::NONE));
+
+    std::string notification_id;
+    EXPECT_EQ(base::Value::TYPE_STRING, result->GetType());
+    EXPECT_TRUE(result->GetAsString(&notification_id));
+    EXPECT_TRUE(notification_id.length() > 0);
+  }
+
+  // Error case: progress value provided for non-progress type.
+  {
+    scoped_refptr<extensions::NotificationsCreateFunction>
+        notification_create_function(
+            new extensions::NotificationsCreateFunction());
+    notification_create_function->set_extension(empty_extension.get());
+    notification_create_function->set_has_callback(true);
+
+    utils::RunFunction(
+        notification_create_function.get(),
+        "[\"\", "
+        "{"
+        "\"type\": \"basic\","
+        "\"iconUrl\": \"an/image/that/does/not/exist.png\","
+        "\"title\": \"Test!\","
+        "\"message\": \"This is a progress notification.\","
+        "\"priority\": 1,"
+        "\"eventTime\": 1234567890.12345678,"
+        "\"progress\": 10"
+        "}]",
+        browser(),
+        utils::NONE);
+    EXPECT_FALSE(notification_create_function->GetError().empty());
+  }
+
+  // Error case: progress value less than lower bound.
+  {
+    scoped_refptr<extensions::NotificationsCreateFunction>
+        notification_create_function(
+            new extensions::NotificationsCreateFunction());
+    notification_create_function->set_extension(empty_extension.get());
+    notification_create_function->set_has_callback(true);
+
+    utils::RunFunction(
+        notification_create_function.get(),
+        "[\"\", "
+        "{"
+        "\"type\": \"progress\","
+        "\"iconUrl\": \"an/image/that/does/not/exist.png\","
+        "\"title\": \"Test!\","
+        "\"message\": \"This is a progress notification.\","
+        "\"priority\": 1,"
+        "\"eventTime\": 1234567890.12345678,"
+        "\"progress\": -10"
+        "}]",
+        browser(),
+        utils::NONE);
+    EXPECT_FALSE(notification_create_function->GetError().empty());
+  }
+
+  // Error case: progress value greater than upper bound.
+  {
+    scoped_refptr<extensions::NotificationsCreateFunction>
+        notification_create_function(
+            new extensions::NotificationsCreateFunction());
+    notification_create_function->set_extension(empty_extension.get());
+    notification_create_function->set_has_callback(true);
+
+    utils::RunFunction(
+        notification_create_function.get(),
+        "[\"\", "
+        "{"
+        "\"type\": \"progress\","
+        "\"iconUrl\": \"an/image/that/does/not/exist.png\","
+        "\"title\": \"Test!\","
+        "\"message\": \"This is a progress notification.\","
+        "\"priority\": 1,"
+        "\"eventTime\": 1234567890.12345678,"
+        "\"progress\": 101"
+        "}]",
+        browser(),
+        utils::NONE);
+    EXPECT_FALSE(notification_create_function->GetError().empty());
+  }
+}
diff --git a/chrome/browser/extensions/api/system_info/system_info_api.cc b/chrome/browser/extensions/api/system_info/system_info_api.cc
index d203948..cb7822c 100644
--- a/chrome/browser/extensions/api/system_info/system_info_api.cc
+++ b/chrome/browser/extensions/api/system_info/system_info_api.cc
@@ -85,9 +85,6 @@
   virtual void OnRemovableStorageDetached(
       const chrome::StorageInfo& info) OVERRIDE;
 
-  void DispatchStorageAttachedEvent(const chrome::StorageInfo& info,
-                                    int64 avail_bytes);
-
   // Called from any thread to dispatch the systemInfo event to all extension
   // processes cross multiple profiles.
   void DispatchEvent(const std::string& event_name,
@@ -217,29 +214,8 @@
 
 void SystemInfoEventRouter::OnRemovableStorageAttached(
     const chrome::StorageInfo& info) {
-  base::PostTaskAndReplyWithResult(
-      BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
-          base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN),
-      FROM_HERE,
-      base::Bind(&StorageInfoProvider::GetStorageFreeSpaceFromTransientId,
-                 StorageInfoProvider::Get(),
-                 StorageInfoProvider::Get()->GetTransientIdForDeviceId(
-                     info.device_id())),
-      base::Bind(&SystemInfoEventRouter::DispatchStorageAttachedEvent,
-                 // Since SystemInfoEventRouter is a global lazy instance, this
-                 // pointer will be alive when the reply comes back.
-                 base::Unretained(this),
-                 info));
-}
-
-void SystemInfoEventRouter::DispatchStorageAttachedEvent(
-    const chrome::StorageInfo& info, int64 avail_bytes) {
   StorageUnitInfo unit;
   systeminfo::BuildStorageUnitInfo(info, &unit);
-
-  unit.available_capacity =
-      avail_bytes > 0 ? static_cast<double>(avail_bytes) : 0;
-
   scoped_ptr<base::ListValue> args(new base::ListValue);
   args->Append(unit.ToValue().release());
   DispatchEvent(event_names::kOnStorageAttached, args.Pass());
diff --git a/chrome/browser/extensions/api/system_info_memory/memory_info_provider.h b/chrome/browser/extensions/api/system_info_memory/memory_info_provider.h
deleted file mode 100644
index 1948c7a..0000000
--- a/chrome/browser/extensions/api/system_info_memory/memory_info_provider.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 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_EXTENSIONS_API_SYSTEM_INFO_MEMORY_MEMORY_INFO_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_MEMORY_MEMORY_INFO_PROVIDER_H_
-
-#include "chrome/browser/extensions/api/system_info/system_info_provider.h"
-#include "chrome/common/extensions/api/system_info_memory.h"
-
-namespace extensions {
-
-class MemoryInfoProvider
-    : public SystemInfoProvider<
-          api::system_info_memory::MemoryInfo> {
- public:
-  static MemoryInfoProvider* Get();
-
-  // Overriden from SystemInfoProvider<MemoryInfo>.
-  virtual bool QueryInfo() OVERRIDE;
-
-  const api::system_info_memory::MemoryInfo& memory_info() const;
-
- private:
-  friend class SystemInfoProvider<
-      api::system_info_memory::MemoryInfo>;
-  friend class MockMemoryInfoProviderImpl;
-
-  MemoryInfoProvider();
-  virtual ~MemoryInfoProvider();
-
-  DISALLOW_COPY_AND_ASSIGN(MemoryInfoProvider);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_MEMORY_MEMORY_INFO_PROVIDER_H_
-
diff --git a/chrome/browser/extensions/api/system_info_memory/system_info_memory_api.cc b/chrome/browser/extensions/api/system_info_memory/system_info_memory_api.cc
deleted file mode 100644
index 7439294..0000000
--- a/chrome/browser/extensions/api/system_info_memory/system_info_memory_api.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 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/system_info_memory/system_info_memory_api.h"
-
-#include "chrome/browser/extensions/api/system_info_memory/memory_info_provider.h"
-
-namespace extensions {
-
-using api::system_info_memory::MemoryInfo;
-
-SystemInfoMemoryGetFunction::SystemInfoMemoryGetFunction() {}
-
-SystemInfoMemoryGetFunction::~SystemInfoMemoryGetFunction() {}
-
-bool SystemInfoMemoryGetFunction::RunImpl() {
-  MemoryInfoProvider::Get()->StartQueryInfo(
-      base::Bind(&SystemInfoMemoryGetFunction::OnGetMemoryInfoCompleted, this));
-  return true;
-}
-
-void SystemInfoMemoryGetFunction::OnGetMemoryInfoCompleted(bool success) {
-  if (success)
-    SetResult(MemoryInfoProvider::Get()->memory_info().ToValue().release());
-  else
-    SetError("Error occurred when querying memory information.");
-  SendResponse(success);
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/system_info_memory/system_info_memory_api.h b/chrome/browser/extensions/api/system_info_memory/system_info_memory_api.h
deleted file mode 100644
index 410fbf6..0000000
--- a/chrome/browser/extensions/api/system_info_memory/system_info_memory_api.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012 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_EXTENSIONS_API_SYSTEM_INFO_MEMORY_SYSTEM_INFO_MEMORY_API_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_MEMORY_SYSTEM_INFO_MEMORY_API_H_
-
-#include "chrome/browser/extensions/extension_function.h"
-#include "chrome/common/extensions/api/system_info_memory.h"
-
-namespace extensions {
-
-class SystemInfoMemoryGetFunction : public AsyncExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("systemInfo.memory.get", SYSTEMINFO_MEMORY_GET)
-  SystemInfoMemoryGetFunction();
-
- private:
-  virtual ~SystemInfoMemoryGetFunction();
-  virtual bool RunImpl() OVERRIDE;
-  void OnGetMemoryInfoCompleted(bool success);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_MEMORY_SYSTEM_INFO_MEMORY_API_H__
diff --git a/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc b/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc
index c43fe8f..c868769 100644
--- a/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc
+++ b/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc
@@ -34,7 +34,6 @@
   unit->type = chrome::StorageInfo::IsRemovableDevice(info.device_id()) ?
       STORAGE_UNIT_TYPE_REMOVABLE : STORAGE_UNIT_TYPE_FIXED;
   unit->capacity = static_cast<double>(info.total_size_in_bytes());
-  unit->available_capacity = 0;
 }
 
 }  // namespace systeminfo
@@ -61,8 +60,7 @@
 }
 
 void StorageInfoProvider::PrepareQueryOnUIThread() {
-  // Get all available storage devices before invoking |QueryInfo()| to get
-  // available capacity.
+  // Get all available storage devices before invoking |QueryInfo()|.
   GetAllStoragesIntoInfoList();
 }
 
@@ -77,13 +75,8 @@
 
 bool StorageInfoProvider::QueryInfo() {
   DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
-  for (StorageUnitInfoList::iterator it = info_.begin();
-       it != info_.end(); ++it) {
-    int64 amount = GetStorageFreeSpaceFromTransientId((*it)->id);
-    if (amount > 0)
-      (*it)->available_capacity = static_cast<double>(amount);
-  }
-
+  // No info to query since we get all available storage devices' info in
+  // |PrepareQueryOnUIThread()|.
   return true;
 }
 
diff --git a/chrome/browser/extensions/api/system_info_memory/memory_info_provider.cc b/chrome/browser/extensions/api/system_memory/memory_info_provider.cc
similarity index 82%
rename from chrome/browser/extensions/api/system_info_memory/memory_info_provider.cc
rename to chrome/browser/extensions/api/system_memory/memory_info_provider.cc
index 4bef0ed..0858183 100644
--- a/chrome/browser/extensions/api/system_info_memory/memory_info_provider.cc
+++ b/chrome/browser/extensions/api/system_memory/memory_info_provider.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2012 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/extensions/api/system_info_memory/memory_info_provider.h"
+#include "chrome/browser/extensions/api/system_memory/memory_info_provider.h"
 
 #include "base/sys_info.h"
 
 namespace extensions {
 
-using api::system_info_memory::MemoryInfo;
+using api::system_memory::MemoryInfo;
 
 // Static member intialization.
 template<>
diff --git a/chrome/browser/extensions/api/system_memory/memory_info_provider.h b/chrome/browser/extensions/api/system_memory/memory_info_provider.h
new file mode 100644
index 0000000..54d0449
--- /dev/null
+++ b/chrome/browser/extensions/api/system_memory/memory_info_provider.h
@@ -0,0 +1,36 @@
+// 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_EXTENSIONS_API_SYSTEM_MEMORY_MEMORY_INFO_PROVIDER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_MEMORY_MEMORY_INFO_PROVIDER_H_
+
+#include "chrome/browser/extensions/api/system_info/system_info_provider.h"
+#include "chrome/common/extensions/api/system_memory.h"
+
+namespace extensions {
+
+class MemoryInfoProvider
+    : public SystemInfoProvider<api::system_memory::MemoryInfo> {
+ public:
+  static MemoryInfoProvider* Get();
+
+  // Overriden from SystemInfoProvider<MemoryInfo>.
+  virtual bool QueryInfo() OVERRIDE;
+
+  const api::system_memory::MemoryInfo& memory_info() const;
+
+ private:
+  friend class SystemInfoProvider<api::system_memory::MemoryInfo>;
+  friend class MockMemoryInfoProviderImpl;
+
+  MemoryInfoProvider();
+  virtual ~MemoryInfoProvider();
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryInfoProvider);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_MEMORY_MEMORY_INFO_PROVIDER_H_
+
diff --git a/chrome/browser/extensions/api/system_memory/system_memory_api.cc b/chrome/browser/extensions/api/system_memory/system_memory_api.cc
new file mode 100644
index 0000000..7556410
--- /dev/null
+++ b/chrome/browser/extensions/api/system_memory/system_memory_api.cc
@@ -0,0 +1,31 @@
+// 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/system_memory/system_memory_api.h"
+
+#include "chrome/browser/extensions/api/system_memory/memory_info_provider.h"
+
+namespace extensions {
+
+using api::system_memory::MemoryInfo;
+
+SystemMemoryGetInfoFunction::SystemMemoryGetInfoFunction() {}
+
+SystemMemoryGetInfoFunction::~SystemMemoryGetInfoFunction() {}
+
+bool SystemMemoryGetInfoFunction::RunImpl() {
+  MemoryInfoProvider::Get()->StartQueryInfo(
+      base::Bind(&SystemMemoryGetInfoFunction::OnGetMemoryInfoCompleted, this));
+  return true;
+}
+
+void SystemMemoryGetInfoFunction::OnGetMemoryInfoCompleted(bool success) {
+  if (success)
+    SetResult(MemoryInfoProvider::Get()->memory_info().ToValue().release());
+  else
+    SetError("Error occurred when querying memory information.");
+  SendResponse(success);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/system_memory/system_memory_api.h b/chrome/browser/extensions/api/system_memory/system_memory_api.h
new file mode 100644
index 0000000..b6ef065
--- /dev/null
+++ b/chrome/browser/extensions/api/system_memory/system_memory_api.h
@@ -0,0 +1,26 @@
+// 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_EXTENSIONS_API_SYSTEM_MEMORY_SYSTEM_MEMORY_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_MEMORY_SYSTEM_MEMORY_API_H_
+
+#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/common/extensions/api/system_memory.h"
+
+namespace extensions {
+
+class SystemMemoryGetInfoFunction : public AsyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("system.memory.getInfo", SYSTEM_MEMORY_GETINFO)
+  SystemMemoryGetInfoFunction();
+
+ private:
+  virtual ~SystemMemoryGetInfoFunction();
+  virtual bool RunImpl() OVERRIDE;
+  void OnGetMemoryInfoCompleted(bool success);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_MEMORY_SYSTEM_MEMORY_API_H_
diff --git a/chrome/browser/extensions/api/system_info_memory/system_info_memory_apitest.cc b/chrome/browser/extensions/api/system_memory/system_memory_apitest.cc
similarity index 77%
rename from chrome/browser/extensions/api/system_info_memory/system_info_memory_apitest.cc
rename to chrome/browser/extensions/api/system_memory/system_memory_apitest.cc
index 0f070ec..9440074 100644
--- a/chrome/browser/extensions/api/system_info_memory/system_info_memory_apitest.cc
+++ b/chrome/browser/extensions/api/system_memory/system_memory_apitest.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2012 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 "base/command_line.h"
 #include "base/message_loop/message_loop.h"
-#include "chrome/browser/extensions/api/system_info_memory/memory_info_provider.h"
+#include "chrome/browser/extensions/api/system_memory/memory_info_provider.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/common/chrome_switches.h"
@@ -12,7 +12,7 @@
 
 namespace extensions {
 
-using api::system_info_memory::MemoryInfo;
+using api::system_memory::MemoryInfo;
 
 const char kExtensionId[] = "lfmcnjhchhgejbpbonjobnlbcgcnmjif";
 
@@ -29,10 +29,10 @@
   virtual ~MockMemoryInfoProviderImpl() {}
 };
 
-class SystemInfoMemoryApiTest: public ExtensionApiTest {
+class SystemMemoryApiTest: public ExtensionApiTest {
  public:
-  SystemInfoMemoryApiTest() {}
-  virtual ~SystemInfoMemoryApiTest() {}
+  SystemMemoryApiTest() {}
+  virtual ~SystemMemoryApiTest() {}
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     ExtensionApiTest::SetUpCommandLine(command_line);
@@ -49,11 +49,11 @@
   scoped_ptr<base::MessageLoop> message_loop_;
 };
 
-IN_PROC_BROWSER_TEST_F(SystemInfoMemoryApiTest, Memory) {
+IN_PROC_BROWSER_TEST_F(SystemMemoryApiTest, Memory) {
   scoped_refptr<MemoryInfoProvider> provider = new MockMemoryInfoProviderImpl();
   // The provider is owned by the single MemoryInfoProvider instance.
   MemoryInfoProvider::InitializeForTesting(provider);
-  ASSERT_TRUE(RunExtensionTest("systeminfo/memory")) << message_;
+  ASSERT_TRUE(RunExtensionTest("system/memory")) << message_;
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc
index c4bb050..5b123ad 100644
--- a/chrome/browser/extensions/api/usb/usb_api.cc
+++ b/chrome/browser/extensions/api/usb/usb_api.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/extensions/api/usb/usb_device_resource.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/usb/usb_device_handle.h"
 #include "chrome/browser/usb/usb_service.h"
 #include "chrome/browser/usb/usb_service_factory.h"
 #include "chrome/common/extensions/api/usb.h"
@@ -89,7 +90,7 @@
 static const int kMaxPackets = 4 * 1024 * 1024;
 static const int kMaxPacketLength = 64 * 1024;
 
-static UsbDevice* device_for_test_ = NULL;
+static UsbDeviceHandle* device_for_test_ = NULL;
 
 static bool ConvertDirectionToApi(const UsbEndpointDirection& input,
                                   Direction* output) {
@@ -184,19 +185,19 @@
 }
 
 static bool ConvertRequestType(const RequestType& input,
-                               UsbDevice::TransferRequestType* output) {
+                               UsbDeviceHandle::TransferRequestType* output) {
   switch (input) {
     case usb::REQUEST_TYPE_STANDARD:
-      *output = UsbDevice::STANDARD;
+      *output = UsbDeviceHandle::STANDARD;
       return true;
     case usb::REQUEST_TYPE_CLASS:
-      *output = UsbDevice::CLASS;
+      *output = UsbDeviceHandle::CLASS;
       return true;
     case usb::REQUEST_TYPE_VENDOR:
-      *output = UsbDevice::VENDOR;
+      *output = UsbDeviceHandle::VENDOR;
       return true;
     case usb::REQUEST_TYPE_RESERVED:
-      *output = UsbDevice::RESERVED;
+      *output = UsbDeviceHandle::RESERVED;
       return true;
     default:
       NOTREACHED();
@@ -205,19 +206,19 @@
 }
 
 static bool ConvertRecipient(const Recipient& input,
-                             UsbDevice::TransferRecipient* output) {
+                             UsbDeviceHandle::TransferRecipient* output) {
   switch (input) {
     case usb::RECIPIENT_DEVICE:
-      *output = UsbDevice::DEVICE;
+      *output = UsbDeviceHandle::DEVICE;
       return true;
     case usb::RECIPIENT_INTERFACE:
-      *output = UsbDevice::INTERFACE;
+      *output = UsbDeviceHandle::INTERFACE;
       return true;
     case usb::RECIPIENT_ENDPOINT:
-      *output = UsbDevice::ENDPOINT;
+      *output = UsbDeviceHandle::ENDPOINT;
       return true;
     case usb::RECIPIENT_OTHER:
-      *output = UsbDevice::OTHER;
+      *output = UsbDeviceHandle::OTHER;
       return true;
     default:
       NOTREACHED();
@@ -383,7 +384,7 @@
 }
 
 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
-    const RequestType& input, UsbDevice::TransferRequestType* output) {
+    const RequestType& input, UsbDeviceHandle::TransferRequestType* output) {
   const bool converted = ConvertRequestType(input, output);
   if (!converted)
     SetError(kErrorConvertRequestType);
@@ -391,7 +392,7 @@
 }
 
 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
-    const Recipient& input, UsbDevice::TransferRecipient* output) {
+    const Recipient& input, UsbDeviceHandle::TransferRecipient* output) {
   const bool converted = ConvertRecipient(input, output);
   if (!converted)
     SetError(kErrorConvertRecipient);
@@ -402,7 +403,7 @@
 
 UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
 
-void UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) {
+void UsbFindDevicesFunction::SetDeviceForTest(UsbDeviceHandle* device) {
   device_for_test_ = device;
 }
 
@@ -454,7 +455,7 @@
 
 void UsbFindDevicesFunction::OnCompleted() {
   for (size_t i = 0; i < devices_.size(); ++i) {
-    UsbDevice* const device = devices_[i].get();
+    UsbDeviceHandle* const device = devices_[i].get();
     UsbDeviceResource* const resource =
         new UsbDeviceResource(extension_->id(), device);
 
@@ -487,8 +488,13 @@
   }
 
   config_ = new UsbConfigDescriptor();
-  resource->device()->ListInterfaces(
-      config_.get(), base::Bind(&UsbListInterfacesFunction::OnCompleted, this));
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::ListInterfaces,
+                 resource->device(),
+                 config_),
+      base::Bind(&UsbListInterfacesFunction::OnCompleted, this));
 }
 
 void UsbListInterfacesFunction::OnCompleted(bool success) {
@@ -611,8 +617,11 @@
     return;
   }
 
-  resource->device()->Close(base::Bind(&UsbCloseDeviceFunction::OnCompleted,
-                                     this));
+  BrowserThread::PostTaskAndReply(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::Close, resource->device()),
+      base::Bind(&UsbCloseDeviceFunction::OnCompleted, this));
   RemoveUsbDeviceResource(parameters_->device.handle);
 }
 
@@ -638,7 +647,12 @@
     return;
   }
 
-  resource->device()->ClaimInterface(parameters_->interface_number,
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::ClaimInterface,
+                 resource->device(),
+                 parameters_->interface_number),
       base::Bind(&UsbClaimInterfaceFunction::OnCompleted, this));
 }
 
@@ -666,7 +680,12 @@
     return;
   }
 
-  resource->device()->ReleaseInterface(parameters_->interface_number,
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::ReleaseInterface,
+                 resource->device(),
+                 parameters_->interface_number),
       base::Bind(&UsbReleaseInterfaceFunction::OnCompleted, this));
 }
 
@@ -696,9 +715,13 @@
     return;
   }
 
-  resource->device()->SetInterfaceAlternateSetting(
-      parameters_->interface_number,
-      parameters_->alternate_setting,
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::SetInterfaceAlternateSetting,
+                 resource->device(),
+                 parameters_->interface_number,
+                 parameters_->alternate_setting),
       base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnCompleted, this));
 }
 
@@ -729,8 +752,8 @@
   const ControlTransferInfo& transfer = parameters_->transfer_info;
 
   UsbEndpointDirection direction;
-  UsbDevice::TransferRequestType request_type;
-  UsbDevice::TransferRecipient recipient;
+  UsbDeviceHandle::TransferRequestType request_type;
+  UsbDeviceHandle::TransferRecipient recipient;
   size_t size = 0;
 
   if (!ConvertDirectionSafely(transfer.direction, &direction) ||
@@ -955,8 +978,7 @@
 
 void UsbResetDeviceFunction::OnStartResest(UsbDeviceResource* resource) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  resource->device()->ResetDevice(
-      base::Bind(&UsbResetDeviceFunction::OnCompletedFileThread, this));
+  OnCompletedFileThread(resource->device()->ResetDevice());
 }
 
 void UsbResetDeviceFunction::OnCompletedFileThread(bool success) {
@@ -978,8 +1000,12 @@
     }
     // Close the device now because the handle is invalid after an
     // unsuccessful reset.
-    resource->device()->Close(
-        base::Bind(&UsbResetDeviceFunction::OnError, this));
+    BrowserThread::PostTaskAndReply(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::Close,
+                 resource->device()),
+      base::Bind(&UsbResetDeviceFunction::OnError, this));
     return;
   }
   SetResult(Value::CreateBooleanValue(true));
diff --git a/chrome/browser/extensions/api/usb/usb_api.h b/chrome/browser/extensions/api/usb/usb_api.h
index f223016..80941fc 100644
--- a/chrome/browser/extensions/api/usb/usb_api.h
+++ b/chrome/browser/extensions/api/usb/usb_api.h
@@ -6,15 +6,16 @@
 #define CHROME_BROWSER_EXTENSIONS_API_USB_USB_API_H_
 
 #include <string>
+#include <vector>
 
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/extensions/api/api_function.h"
 #include "chrome/browser/extensions/api/api_resource_manager.h"
-#include "chrome/browser/usb/usb_device.h"
+#include "chrome/browser/usb/usb_device_handle.h"
 #include "chrome/common/extensions/api/usb.h"
 #include "net/base/io_buffer.h"
 
-class UsbDevice;
+class UsbDeviceHandle;
 
 namespace extensions {
 
@@ -46,9 +47,9 @@
   bool ConvertDirectionSafely(const extensions::api::usb::Direction& input,
                               UsbEndpointDirection* output);
   bool ConvertRequestTypeSafely(const extensions::api::usb::RequestType& input,
-                              UsbDevice::TransferRequestType* output);
+                              UsbDeviceHandle::TransferRequestType* output);
   bool ConvertRecipientSafely(const extensions::api::usb::Recipient& input,
-                              UsbDevice::TransferRecipient* output);
+                              UsbDeviceHandle::TransferRecipient* output);
 
   void OnCompleted(UsbTransferStatus status,
                    scoped_refptr<net::IOBuffer> data,
@@ -61,7 +62,7 @@
 
   UsbFindDevicesFunction();
 
-  static void SetDeviceForTest(UsbDevice* device);
+  static void SetDeviceForTest(UsbDeviceHandle* device);
 
  protected:
   virtual ~UsbFindDevicesFunction();
@@ -73,7 +74,7 @@
   void OnCompleted();
 
   scoped_ptr<base::ListValue> result_;
-  std::vector<scoped_refptr<UsbDevice> > devices_;
+  std::vector<scoped_refptr<UsbDeviceHandle> > devices_;
   scoped_ptr<extensions::api::usb::FindDevices::Params> parameters_;
 };
 
diff --git a/chrome/browser/extensions/api/usb/usb_apitest.cc b/chrome/browser/extensions/api/usb/usb_apitest.cc
index 20f37d9..bb64f14 100644
--- a/chrome/browser/extensions/api/usb/usb_apitest.cc
+++ b/chrome/browser/extensions/api/usb/usb_apitest.cc
@@ -13,25 +13,16 @@
 
 using testing::AnyNumber;
 using testing::_;
+using testing::Return;
 
 namespace {
 
-ACTION(InvokeUsbCallback) {
-  ::std::tr1::get<0>(args).Run();
-}
-
 ACTION_TEMPLATE(InvokeUsbTransferCallback,
                 HAS_1_TEMPLATE_PARAMS(int, k),
                 AND_1_VALUE_PARAMS(p1)) {
   ::std::tr1::get<k>(args).Run(p1, new net::IOBuffer(1), 1);
 }
 
-ACTION_TEMPLATE(InvokeUsbResultCallback,
-                HAS_1_TEMPLATE_PARAMS(int, k),
-                AND_1_VALUE_PARAMS(p1)) {
-  ::std::tr1::get<k>(args).Run(p1);
-}
-
 // MSVC erroneously thinks that at least one of the arguments for the transfer
 // methods differ by const or volatility and emits a warning about the old
 // standards-noncompliant behaviour of their compiler.
@@ -39,11 +30,11 @@
 #pragma warning(push)
 #pragma warning(disable:4373)
 #endif
-class MockUsbDevice : public UsbDevice {
+class MockUsbDeviceHandle : public UsbDeviceHandle {
  public:
-  MockUsbDevice() : UsbDevice() {}
+  MockUsbDeviceHandle() : UsbDeviceHandle() {}
 
-  MOCK_METHOD1(Close, void(const base::Callback<void()>& callback));
+  MOCK_METHOD0(Close, void());
 
   MOCK_METHOD10(ControlTransfer, void(const UsbEndpointDirection direction,
       const TransferRequestType request_type, const TransferRecipient recipient,
@@ -64,13 +55,12 @@
       const unsigned int packets, const unsigned int packet_length,
       const unsigned int timeout, const UsbTransferCallback& callback));
 
-  MOCK_METHOD1(ResetDevice, void(const base::Callback<void(bool)>& callback));
+  MOCK_METHOD0(ResetDevice, bool());
 
-  MOCK_METHOD2(ListInterfaces, void(UsbConfigDescriptor* config,
-      const UsbInterfaceCallback& callback));
+  MOCK_METHOD1(ListInterfaces, bool(UsbConfigDescriptor* config));
 
  protected:
-  virtual ~MockUsbDevice() {}
+  virtual ~MockUsbDeviceHandle() {}
 };
 #if defined(OS_WIN)
 #pragma warning(pop)
@@ -84,22 +74,21 @@
   }
 
   virtual void SetUpOnMainThread() OVERRIDE {
-    mock_device_ = new MockUsbDevice();
+    mock_device_ = new MockUsbDeviceHandle();
     extensions::UsbFindDevicesFunction::SetDeviceForTest(mock_device_.get());
   }
 
  protected:
-  scoped_refptr<MockUsbDevice> mock_device_;
+  scoped_refptr<MockUsbDeviceHandle> mock_device_;
 };
 
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) {
-  EXPECT_CALL(*mock_device_.get(), Close(_))
-      .WillRepeatedly(InvokeUsbCallback());
-  EXPECT_CALL(*mock_device_.get(), ResetDevice(_))
-      .WillOnce(InvokeUsbResultCallback<0>(true))
-      .WillOnce(InvokeUsbResultCallback<0>(false));
+  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_.get(), ResetDevice())
+      .WillOnce(Return(true))
+      .WillOnce(Return(false));
   EXPECT_CALL(*mock_device_.get(),
               InterruptTransfer(USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
@@ -107,17 +96,17 @@
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) {
-  EXPECT_CALL(*mock_device_.get(), ListInterfaces(_, _))
-      .WillOnce(InvokeUsbResultCallback<1>(false));
-  EXPECT_CALL(*mock_device_.get(), Close(_)).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_.get(), ListInterfaces(_))
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/list_interfaces"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) {
   EXPECT_CALL(*mock_device_.get(),
               ControlTransfer(USB_DIRECTION_OUTBOUND,
-                              UsbDevice::STANDARD,
-                              UsbDevice::DEVICE,
+                              UsbDeviceHandle::STANDARD,
+                              UsbDeviceHandle::DEVICE,
                               1,
                               2,
                               3,
@@ -135,14 +124,14 @@
   EXPECT_CALL(*mock_device_.get(),
               IsochronousTransfer(USB_DIRECTION_OUTBOUND, 3, _, 1, 1, 1, _, _))
       .WillOnce(InvokeUsbTransferCallback<7>(USB_TRANSFER_COMPLETED));
-  EXPECT_CALL(*mock_device_.get(), Close(_)).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/transfer_event"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) {
   EXPECT_CALL(*mock_device_.get(), BulkTransfer(_, _, _, 0, _, _))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
-  EXPECT_CALL(*mock_device_.get(), Close(_)).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer"));
 }
 
@@ -151,12 +140,12 @@
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_ERROR))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_TIMEOUT));
-  EXPECT_CALL(*mock_device_.get(), Close(_)).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/transfer_failure"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) {
-  EXPECT_CALL(*mock_device_.get(), Close(_)).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer"));
 }
 
diff --git a/chrome/browser/extensions/api/usb/usb_device_resource.cc b/chrome/browser/extensions/api/usb/usb_device_resource.cc
index 4d8aa95..685d24d 100644
--- a/chrome/browser/extensions/api/usb/usb_device_resource.cc
+++ b/chrome/browser/extensions/api/usb/usb_device_resource.cc
@@ -11,7 +11,7 @@
 #include "base/bind_helpers.h"
 #include "base/synchronization/lock.h"
 #include "chrome/browser/extensions/api/api_resource.h"
-#include "chrome/browser/usb/usb_device.h"
+#include "chrome/browser/usb/usb_device_handle.h"
 #include "chrome/common/extensions/api/usb.h"
 
 namespace extensions {
@@ -28,7 +28,7 @@
 }
 
 UsbDeviceResource::UsbDeviceResource(const std::string& owner_extension_id,
-                                     scoped_refptr<UsbDevice> device)
+                                     scoped_refptr<UsbDeviceHandle> device)
     : ApiResource(owner_extension_id), device_(device) {}
 
 UsbDeviceResource::~UsbDeviceResource() {}
diff --git a/chrome/browser/extensions/api/usb/usb_device_resource.h b/chrome/browser/extensions/api/usb/usb_device_resource.h
index 15fcca0..6592548 100644
--- a/chrome/browser/extensions/api/usb/usb_device_resource.h
+++ b/chrome/browser/extensions/api/usb/usb_device_resource.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_EXTENSIONS_API_USB_USB_DEVICE_RESOURCE_H_
 
 #include <set>
+#include <string>
 
 #include "base/basictypes.h"
 #include "base/memory/linked_ptr.h"
@@ -13,10 +14,10 @@
 #include "base/synchronization/lock.h"
 #include "chrome/browser/extensions/api/api_resource.h"
 #include "chrome/browser/extensions/api/api_resource_manager.h"
-#include "chrome/browser/usb/usb_device.h"
+#include "chrome/browser/usb/usb_device_handle.h"
 #include "chrome/common/extensions/api/usb.h"
 
-class UsbDevice;
+class UsbDeviceHandle;
 
 namespace net {
 class IOBuffer;
@@ -28,10 +29,10 @@
 class UsbDeviceResource : public ApiResource {
  public:
   UsbDeviceResource(const std::string& owner_extension_id,
-                    scoped_refptr<UsbDevice> device);
+                    scoped_refptr<UsbDeviceHandle> device);
   virtual ~UsbDeviceResource();
 
-  scoped_refptr<UsbDevice> device() {
+  scoped_refptr<UsbDeviceHandle> device() {
     return device_;
   }
 
@@ -41,7 +42,7 @@
     return "UsbDeviceResourceManager";
   }
 
-  scoped_refptr<UsbDevice> device_;
+  scoped_refptr<UsbDeviceHandle> device_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbDeviceResource);
 };
diff --git a/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc b/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc
index b3088d0..db5b0e2 100644
--- a/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc
+++ b/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc
@@ -11,7 +11,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
@@ -19,10 +19,7 @@
 namespace {
 
 class BrowserPermissionsPolicyDelegateTest : public testing::Test {
-public:
- BrowserPermissionsPolicyDelegateTest()
-     : loop_(base::MessageLoop::TYPE_UI),
-       ui_thread_(content::BrowserThread::UI, &loop_) {}
+ protected:
   virtual void SetUp() {
     profile_manager_.reset(
         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
@@ -35,8 +32,7 @@
     profile_manager_.reset();
   }
  protected:
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfileManager> profile_manager_;
   TestingProfile* profile_;
 };
diff --git a/chrome/browser/extensions/extension_function_histogram_value.h b/chrome/browser/extensions/extension_function_histogram_value.h
index 2bc33fc..f9123fd 100644
--- a/chrome/browser/extensions/extension_function_histogram_value.h
+++ b/chrome/browser/extensions/extension_function_histogram_value.h
@@ -153,7 +153,7 @@
   APP_CURRENTWINDOWINTERNAL_MINIMIZE,
   DEVELOPERPRIVATE_AUTOUPDATE,
   EXPERIMENTAL_DNS_RESOLVE,
-  EXPERIMENTAL_SYSTEMINFO_MEMORY_GET,
+  DELETED_EXPERIMENTAL_SYSTEMINFO_MEMORY_GET,
   HISTORY_ADDURL,
   TABS_GET,
   BROWSERACTION_SETBADGETEXT,
@@ -545,7 +545,7 @@
   EXPERIMENTAL_SYSTEMINFO_STORAGE_REMOVEWATCH,
   EXPERIMENTAL_SYSTEMINFO_STORAGE_GETALLWATCH,
   EXPERIMENTAL_SYSTEMINFO_STORAGE_REMOVEALLWATCH,
-  SYSTEMINFO_MEMORY_GET,
+  DELETED_SYSTEMINFO_MEMORY_GET,
   ACTIVITYLOGPRIVATE_GETEXTENSIONACTIVITIES,
   RUNTIME_GETPACKAGEDIRECTORYENTRY,
   DELETED_SYSTEMINFO_DISPLAY_SETDISPLAYPROPERTIES,
@@ -570,6 +570,7 @@
   BOOKMARKMANAGERPRIVATE_REMOVETREES,
   SYSTEM_DISPLAY_GETINFO,
   SYSTEM_DISPLAY_SETDISPLAYPROPERTIES,
+  SYSTEM_MEMORY_GETINFO,
   ENUM_BOUNDARY // Last entry: Add new entries above.
 };
 
diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc
index 2ec1145..2385d0e 100644
--- a/chrome/browser/extensions/extension_protocols.cc
+++ b/chrome/browser/extensions/extension_protocols.cc
@@ -482,7 +482,7 @@
 
   std::string path = request->url().path();
   if (path.size() > 1 &&
-      path.substr(1) == extension_filenames::kGeneratedBackgroundPageFilename) {
+      path.substr(1) == extensions::kGeneratedBackgroundPageFilename) {
     return new GeneratedBackgroundPageJob(
         request, network_delegate, extension, content_security_policy);
   }
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc
index 0e41a0d..2a2ae7c 100644
--- a/chrome/browser/extensions/extension_protocols_unittest.cc
+++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -86,7 +86,8 @@
 class ExtensionProtocolTest : public testing::Test {
  public:
   ExtensionProtocolTest()
-      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
+    : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+      resource_context_(&test_url_request_context_) {}
 
   virtual void SetUp() OVERRIDE {
     testing::Test::SetUp();
@@ -128,6 +129,7 @@
   net::URLRequestJobFactoryImpl job_factory_;
   const net::URLRequestJobFactory* old_factory_;
   net::TestDelegate test_delegate_;
+  net::TestURLRequestContext test_url_request_context_;
   content::MockResourceContext resource_context_;
 };
 
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index e3ae629..5439e10 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -2896,19 +2896,11 @@
 }
 
 void ExtensionService::SetBeingReloaded(const std::string& extension_id,
-                                         bool isBeingReloaded) {
-  LOG(INFO) << "****** " << __FUNCTION__;
-  LOG(INFO) << "****** " << __FUNCTION__ << " extension_id is: "
-            << extension_id << " and isBeingReloaded is " << isBeingReloaded;
-  LOG(INFO) << "****** " << __FUNCTION__ << " Set size is "
-            << extensions_being_reloaded_.size();
-  if (isBeingReloaded) {
+                                        bool isBeingReloaded) {
+  if (isBeingReloaded)
     extensions_being_reloaded_.insert(extension_id);
-    LOG(INFO) << "****** " << __FUNCTION__ << " insert succeeded.";
-  } else {
+  else
     extensions_being_reloaded_.erase(extension_id);
-    LOG(INFO) << "****** " << __FUNCTION__ << " erase succeeded.";
-  }
 }
 
 bool ExtensionService::HasUsedWebRequest(const Extension* extension) const {
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 580e728..e8f452b 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -578,13 +578,6 @@
   InitializeExtensionService(params);
 }
 
-void ExtensionServiceTestBase::InitializeRequestContext() {
-  ASSERT_TRUE(profile_.get());
-  TestingProfile* profile =
-      static_cast<TestingProfile*>(profile_.get());
-  profile->CreateRequestContext();
-}
-
 // static
 void ExtensionServiceTestBase::SetUpTestCase() {
   ExtensionErrorReporter::Init(false);  // no noisy errors
@@ -1974,7 +1967,6 @@
 // default apps.
 TEST_F(ExtensionServiceTest, DefaultAppsGrantedPermissions) {
   InitializeEmptyExtensionService();
-  InitializeRequestContext();
   base::FilePath path = data_dir_
       .AppendASCII("permissions");
 
@@ -2607,7 +2599,6 @@
 
 TEST_F(ExtensionServiceTest, InstallAppsWithUnlimitedStorage) {
   InitializeEmptyExtensionService();
-  InitializeRequestContext();
   EXPECT_TRUE(service_->extensions()->is_empty());
 
   int pref_count = 0;
@@ -2659,7 +2650,6 @@
 
 TEST_F(ExtensionServiceTest, InstallAppsAndCheckStorageProtection) {
   InitializeEmptyExtensionService();
-  InitializeRequestContext();
   EXPECT_TRUE(service_->extensions()->is_empty());
 
   int pref_count = 0;
@@ -3744,7 +3734,6 @@
 // This tests if default apps are installed correctly.
 TEST_F(ExtensionServiceTest, DefaultAppsInstall) {
   InitializeEmptyExtensionService();
-  InitializeRequestContext();
   set_extensions_enabled(true);
 
   {
@@ -3853,7 +3842,6 @@
 // Tests reloading extensions.
 TEST_F(ExtensionServiceTest, ReloadExtensions) {
   InitializeEmptyExtensionService();
-  InitializeRequestContext();
 
   // Simple extension that should install without error.
   base::FilePath path = data_dir_.AppendASCII("good.crx");
@@ -4184,7 +4172,6 @@
 // Verifies app state is removed upon uninstall.
 TEST_F(ExtensionServiceTest, ClearAppData) {
   InitializeEmptyExtensionService();
-  InitializeRequestContext();
   ExtensionCookieCallback callback;
 
   int pref_count = 0;
@@ -5641,7 +5628,6 @@
 
 TEST_F(ExtensionServiceTest, ProcessSyncDataVersionCheck) {
   InitializeExtensionServiceWithUpdater();
-  InitializeRequestContext();
   TestSyncProcessorStub processor;
   service_->MergeDataAndStartSyncing(
       syncer::EXTENSIONS, syncer::SyncDataList(),
@@ -5709,7 +5695,6 @@
 
 TEST_F(ExtensionServiceTest, ProcessSyncDataNotInstalled) {
   InitializeExtensionServiceWithUpdater();
-  InitializeRequestContext();
   TestSyncProcessorStub processor;
   service_->MergeDataAndStartSyncing(
       syncer::EXTENSIONS, syncer::SyncDataList(),
diff --git a/chrome/browser/extensions/extension_service_unittest.h b/chrome/browser/extensions/extension_service_unittest.h
index 24be033..884681e 100644
--- a/chrome/browser/extensions/extension_service_unittest.h
+++ b/chrome/browser/extensions/extension_service_unittest.h
@@ -55,8 +55,6 @@
 
   void InitializeExtensionServiceWithUpdater();
 
-  void InitializeRequestContext();
-
   static void SetUpTestCase();
 
   virtual void SetUp() OVERRIDE;
diff --git a/chrome/browser/extensions/pack_extension_job.cc b/chrome/browser/extensions/pack_extension_job.cc
index 744eb62..da182b1 100644
--- a/chrome/browser/extensions/pack_extension_job.cc
+++ b/chrome/browser/extensions/pack_extension_job.cc
@@ -9,7 +9,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_creator.h"
-#include "chrome/common/chrome_constants.h"
+#include "extensions/common/constants.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -45,11 +45,11 @@
 
 void PackExtensionJob::Run() {
   crx_file_out_ = base::FilePath(root_directory_.value() +
-                           chrome::kExtensionFileExtension);
+                                 kExtensionFileExtension);
 
   if (key_file_.empty())
     key_file_out_ = base::FilePath(root_directory_.value() +
-                             chrome::kExtensionKeyFileExtension);
+                                   kExtensionKeyFileExtension);
 
   // TODO(aa): Need to internationalize the errors that ExtensionCreator
   // returns. See bug 20734.
diff --git a/chrome/browser/extensions/plugin_manager.cc b/chrome/browser/extensions/plugin_manager.cc
index ff77620..47df4cf 100644
--- a/chrome/browser/extensions/plugin_manager.cc
+++ b/chrome/browser/extensions/plugin_manager.cc
@@ -87,6 +87,8 @@
       PluginService::GetInstance()->PurgePluginListCache(profile_, false);
 
   } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) {
+    if (content::Details<UnloadedExtensionInfo>(details)->already_disabled)
+      return;
     const Extension* extension =
         content::Details<UnloadedExtensionInfo>(details)->extension;
 
diff --git a/chrome/browser/extensions/sandboxed_unpacker.cc b/chrome/browser/extensions/sandboxed_unpacker.cc
index e2b317f..30d6c94 100644
--- a/chrome/browser/extensions/sandboxed_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_unpacker.cc
@@ -24,7 +24,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_utility_messages.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_file_util.h"
 #include "chrome/common/extensions/extension_l10n_util.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
@@ -182,7 +181,7 @@
 bool ReadImagesFromFile(const base::FilePath& extension_path,
                         DecodedImages* images) {
   base::FilePath path =
-      extension_path.AppendASCII(extension_filenames::kDecodedImagesFilename);
+      extension_path.AppendASCII(kDecodedImagesFilename);
   std::string file_str;
   if (!file_util::ReadFileToString(path, &file_str))
     return false;
@@ -198,7 +197,7 @@
 bool ReadMessageCatalogsFromFile(const base::FilePath& extension_path,
                                  base::DictionaryValue* catalogs) {
   base::FilePath path = extension_path.AppendASCII(
-      extension_filenames::kDecodedMessageCatalogsFilename);
+      kDecodedMessageCatalogsFilename);
   std::string file_str;
   if (!file_util::ReadFileToString(path, &file_str))
     return false;
@@ -264,8 +263,7 @@
     return;  // ReportFailure() already called.
 
   // Initialize the path that will eventually contain the unpacked extension.
-  extension_root_ = temp_dir_.path().AppendASCII(
-      extension_filenames::kTempExtensionName);
+  extension_root_ = temp_dir_.path().AppendASCII(kTempExtensionName);
   PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackUnpackedCrxPathLength",
                         extension_root_);
 
diff --git a/chrome/browser/extensions/sandboxed_unpacker_unittest.cc b/chrome/browser/extensions/sandboxed_unpacker_unittest.cc
index 1bf0018..39f634e 100644
--- a/chrome/browser/extensions/sandboxed_unpacker_unittest.cc
+++ b/chrome/browser/extensions/sandboxed_unpacker_unittest.cc
@@ -97,8 +97,7 @@
   }
 
   base::FilePath GetInstallPath() {
-    return client_->temp_dir().AppendASCII(
-        extension_filenames::kTempExtensionName);
+    return client_->temp_dir().AppendASCII(kTempExtensionName);
   }
 
  protected:
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index 8fdd4bf..3c78899 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -239,7 +239,6 @@
       : prefs_(prefs),
         pending_extension_manager_(*this),
         blacklist_(prefs_->prefs()) {
-    profile_.CreateRequestContext();
   }
 
   virtual ~MockService() {}
@@ -498,13 +497,10 @@
 class ExtensionUpdaterTest : public testing::Test {
  public:
   ExtensionUpdaterTest()
-      : test_browser_thread_bundle_(
+      : thread_bundle_(
             content::TestBrowserThreadBundle::IO_MAINLOOP) {
   }
 
-  virtual ~ExtensionUpdaterTest() {
-  }
-
   virtual void SetUp() OVERRIDE {
     prefs_.reset(new TestExtensionPrefs(base::MessageLoopProxy::current()));
     content::RenderProcessHost::SetRunRendererInProcess(true);
@@ -751,7 +747,6 @@
 
   void TestDetermineUpdates() {
     TestingProfile profile;
-    profile.CreateRequestContext();
     MockExtensionDownloaderDelegate delegate;
     ExtensionDownloader downloader(&delegate, profile.GetRequestContext());
 
@@ -795,7 +790,6 @@
     SetupPendingExtensionManagerForTest(3, GURL(), pending_extension_manager);
 
     TestingProfile profile;
-    profile.CreateRequestContext();
     MockExtensionDownloaderDelegate delegate;
     ExtensionDownloader downloader(&delegate, profile.GetRequestContext());
 
@@ -1502,7 +1496,7 @@
   scoped_ptr<TestExtensionPrefs> prefs_;
 
  private:
-  content::TestBrowserThreadBundle test_browser_thread_bundle_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
 #if defined OS_CHROMEOS
   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/extensions/web_view_browsertest.cc b/chrome/browser/extensions/web_view_browsertest.cc
index 3f56d70..08b2f7d 100644
--- a/chrome/browser/extensions/web_view_browsertest.cc
+++ b/chrome/browser/extensions/web_view_browsertest.cc
@@ -1382,3 +1382,45 @@
   ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/document_interactive"))
                   << message_;
 }
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestAlertDialog) {
+  TestHelper("testAlertDialog",
+             "DoneDialogTest.PASSED",
+             "DoneDialogTest.FAILED",
+             "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialog) {
+  TestHelper("testConfirmDialog",
+             "DoneDialogTest.PASSED",
+             "DoneDialogTest.FAILED",
+             "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialogCancel) {
+  TestHelper("testConfirmDialogCancel",
+             "DoneDialogTest.PASSED",
+             "DoneDialogTest.FAILED",
+             "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialogDefaultCancel) {
+  TestHelper("testConfirmDialogDefaultCancel",
+             "DoneDialogTest.PASSED",
+             "DoneDialogTest.FAILED",
+             "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialogDefaultGCCancel) {
+  TestHelper("testConfirmDialogDefaultGCCancel",
+             "DoneDialogTest.PASSED",
+             "DoneDialogTest.FAILED",
+             "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestPromptDialog) {
+  TestHelper("testPromptDialog",
+             "DoneDialogTest.PASSED",
+             "DoneDialogTest.FAILED",
+             "web_view/dialog");
+}
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc
index 1563afb..7ebb814 100644
--- a/chrome/browser/extensions/window_open_apitest.cc
+++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -328,15 +328,10 @@
   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 1, num_popups, 0));
 }
 
-#if defined(OS_CHROMEOS)
-// TODO(derat): See if there's some way to get this to work on Chrome OS.  It
-// crashes there, apparently because we automatically reload crashed pages:
-// http:/crbug.com/161073
-#define MAYBE_ClosePanelsOnExtensionCrash DISABLED_ClosePanelsOnExtensionCrash
-#else
-#define MAYBE_ClosePanelsOnExtensionCrash ClosePanelsOnExtensionCrash
-#endif
-IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, MAYBE_ClosePanelsOnExtensionCrash) {
+// This test isn't applicable on Chrome OS, which automatically reloads
+// crashed pages.
+#if !defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, ClosePanelsOnExtensionCrash) {
 #if defined(USE_ASH_PANELS)
   // On Ash, new panel windows open as popup windows instead.
   int num_popups = 4;
@@ -386,6 +381,7 @@
   // Only expect panels to close. The rest stay open to show a sad-tab.
   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 2, num_popups, 0));
 }
+#endif  // !defined(OS_CHROMEOS)
 
 #if defined(USE_ASH_PANELS)
 // This test is not applicable on Ash. The modified window.open behavior only
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
index cdf6bc4..e3bfc92 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
@@ -11,12 +11,11 @@
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/content_settings/permission_request_id.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/suggest_permission_util.h"
-#include "chrome/browser/geolocation/geolocation_infobar_queue_controller.h"
-#include "chrome/browser/geolocation/geolocation_permission_request_id.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/common/extensions/extension.h"
@@ -35,9 +34,9 @@
 
 ChromeGeolocationPermissionContext::~ChromeGeolocationPermissionContext() {
   // ChromeGeolocationPermissionContext may be destroyed on either the UI thread
-  // or the IO thread, but the GeolocationInfobarQueueController must have been
+  // or the IO thread, but the PermissionQueueController must have been
   // destroyed on the UI thread.
-  DCHECK(!geolocation_infobar_queue_controller_.get());
+  DCHECK(!permission_queue_controller_.get());
 }
 
 void ChromeGeolocationPermissionContext::RequestGeolocationPermission(
@@ -62,7 +61,7 @@
 
   content::WebContents* web_contents =
       tab_util::GetWebContentsByID(render_process_id, render_view_id);
-  const GeolocationPermissionRequestID id(render_process_id, render_view_id,
+  const PermissionRequestID id(render_process_id, render_view_id,
                                           bridge_id);
   ExtensionService* extension_service =
       extensions::ExtensionSystem::Get(profile_)->extension_service();
@@ -112,12 +111,12 @@
     int render_view_id,
     int bridge_id,
     const GURL& requesting_frame) {
-  CancelPendingInfoBarRequest(GeolocationPermissionRequestID(
+  CancelPendingInfoBarRequest(PermissionRequestID(
       render_process_id, render_view_id, bridge_id));
 }
 
 void ChromeGeolocationPermissionContext::DecidePermission(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
     base::Callback<void(bool)> callback) {
@@ -145,12 +144,12 @@
 
 void ChromeGeolocationPermissionContext::ShutdownOnUIThread() {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  geolocation_infobar_queue_controller_.reset();
+  permission_queue_controller_.reset();
   shutting_down_ = true;
 }
 
 void ChromeGeolocationPermissionContext::PermissionDecided(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
     base::Callback<void(bool)> callback,
@@ -159,7 +158,7 @@
 }
 
 void ChromeGeolocationPermissionContext::NotifyPermissionSet(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     base::Callback<void(bool)> callback,
     bool allowed) {
@@ -177,23 +176,24 @@
   callback.Run(allowed);
 }
 
-GeolocationInfoBarQueueController*
+PermissionQueueController*
     ChromeGeolocationPermissionContext::QueueController() {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   DCHECK(!shutting_down_);
-  if (!geolocation_infobar_queue_controller_)
-    geolocation_infobar_queue_controller_.reset(CreateQueueController());
-  return geolocation_infobar_queue_controller_.get();
+  if (!permission_queue_controller_)
+    permission_queue_controller_.reset(CreateQueueController());
+  return permission_queue_controller_.get();
 }
 
-GeolocationInfoBarQueueController*
+PermissionQueueController*
     ChromeGeolocationPermissionContext::CreateQueueController() {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  return new GeolocationInfoBarQueueController(profile());
+  return new PermissionQueueController(profile(),
+                                       CONTENT_SETTINGS_TYPE_GEOLOCATION);
 }
 
 void ChromeGeolocationPermissionContext::CancelPendingInfoBarRequest(
-    const GeolocationPermissionRequestID& id) {
+    const PermissionRequestID& id) {
   if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context.h b/chrome/browser/geolocation/chrome_geolocation_permission_context.h
index fde8d5a..06b324d 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context.h
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context.h
@@ -8,15 +8,15 @@
 #include <string>
 
 #include "base/memory/scoped_ptr.h"
-#include "chrome/browser/geolocation/geolocation_infobar_queue_controller.h"
+#include "chrome/browser/content_settings/permission_queue_controller.h"
 #include "content/public/browser/geolocation_permission_context.h"
 
-class GeolocationPermissionRequestID;
+class PermissionRequestID;
 class Profile;
 
 // Chrome specific implementation of GeolocationPermissionContext; manages
 // Geolocation permissions flow, and delegates UI handling via
-// GeolocationInfoBarQueueController.
+// PermissionQueueController.
 class ChromeGeolocationPermissionContext
     : public content::GeolocationPermissionContext {
  public:
@@ -45,13 +45,13 @@
 
   // Return an instance of the infobar queue controller, creating it
   // if necessary.
-  GeolocationInfoBarQueueController* QueueController();
+  PermissionQueueController* QueueController();
 
   // Notifies whether or not the corresponding bridge is allowed to use
   // geolocation via
   // GeolocationPermissionContext::SetGeolocationPermissionResponse().
   // Called on the UI thread.
-  void NotifyPermissionSet(const GeolocationPermissionRequestID& id,
+  void NotifyPermissionSet(const PermissionRequestID& id,
                            const GURL& requesting_frame,
                            base::Callback<void(bool)> callback,
                            bool allowed);
@@ -61,7 +61,7 @@
   // Calls PermissionDecided if permission can be decided non-interactively,
   // or NotifyPermissionSet if permission decided by presenting an
   // infobar to the user. Called on the UI thread.
-  virtual void DecidePermission(const GeolocationPermissionRequestID& id,
+  virtual void DecidePermission(const PermissionRequestID& id,
                                 const GURL& requesting_frame,
                                 const GURL& embedder,
                                 base::Callback<void(bool)> callback);
@@ -70,25 +70,24 @@
   // the user. Can be overridden to introduce additional UI flow.
   // Should ultimately ensure that NotifyPermissionSet is called.
   // Called on the UI thread.
-  virtual void PermissionDecided(const GeolocationPermissionRequestID& id,
+  virtual void PermissionDecided(const PermissionRequestID& id,
                                  const GURL& requesting_frame,
                                  const GURL& embedder,
                                  base::Callback<void(bool)> callback,
                                  bool allowed);
 
-  // Create an InfoBarQueueController. overriden in derived classes to provide
-  // additional UI flow.  Called on the UI thread.
-  virtual GeolocationInfoBarQueueController* CreateQueueController();
+  // Create an PermissionQueueController. overriden in derived classes to
+  // provide additional UI flow.  Called on the UI thread.
+  virtual PermissionQueueController* CreateQueueController();
 
  private:
   // Removes any pending InfoBar request.
-  void CancelPendingInfoBarRequest(const GeolocationPermissionRequestID& id);
+  void CancelPendingInfoBarRequest(const PermissionRequestID& id);
 
   // These must only be accessed from the UI thread.
   Profile* const profile_;
   bool shutting_down_;
-  scoped_ptr<GeolocationInfoBarQueueController>
-      geolocation_infobar_queue_controller_;
+  scoped_ptr<PermissionQueueController> permission_queue_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeGeolocationPermissionContext);
 };
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context_android.cc b/chrome/browser/geolocation/chrome_geolocation_permission_context_android.cc
index 3a8a978..afb213c 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context_android.cc
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context_android.cc
@@ -22,7 +22,7 @@
 }
 
 void ChromeGeolocationPermissionContextAndroid::DecidePermission(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
     base::Callback<void(bool)> callback) {
@@ -41,7 +41,7 @@
 }
 
 void ChromeGeolocationPermissionContextAndroid::PermissionDecided(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
     base::Callback<void(bool)> callback,
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context_android.h b/chrome/browser/geolocation/chrome_geolocation_permission_context_android.h
index 0dbed89..c14f224 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context_android.h
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context_android.h
@@ -22,12 +22,12 @@
   virtual ~ChromeGeolocationPermissionContextAndroid();
 
   // ChromeGeolocationPermissionContext implementation:
-  virtual void DecidePermission(const GeolocationPermissionRequestID& id,
+  virtual void DecidePermission(const PermissionRequestID& id,
                                 const GURL& requesting_frame,
                                 const GURL& embedder,
                                 base::Callback<void(bool)> callback) OVERRIDE;
 
-  virtual void PermissionDecided(const GeolocationPermissionRequestID& id,
+  virtual void PermissionDecided(const PermissionRequestID& id,
                                  const GURL& requesting_frame,
                                  const GURL& embedder,
                                  base::Callback<void(bool)> callback,
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc
index 10eae81..7a1c0e5 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc
@@ -14,9 +14,9 @@
 #include "base/synchronization/waitable_event.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/content_settings/permission_request_id.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/geolocation/chrome_geolocation_permission_context_factory.h"
-#include "chrome/browser/geolocation/geolocation_permission_request_id.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
 #include "chrome/browser/infobars/infobar.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -101,8 +101,8 @@
   virtual void SetUp() OVERRIDE;
   virtual void TearDown() OVERRIDE;
 
-  GeolocationPermissionRequestID RequestID(int bridge_id);
-  GeolocationPermissionRequestID RequestIDForTab(int tab, int bridge_id);
+  PermissionRequestID RequestID(int bridge_id);
+  PermissionRequestID RequestIDForTab(int tab, int bridge_id);
   InfoBarService* infobar_service() {
     return InfoBarService::FromWebContents(web_contents());
   }
@@ -110,12 +110,11 @@
     return InfoBarService::FromWebContents(extra_tabs_[tab]);
   }
 
-  void RequestGeolocationPermission(const GeolocationPermissionRequestID& id,
+  void RequestGeolocationPermission(const PermissionRequestID& id,
                                     const GURL& requesting_frame);
-  void CancelGeolocationPermissionRequest(
-      const GeolocationPermissionRequestID& id,
-      const GURL& requesting_frame);
-  void PermissionResponse(const GeolocationPermissionRequestID& id,
+  void CancelGeolocationPermissionRequest(const PermissionRequestID& id,
+                                          const GURL& requesting_frame);
+  void PermissionResponse(const PermissionRequestID& id,
                           bool allowed);
   void CheckPermissionMessageSent(int bridge_id, bool allowed);
   void CheckPermissionMessageSentForTab(int tab, int bridge_id, bool allowed);
@@ -136,24 +135,25 @@
   base::hash_map<int, std::pair<int, bool> > responses_;
 };
 
-GeolocationPermissionRequestID GeolocationPermissionContextTests::RequestID(
+PermissionRequestID GeolocationPermissionContextTests::RequestID(
     int bridge_id) {
-  return GeolocationPermissionRequestID(
+  return PermissionRequestID(
       web_contents()->GetRenderProcessHost()->GetID(),
       web_contents()->GetRenderViewHost()->GetRoutingID(),
       bridge_id);
 }
 
-GeolocationPermissionRequestID
-    GeolocationPermissionContextTests::RequestIDForTab(int tab, int bridge_id) {
-  return GeolocationPermissionRequestID(
+PermissionRequestID GeolocationPermissionContextTests::RequestIDForTab(
+    int tab,
+    int bridge_id) {
+  return PermissionRequestID(
       extra_tabs_[tab]->GetRenderProcessHost()->GetID(),
       extra_tabs_[tab]->GetRenderViewHost()->GetRoutingID(),
       bridge_id);
 }
 
 void GeolocationPermissionContextTests::RequestGeolocationPermission(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame) {
   geolocation_permission_context_->RequestGeolocationPermission(
       id.render_process_id(), id.render_view_id(), id.bridge_id(),
@@ -163,7 +163,7 @@
 }
 
 void GeolocationPermissionContextTests::CancelGeolocationPermissionRequest(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     const GURL& requesting_frame) {
   geolocation_permission_context_->CancelGeolocationPermissionRequest(
       id.render_process_id(), id.render_view_id(), id.bridge_id(),
@@ -171,7 +171,7 @@
 }
 
 void GeolocationPermissionContextTests::PermissionResponse(
-    const GeolocationPermissionRequestID& id,
+    const PermissionRequestID& id,
     bool allowed) {
   responses_[id.render_process_id()] = std::make_pair(id.bridge_id(), allowed);
 }
diff --git a/chrome/browser/geolocation/geolocation_infobar_delegate.cc b/chrome/browser/geolocation/geolocation_infobar_delegate.cc
index 017c570..4e9c37d 100644
--- a/chrome/browser/geolocation/geolocation_infobar_delegate.cc
+++ b/chrome/browser/geolocation/geolocation_infobar_delegate.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/geolocation/geolocation_infobar_delegate.h"
 
-#include "chrome/browser/geolocation/geolocation_infobar_queue_controller.h"
+#include "chrome/browser/content_settings/permission_queue_controller.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "content/public/browser/navigation_details.h"
@@ -27,8 +27,8 @@
 // static
 InfoBarDelegate* GeolocationInfoBarDelegate::Create(
     InfoBarService* infobar_service,
-    GeolocationInfoBarQueueController* controller,
-    const GeolocationPermissionRequestID& id,
+    PermissionQueueController* controller,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     const std::string& display_languages) {
   const content::NavigationEntry* committed_entry =
@@ -41,8 +41,8 @@
 
 GeolocationInfoBarDelegate::GeolocationInfoBarDelegate(
     InfoBarService* infobar_service,
-    GeolocationInfoBarQueueController* controller,
-    const GeolocationPermissionRequestID& id,
+    PermissionQueueController* controller,
+    const PermissionRequestID& id,
     const GURL& requesting_frame,
     int contents_unique_id,
     const std::string& display_languages)
diff --git a/chrome/browser/geolocation/geolocation_infobar_delegate.h b/chrome/browser/geolocation/geolocation_infobar_delegate.h
index 4e63f64..93a6ab7 100644
--- a/chrome/browser/geolocation/geolocation_infobar_delegate.h
+++ b/chrome/browser/geolocation/geolocation_infobar_delegate.h
@@ -7,11 +7,11 @@
 
 #include <string>
 
-#include "chrome/browser/geolocation/geolocation_permission_request_id.h"
+#include "chrome/browser/content_settings/permission_request_id.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
 #include "url/gurl.h"
 
-class GeolocationInfoBarQueueController;
+class PermissionQueueController;
 class InfoBarService;
 
 // GeolocationInfoBarDelegates are created by the
@@ -22,15 +22,15 @@
   // Creates a geolocation infobar delegate and adds it to |infobar_service|.
   // Returns the delegate if it was successfully added.
   static InfoBarDelegate* Create(InfoBarService* infobar_service,
-                                 GeolocationInfoBarQueueController* controller,
-                                 const GeolocationPermissionRequestID& id,
+                                 PermissionQueueController* controller,
+                                 const PermissionRequestID& id,
                                  const GURL& requesting_frame,
                                  const std::string& display_languages);
 
  protected:
   GeolocationInfoBarDelegate(InfoBarService* infobar_service,
-                             GeolocationInfoBarQueueController* controller,
-                             const GeolocationPermissionRequestID& id,
+                             PermissionQueueController* controller,
+                             const PermissionRequestID& id,
                              const GURL& requesting_frame,
                              int contents_unique_id,
                              const std::string& display_languages);
@@ -54,8 +54,8 @@
   virtual string16 GetLinkText() const OVERRIDE;
   virtual bool LinkClicked(WindowOpenDisposition disposition) OVERRIDE;
 
-  GeolocationInfoBarQueueController* controller_;
-  const GeolocationPermissionRequestID id_;
+  PermissionQueueController* controller_;
+  const PermissionRequestID id_;
   GURL requesting_frame_;
   int contents_unique_id_;
   std::string display_languages_;
diff --git a/chrome/browser/geolocation/geolocation_infobar_delegate_android.cc b/chrome/browser/geolocation/geolocation_infobar_delegate_android.cc
index 032b7f4..52c2b5b 100644
--- a/chrome/browser/geolocation/geolocation_infobar_delegate_android.cc
+++ b/chrome/browser/geolocation/geolocation_infobar_delegate_android.cc
@@ -13,8 +13,8 @@
 
 GeolocationInfoBarDelegateAndroid::GeolocationInfoBarDelegateAndroid(
     InfoBarService* infobar_service,
-    GeolocationInfoBarQueueController* controller,
-    const GeolocationPermissionRequestID& id,
+    PermissionQueueController* controller,
+    const PermissionRequestID& id,
     const GURL& requesting_frame_url,
     int contents_unique_id,
     const std::string& display_languages)
diff --git a/chrome/browser/geolocation/geolocation_infobar_delegate_android.h b/chrome/browser/geolocation/geolocation_infobar_delegate_android.h
index f5059e3..e247f7f 100644
--- a/chrome/browser/geolocation/geolocation_infobar_delegate_android.h
+++ b/chrome/browser/geolocation/geolocation_infobar_delegate_android.h
@@ -14,8 +14,8 @@
  public:
   GeolocationInfoBarDelegateAndroid(
       InfoBarService* infobar_service,
-      GeolocationInfoBarQueueController* controller,
-      const GeolocationPermissionRequestID& id,
+      PermissionQueueController* controller,
+      const PermissionRequestID& id,
       const GURL& requesting_frame_url,
       int contents_unique_id,
       const std::string& display_languages);
diff --git a/chrome/browser/geolocation/geolocation_permission_request_id.cc b/chrome/browser/geolocation/geolocation_permission_request_id.cc
deleted file mode 100644
index 89df8c4..0000000
--- a/chrome/browser/geolocation/geolocation_permission_request_id.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 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/geolocation/geolocation_permission_request_id.h"
-
-#include "base/strings/stringprintf.h"
-
-
-GeolocationPermissionRequestID::GeolocationPermissionRequestID(
-    int render_process_id,
-    int render_view_id,
-    int bridge_id)
-    : render_process_id_(render_process_id),
-      render_view_id_(render_view_id),
-      bridge_id_(bridge_id) {
-}
-
-GeolocationPermissionRequestID::~GeolocationPermissionRequestID() {
-}
-
-bool GeolocationPermissionRequestID::Equals(
-    const GeolocationPermissionRequestID& other) const {
-  return IsForSameTabAs(other) && (bridge_id_ == other.bridge_id_);
-}
-
-bool GeolocationPermissionRequestID::IsForSameTabAs(
-    const GeolocationPermissionRequestID& other) const {
-  return (render_process_id_ == other.render_process_id_) &&
-      (render_view_id_ == other.render_view_id_);
-}
-
-std::string GeolocationPermissionRequestID::ToString() const {
-  return base::StringPrintf("%d,%d,%d", render_process_id_, render_view_id_,
-                            bridge_id_);
-}
diff --git a/chrome/browser/geolocation/geolocation_permission_request_id.h b/chrome/browser/geolocation/geolocation_permission_request_id.h
deleted file mode 100644
index eb29de9..0000000
--- a/chrome/browser/geolocation/geolocation_permission_request_id.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 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_GEOLOCATION_GEOLOCATION_PERMISSION_REQUEST_ID_H_
-#define CHROME_BROWSER_GEOLOCATION_GEOLOCATION_PERMISSION_REQUEST_ID_H_
-
-#include <string>
-
-// Uniquely identifies a particular geolocation permission request.
-class GeolocationPermissionRequestID {
- public:
-  GeolocationPermissionRequestID(int render_process_id,
-                                 int render_view_id,
-                                 int bridge_id);
-  ~GeolocationPermissionRequestID();
-
-  int render_process_id() const { return render_process_id_; }
-  int render_view_id() const { return render_view_id_; }
-  int bridge_id() const { return bridge_id_; }
-
-  bool Equals(const GeolocationPermissionRequestID& other) const;
-  bool IsForSameTabAs(const GeolocationPermissionRequestID& other) const;
-  std::string ToString() const;
-
- private:
-  int render_process_id_;
-  int render_view_id_;
-  int bridge_id_;
-
-  // Purposefully do not disable copying, as this is stored in STL containers.
-};
-
-#endif  // CHROME_BROWSER_GEOLOCATION_GEOLOCATION_PERMISSION_REQUEST_ID_H_
diff --git a/chrome/browser/google/google_url_tracker_unittest.cc b/chrome/browser/google/google_url_tracker_unittest.cc
index 88bdc5a..1ddda26 100644
--- a/chrome/browser/google/google_url_tracker_unittest.cc
+++ b/chrome/browser/google/google_url_tracker_unittest.cc
@@ -18,14 +18,13 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class GoogleURLTrackerTest;
 
-
 namespace {
 
 // TestInfoBarDelegate --------------------------------------------------------
@@ -249,8 +248,7 @@
 
   // These are required by the TestURLFetchers GoogleURLTracker will create (see
   // test_url_fetcher_factory.h).
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   // Creating this allows us to call
   // net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests().
   scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
@@ -283,8 +281,7 @@
 }
 
 GoogleURLTrackerTest::GoogleURLTrackerTest()
-    : message_loop_(base::MessageLoop::TYPE_IO),
-      io_thread_(content::BrowserThread::IO, &message_loop_) {
+    : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
   GoogleURLTrackerFactory::GetInstance()->RegisterUserPrefsOnBrowserContext(
       &profile_);
 }
diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc
index 5a0dc26..6f7865c 100644
--- a/chrome/browser/history/download_database.cc
+++ b/chrome/browser/history/download_database.cc
@@ -111,6 +111,7 @@
 const int DownloadDatabase::kDangerTypeUncommonContent = 5;
 const int DownloadDatabase::kDangerTypeUserValidated = 6;
 const int DownloadDatabase::kDangerTypeDangerousHost = 7;
+const int DownloadDatabase::kDangerTypePotentiallyUnwanted = 8;
 
 int DownloadDatabase::StateToInt(DownloadItem::DownloadState state) {
   switch (state) {
@@ -156,6 +157,8 @@
       return DownloadDatabase::kDangerTypeUserValidated;
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
       return DownloadDatabase::kDangerTypeDangerousHost;
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+      return DownloadDatabase::kDangerTypePotentiallyUnwanted;
     case content::DOWNLOAD_DANGER_TYPE_MAX:
       NOTREACHED();
       return DownloadDatabase::kDangerTypeInvalid;
@@ -182,6 +185,8 @@
       return content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED;
     case DownloadDatabase::kDangerTypeDangerousHost:
       return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
+    case DownloadDatabase::kDangerTypePotentiallyUnwanted:
+      return content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
     default:
       return content::DOWNLOAD_DANGER_TYPE_MAX;
   }
diff --git a/chrome/browser/history/download_database.h b/chrome/browser/history/download_database.h
index 1550a0a..12e5a1e 100644
--- a/chrome/browser/history/download_database.h
+++ b/chrome/browser/history/download_database.h
@@ -94,6 +94,7 @@
   static const int kDangerTypeUncommonContent;
   static const int kDangerTypeUserValidated;
   static const int kDangerTypeDangerousHost;
+  static const int kDangerTypePotentiallyUnwanted;
 
   // Fixes state of the download entries. Sometimes entries with IN_PROGRESS
   // state are not updated during browser shutdown (particularly when crashing).
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 3688996..44cd6cd 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -439,6 +439,12 @@
   return globals_;
 }
 
+void IOThread::SetGlobalsForTesting(Globals* globals) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK(!globals || !globals_);
+  globals_ = globals;
+}
+
 ChromeNetLog* IOThread::net_log() {
   return net_log_;
 }
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index 4b1b9ef..4408a50 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -187,6 +187,11 @@
   // Can only be called on the IO thread.
   Globals* globals();
 
+  // Allows overriding Globals in tests where IOThread::Init() and
+  // IOThread::CleanUp() are not called.  This allows for injecting mocks into
+  // IOThread global objects.
+  void SetGlobalsForTesting(Globals* globals);
+
   ChromeNetLog* net_log();
 
   // Handles changing to On The Record mode, discarding confidential data.
diff --git a/chrome/browser/local_discovery/privet_confirm_api_flow.cc b/chrome/browser/local_discovery/privet_confirm_api_flow.cc
new file mode 100644
index 0000000..8f9f6ce
--- /dev/null
+++ b/chrome/browser/local_discovery/privet_confirm_api_flow.cc
@@ -0,0 +1,103 @@
+// 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 "base/json/json_reader.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/local_discovery/privet_confirm_api_flow.h"
+#include "chrome/common/cloud_print/cloud_print_constants.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_request_status.h"
+
+namespace local_discovery {
+
+namespace {
+const char kCloudPrintOAuthHeaderFormat[] = "Authorization: Bearer %s";
+}
+
+PrivetConfirmApiCallFlow::PrivetConfirmApiCallFlow(
+    net::URLRequestContextGetter* request_context,
+    OAuth2TokenService* token_service,
+    const GURL& automated_claim_url,
+    const ResponseCallback& callback)
+    : request_context_(request_context),
+      token_service_(token_service),
+      automated_claim_url_(automated_claim_url),
+      callback_(callback) {
+}
+
+PrivetConfirmApiCallFlow::~PrivetConfirmApiCallFlow() {
+}
+
+void PrivetConfirmApiCallFlow::Start() {
+  OAuth2TokenService::ScopeSet oauth_scopes;
+  oauth_scopes.insert(cloud_print::kCloudPrintAuth);
+  oauth_request_ = token_service_->StartRequest(oauth_scopes, this);
+}
+
+void PrivetConfirmApiCallFlow::OnGetTokenSuccess(
+    const OAuth2TokenService::Request* request,
+    const std::string& access_token,
+    const base::Time& expiration_time) {
+  url_fetcher_.reset(net::URLFetcher::Create(automated_claim_url_,
+                                             net::URLFetcher::GET,
+                                             this));
+  url_fetcher_->SetRequestContext(request_context_.get());
+  std::string authorization_header =
+      base::StringPrintf(kCloudPrintOAuthHeaderFormat, access_token.c_str());
+
+  url_fetcher_->AddExtraRequestHeader(
+      cloud_print::kChromeCloudPrintProxyHeader);
+  url_fetcher_->AddExtraRequestHeader(authorization_header);
+  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
+                             net::LOAD_DO_NOT_SEND_COOKIES);
+  url_fetcher_->Start();
+}
+
+void PrivetConfirmApiCallFlow::OnGetTokenFailure(
+    const OAuth2TokenService::Request* request,
+    const GoogleServiceAuthError& error) {
+  callback_.Run(ERROR_TOKEN);
+}
+
+void PrivetConfirmApiCallFlow::OnURLFetchComplete(
+    const net::URLFetcher* source) {
+  // TODO(noamsml): Error logging.
+
+  // TODO(noamsml): Extract this and PrivetURLFetcher::OnURLFetchComplete into
+  // one helper method.
+  std::string response_str;
+
+  if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS ||
+      !source->GetResponseAsString(&response_str)) {
+    callback_.Run(ERROR_NETWORK);
+    return;
+  }
+
+  if (source->GetResponseCode() != net::HTTP_OK) {
+    callback_.Run(ERROR_HTTP_CODE);
+    return;
+  }
+
+  base::JSONReader reader;
+  scoped_ptr<const base::Value> value(reader.Read(response_str));
+  const base::DictionaryValue* dictionary_value;
+  bool success = false;
+
+  if (!value.get() || !value->GetAsDictionary(&dictionary_value)
+      || !dictionary_value->GetBoolean(cloud_print::kSuccessValue, &success)) {
+    callback_.Run(ERROR_MALFORMED_RESPONSE);
+    return;
+  }
+
+  if (success) {
+    callback_.Run(SUCCESS);
+  } else {
+    callback_.Run(ERROR_FROM_SERVER);
+  }
+}
+
+}  // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privet_confirm_api_flow.h b/chrome/browser/local_discovery/privet_confirm_api_flow.h
new file mode 100644
index 0000000..dadcf83
--- /dev/null
+++ b/chrome/browser/local_discovery/privet_confirm_api_flow.h
@@ -0,0 +1,62 @@
+// 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_LOCAL_DISCOVERY_PRIVET_CONFIRM_API_FLOW_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_PRIVET_CONFIRM_API_FLOW_H_
+
+#include <string>
+
+#include "chrome/browser/local_discovery/privet_http.h"
+#include "chrome/browser/signin/oauth2_token_service.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace local_discovery {
+
+// API call flow for server-side communication with cloudprint for registration.
+class PrivetConfirmApiCallFlow : public net::URLFetcherDelegate,
+                                 public OAuth2TokenService::Consumer {
+ public:
+  // TODO(noamsml): Better error model for this class.
+  enum Status {
+    SUCCESS,
+    ERROR_TOKEN,
+    ERROR_NETWORK,
+    ERROR_HTTP_CODE,
+    ERROR_FROM_SERVER,
+    ERROR_MALFORMED_RESPONSE
+  };
+  typedef base::Callback<void(Status /*success*/)> ResponseCallback;
+
+  PrivetConfirmApiCallFlow(net::URLRequestContextGetter* request_context,
+                           OAuth2TokenService* token_service_,
+                           const GURL& automated_claim_url,
+                           const ResponseCallback& callback);
+  virtual ~PrivetConfirmApiCallFlow();
+
+  void Start();
+
+  // net::URLFetcherDelegate implementation:
+  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+
+  // OAuth2TokenService::Consumer implementation:
+  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:
+  scoped_ptr<net::URLFetcher> url_fetcher_;
+  scoped_ptr<OAuth2TokenService::Request> oauth_request_;
+  scoped_refptr<net::URLRequestContextGetter> request_context_;
+  OAuth2TokenService* token_service_;
+  GURL automated_claim_url_;
+  ResponseCallback callback_;
+};
+
+}  // namespace local_discovery
+
+#endif  // CHROME_BROWSER_LOCAL_DISCOVERY_PRIVET_CONFIRM_API_FLOW_H_
diff --git a/chrome/browser/local_discovery/privet_confirm_api_flow_unittest.cc b/chrome/browser/local_discovery/privet_confirm_api_flow_unittest.cc
new file mode 100644
index 0000000..0ec365e
--- /dev/null
+++ b/chrome/browser/local_discovery/privet_confirm_api_flow_unittest.cc
@@ -0,0 +1,177 @@
+// 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 "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "chrome/browser/local_discovery/privet_confirm_api_flow.h"
+#include "content/public/test/test_browser_thread.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::NiceMock;
+
+namespace local_discovery {
+
+namespace {
+
+const char kSampleConfirmResponse[] = "{"
+    "   \"success\": true"
+    "}";
+
+const char kFailedConfirmResponse[] = "{"
+    "   \"success\": false"
+    "}";
+
+
+const char kFailedConfirmResponseBadJson[] = "["
+    "   \"success\""
+    "]";
+
+class TestOAuth2TokenService : public OAuth2TokenService {
+ public:
+  explicit TestOAuth2TokenService(net::URLRequestContextGetter* request_context)
+      : request_context_(request_context) {
+  }
+ protected:
+  virtual std::string GetRefreshToken() OVERRIDE {
+    return "SampleToken";
+  }
+
+  virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE {
+    return request_context_.get();
+  }
+
+ private:
+  scoped_refptr<net::URLRequestContextGetter> request_context_;
+};
+
+class MockableConfirmCallback {
+ public:
+  MOCK_METHOD1(ConfirmCallback, void(PrivetConfirmApiCallFlow::Status));
+
+  PrivetConfirmApiCallFlow::ResponseCallback callback() {
+    return base::Bind(&MockableConfirmCallback::ConfirmCallback,
+                      base::Unretained(this));
+  }
+};
+
+class PrivetConfirmApiFlowTest : public testing::Test {
+ public:
+  PrivetConfirmApiFlowTest()
+      : ui_thread_(content::BrowserThread::UI,
+                   &loop_),
+        request_context_(new net::TestURLRequestContextGetter(
+            base::MessageLoopProxy::current())),
+        token_service_(request_context_.get()) {
+    ui_thread_.Stop();  // HACK: Fake being on the UI thread
+  }
+
+  virtual ~PrivetConfirmApiFlowTest() {
+  }
+
+ protected:
+  base::MessageLoopForUI loop_;
+  content::TestBrowserThread ui_thread_;
+  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+  net::TestURLFetcherFactory fetcher_factory_;
+  TestOAuth2TokenService token_service_;
+  MockableConfirmCallback callback_;
+};
+
+TEST_F(PrivetConfirmApiFlowTest, Success) {
+  PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
+                                        &token_service_,
+                                        GURL("http://SoMeUrL.com"),
+                                        callback_.callback());
+
+  confirm_flow.OnGetTokenSuccess(NULL, "SomeToken", base::Time());
+  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
+
+  EXPECT_EQ(GURL("http://SoMeUrL.com"), fetcher->GetOriginalURL());
+
+  net::HttpRequestHeaders headers;
+  fetcher->GetExtraRequestHeaders(&headers);
+  std::string oauth_header;
+  std::string proxy;
+  EXPECT_TRUE(headers.GetHeader("Authorization", &oauth_header));
+  EXPECT_EQ("Bearer SomeToken", oauth_header);
+  EXPECT_TRUE(headers.GetHeader("X-Cloudprint-Proxy", &proxy));
+  EXPECT_EQ("Chrome", proxy);
+
+  fetcher->SetResponseString(kSampleConfirmResponse);
+  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
+                                            net::OK));
+  fetcher->set_response_code(200);
+
+  EXPECT_CALL(callback_, ConfirmCallback(PrivetConfirmApiCallFlow::SUCCESS));
+
+  fetcher->delegate()->OnURLFetchComplete(fetcher);
+}
+
+TEST_F(PrivetConfirmApiFlowTest, BadToken) {
+  PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
+                                        &token_service_,
+                                        GURL("http://SoMeUrL.com"),
+                                        callback_.callback());
+
+  EXPECT_CALL(callback_,
+              ConfirmCallback(PrivetConfirmApiCallFlow::ERROR_TOKEN));
+  confirm_flow.OnGetTokenFailure(NULL, GoogleServiceAuthError(
+      GoogleServiceAuthError::USER_NOT_SIGNED_UP));
+}
+
+TEST_F(PrivetConfirmApiFlowTest, ServerFailure) {
+  PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
+                                        &token_service_,
+                                        GURL("http://SoMeUrL.com"),
+                                        callback_.callback());
+
+  confirm_flow.OnGetTokenSuccess(NULL, "SomeToken", base::Time());
+  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
+
+  EXPECT_EQ(GURL("http://SoMeUrL.com"), fetcher->GetOriginalURL());
+
+  fetcher->SetResponseString(kFailedConfirmResponse);
+  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
+                                            net::OK));
+  fetcher->set_response_code(200);
+
+  EXPECT_CALL(callback_,
+              ConfirmCallback(PrivetConfirmApiCallFlow::ERROR_FROM_SERVER));
+
+  fetcher->delegate()->OnURLFetchComplete(fetcher);
+}
+
+TEST_F(PrivetConfirmApiFlowTest, BadJson) {
+  PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
+                                        &token_service_,
+                                        GURL("http://SoMeUrL.com"),
+                                        callback_.callback());
+
+  confirm_flow.OnGetTokenSuccess(NULL, "SomeToken", base::Time());
+  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
+
+  EXPECT_EQ(GURL("http://SoMeUrL.com"), fetcher->GetOriginalURL());
+
+  fetcher->SetResponseString(kFailedConfirmResponseBadJson);
+  fetcher->set_status(net::URLRequestStatus(
+      net::URLRequestStatus::SUCCESS,
+      net::OK));
+  fetcher->set_response_code(200);
+
+  EXPECT_CALL(callback_, ConfirmCallback
+              (PrivetConfirmApiCallFlow::ERROR_MALFORMED_RESPONSE));
+
+  fetcher->delegate()->OnURLFetchComplete(fetcher);
+}
+
+}  // namespace
+
+}  // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privet_device_lister_unittest.cc b/chrome/browser/local_discovery/privet_device_lister_unittest.cc
index 48e18f4..98dc714 100644
--- a/chrome/browser/local_discovery/privet_device_lister_unittest.cc
+++ b/chrome/browser/local_discovery/privet_device_lister_unittest.cc
@@ -129,6 +129,15 @@
     return mock_service_resolver.PassAs<ServiceResolver>();
   }
 
+  // Not used in this test.
+  virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
+    const std::string& domain,
+    net::AddressFamily address_family,
+    const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE {
+    NOTREACHED();
+    return scoped_ptr<LocalDomainResolver>();
+  }
+
  private:
   ServiceDiscoveryMockDelegate* mock_delegate_;
 };
diff --git a/chrome/browser/local_discovery/service_discovery_host_client.cc b/chrome/browser/local_discovery/service_discovery_host_client.cc
index 42b5a22..3a2c172 100644
--- a/chrome/browser/local_discovery/service_discovery_host_client.cc
+++ b/chrome/browser/local_discovery/service_discovery_host_client.cc
@@ -113,6 +113,15 @@
       new ServiceResolverProxy(this, service_name, callback));
 }
 
+scoped_ptr<LocalDomainResolver>
+ServiceDiscoveryHostClient::CreateLocalDomainResolver(
+    const std::string& domain,
+    net::AddressFamily address_family,
+    const LocalDomainResolver::IPAddressCallback& callback) {
+  NOTIMPLEMENTED();  // TODO(noamsml): Multiprocess domain resolver
+  return scoped_ptr<LocalDomainResolver>();
+}
+
 uint64 ServiceDiscoveryHostClient::RegisterWatcherCallback(
     const ServiceWatcher::UpdatedCallback& callback) {
   DCHECK(CalledOnValidThread());
@@ -179,8 +188,13 @@
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
-      base::Bind(base::IgnoreResult(&content::UtilityProcessHost::Send),
-                 utility_host_, msg));
+      base::Bind(&ServiceDiscoveryHostClient::SendOnIOThread, this, msg));
+}
+
+void ServiceDiscoveryHostClient::SendOnIOThread(IPC::Message* msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (utility_host_)
+    utility_host_->Send(msg);
 }
 
 bool ServiceDiscoveryHostClient::OnMessageReceived(
diff --git a/chrome/browser/local_discovery/service_discovery_host_client.h b/chrome/browser/local_discovery/service_discovery_host_client.h
index 4bdf08b..28cdcce 100644
--- a/chrome/browser/local_discovery/service_discovery_host_client.h
+++ b/chrome/browser/local_discovery/service_discovery_host_client.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_HOST_CLIENT_H_
 
 #include <map>
+#include <string>
 
 #include "base/threading/non_thread_safe.h"
 #include "chrome/common/local_discovery/service_discovery_client.h"
@@ -42,6 +43,10 @@
   virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
       const std::string& service_name,
       const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
+  virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
+      const std::string& domain,
+      net::AddressFamily address_family,
+      const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE;
 
   // UtilityProcessHostClient implementation.
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -61,6 +66,7 @@
   void ShutdownOnIOThread();
 
   void Send(IPC::Message* msg);
+  void SendOnIOThread(IPC::Message* msg);
 
   uint64 RegisterWatcherCallback(
       const ServiceWatcher::UpdatedCallback& callback);
diff --git a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc
index 7b7bebf..c547599 100644
--- a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc
+++ b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc
@@ -4,13 +4,12 @@
 
 #include "base/bind.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -195,9 +194,7 @@
   void OnTokenFetched(const GoogleServiceAuthError& error,
                       const std::string& token);
 
-  base::WeakPtrFactory<ManagedUserRefreshTokenFetcherTest> weak_ptr_factory_;
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   MockOAuth2TokenService oauth2_token_service_;
   net::TestURLFetcherFactory url_fetcher_factory_;
@@ -205,15 +202,15 @@
 
   GoogleServiceAuthError error_;
   std::string token_;
+  base::WeakPtrFactory<ManagedUserRefreshTokenFetcherTest> weak_ptr_factory_;
 };
 
 ManagedUserRefreshTokenFetcherTest::ManagedUserRefreshTokenFetcherTest()
-    : weak_ptr_factory_(this),
-      ui_thread_(content::BrowserThread::UI, &message_loop_),
-      token_fetcher_(
+    : token_fetcher_(
           ManagedUserRefreshTokenFetcher::Create(&oauth2_token_service_,
                                           profile_.GetRequestContext())),
-      error_(GoogleServiceAuthError::NONE) {}
+      error_(GoogleServiceAuthError::NONE),
+      weak_ptr_factory_(this) {}
 
 void ManagedUserRefreshTokenFetcherTest::StartFetching() {
   token_fetcher_->Start(kManagedUserId, UTF8ToUTF16(kName), kDeviceName,
diff --git a/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
index 5396b11..a0aada7 100644
--- a/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
+++ b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/infobars/infobar.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/media/webrtc_browsertest_common.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
@@ -115,7 +116,7 @@
     CloseInfobarInTab(tab_contents, media_infobar);
 
     // Wait for WebRTC to call the success callback.
-    EXPECT_TRUE(UglyPollingWaitUntil(
+    EXPECT_TRUE(PollingWaitUntil(
         "obtainGetUserMediaResult()", kOkGotStream, tab_contents));
   }
 
@@ -134,9 +135,9 @@
     CloseInfobarInTab(tab_contents, media_infobar);
 
     // Wait for WebRTC to call the fail callback.
-    EXPECT_TRUE(UglyPollingWaitUntil("obtainGetUserMediaResult()",
-                                     kFailedWithErrorPermissionDenied,
-                                     tab_contents));
+    EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()",
+                                 kFailedWithErrorPermissionDenied,
+                                 tab_contents));
   }
 
   void TestDismissOnInfobar(content::WebContents* tab_contents) {
@@ -148,35 +149,9 @@
     CloseInfobarInTab(tab_contents, media_infobar);
 
     // A dismiss should be treated like a deny.
-    EXPECT_TRUE(UglyPollingWaitUntil("obtainGetUserMediaResult()",
-                                     kFailedWithErrorPermissionDenied,
-                                     tab_contents));
-  }
-
-  // TODO(phoglund): de-dupe
-  // TODO(phoglund): This ugly poll method is only here while we transition
-  // the test javascript to just post events when things happen. Right now they
-  // don't because the webrtc_call.py and other tests use this polling way of
-  // communicating when we are waiting from an asynchronous event in the
-  // javascript. This method is meant to emulate WaitUntil in the PyAuto
-  // framework.
-  bool UglyPollingWaitUntil(const std::string& javascript,
-                            const std::string& evaluates_to,
-                            content::WebContents* tab_contents) {
-    const base::Time start_time = base::Time::Now();
-    const base::TimeDelta timeout = TestTimeouts::action_max_timeout();
-    std::string result;
-
-    while (base::Time::Now() - start_time < timeout) {
-      result = ExecuteJavascript(javascript, tab_contents);
-      LOG(INFO) << result;
-      if (evaluates_to == result)
-        return true;
-    }
-    LOG(ERROR) << "Timed out while waiting for " << javascript
-               << " to evaluate to " << evaluates_to << "; last result was '"
-               << result << "'";
-    return false;
+    EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()",
+                                 kFailedWithErrorPermissionDenied,
+                                 tab_contents));
   }
 
   void GetUserMedia(const std::string& constraints,
@@ -219,9 +194,9 @@
 
   // Should fail with permission denied right away with no infobar popping up.
   GetUserMedia(kAudioVideoCallConstraints, tab_contents);
-  EXPECT_TRUE(UglyPollingWaitUntil("obtainGetUserMediaResult()",
-                                   kFailedWithErrorPermissionDenied,
-                                   tab_contents));
+  EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()",
+                               kFailedWithErrorPermissionDenied,
+                               tab_contents));
   InfoBarService* infobar_service =
       InfoBarService::FromWebContents(tab_contents);
   EXPECT_EQ(0u, infobar_service->infobar_count());
diff --git a/chrome/browser/media/chrome_webrtc_browsertest.cc b/chrome/browser/media/chrome_webrtc_browsertest.cc
index 2b6eb8e..b9c6b51 100644
--- a/chrome/browser/media/chrome_webrtc_browsertest.cc
+++ b/chrome/browser/media/chrome_webrtc_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/infobars/infobar.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/media/webrtc_browsertest_common.h"
 #include "chrome/browser/media/webrtc_log_uploader.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -98,30 +99,6 @@
         switches::kUseFakeUIForMediaStream));
   }
 
-  // TODO(phoglund): This ugly poll method is only here while we transition
-  // the test javascript to just post events when things happen. Right now they
-  // don't because the webrtc_call.py and other tests use this polling way of
-  // communicating when we are waiting from an asynchronous event in the
-  // javascript. This method is meant to emulate WaitUntil in the PyAuto
-  // framework.
-  bool UglyPollingWaitUntil(const std::string& javascript,
-                            const std::string& evaluates_to,
-                            content::WebContents* tab_contents) {
-    base::Time start_time = base::Time::Now();
-    base::TimeDelta timeout = base::TimeDelta::FromSeconds(20);
-    std::string result;
-
-    while (base::Time::Now() - start_time < timeout) {
-      result = ExecuteJavascript(javascript, tab_contents);
-      if (evaluates_to == result)
-        return true;
-    }
-    LOG(ERROR) << "Timed out while waiting for " << javascript <<
-        " to evaluate to " << evaluates_to << "; last result was '" << result <<
-        "'";
-    return false;
-  }
-
   // Convenience method which executes the provided javascript in the context
   // of the provided web contents and returns what it evaluated to.
   std::string ExecuteJavascript(const std::string& javascript,
@@ -149,9 +126,9 @@
     media_infobar->Accept();
 
     // Wait for WebRTC to call the success callback.
-    EXPECT_TRUE(UglyPollingWaitUntil("obtainGetUserMediaResult();",
-                                     "ok-got-stream",
-                                     tab_contents));
+    EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult();",
+                                 "ok-got-stream",
+                                 tab_contents));
   }
 
   // Ensures we didn't get any errors asynchronously (e.g. while no javascript
@@ -187,10 +164,10 @@
               ExecuteJavascript("negotiateCall()", from_tab));
 
     // Ensure the call gets up on both sides.
-    EXPECT_TRUE(UglyPollingWaitUntil("getPeerConnectionReadyState()",
-                                     "active", from_tab));
-    EXPECT_TRUE(UglyPollingWaitUntil("getPeerConnectionReadyState()",
-                                     "active", to_tab));
+    EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+                                 "active", from_tab));
+    EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+                                 "active", to_tab));
   }
 
   void StartDetectingVideo(content::WebContents* tab_contents,
@@ -202,13 +179,13 @@
   }
 
   void WaitForVideoToPlay(content::WebContents* tab_contents) {
-    EXPECT_TRUE(UglyPollingWaitUntil("isVideoPlaying()", "video-playing",
-                                     tab_contents));
+    EXPECT_TRUE(PollingWaitUntil("isVideoPlaying()", "video-playing",
+                                 tab_contents));
   }
 
   void WaitForVideoToStopPlaying(content::WebContents* tab_contents) {
-    EXPECT_TRUE(UglyPollingWaitUntil("isVideoPlaying()", "video-not-playing",
-                                     tab_contents));
+    EXPECT_TRUE(PollingWaitUntil("isVideoPlaying()", "video-not-playing",
+                                 tab_contents));
   }
 
   void HangUp(content::WebContents* from_tab) {
@@ -216,8 +193,8 @@
   }
 
   void WaitUntilHangupVerified(content::WebContents* tab_contents) {
-    EXPECT_TRUE(UglyPollingWaitUntil("getPeerConnectionReadyState()",
-                                     "no-peer-connection", tab_contents));
+    EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+                                 "no-peer-connection", tab_contents));
   }
 
   std::string ToggleLocalVideoTrack(content::WebContents* tab_contents) {
diff --git a/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
index 8e5b3e4..f6c5a97 100644
--- a/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
+++ b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/infobars/infobar.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/media/webrtc_browsertest_common.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
@@ -169,30 +170,6 @@
         << "Failed to shut down pywebsocket server!";
   }
 
-  // TODO(phoglund): This ugly poll method is only here while we transition
-  // the test javascript to just post events when things happen. Right now they
-  // don't because the webrtc_call.py and other tests use this polling way of
-  // communicating when we are waiting from an asynchronous event in the
-  // javascript. This method is meant to emulate WaitUntil in the PyAuto
-  // framework.
-  bool UglyPollingWaitUntil(const std::string& javascript,
-                            const std::string& evaluates_to,
-                            content::WebContents* tab_contents) {
-    base::Time start_time = base::Time::Now();
-    base::TimeDelta timeout = TestTimeouts::action_max_timeout();
-    std::string result;
-
-    while (base::Time::Now() - start_time < timeout) {
-      result = ExecuteJavascript(javascript, tab_contents);
-      if (evaluates_to == result)
-        return true;
-    }
-    LOG(ERROR) << "Timed out while waiting for " << javascript
-               << " to evaluate to " << evaluates_to << "; last result was '"
-               << result << "'";
-    return false;
-  }
-
   // Convenience method which executes the provided javascript in the context
   // of the provided web contents and returns what it evaluated to.
   std::string ExecuteJavascript(const std::string& javascript,
@@ -221,7 +198,7 @@
     media_infobar->Accept();
 
     // Wait for WebRTC to call the success callback.
-    EXPECT_TRUE(UglyPollingWaitUntil(
+    EXPECT_TRUE(PollingWaitUntil(
         "obtainGetUserMediaResult();", "ok-got-stream", tab_contents));
   }
 
@@ -251,9 +228,9 @@
     EXPECT_EQ("ok-negotiating", ExecuteJavascript("negotiateCall()", from_tab));
 
     // Ensure the call gets up on both sides.
-    EXPECT_TRUE(UglyPollingWaitUntil(
+    EXPECT_TRUE(PollingWaitUntil(
         "getPeerConnectionReadyState()", "active", from_tab));
-    EXPECT_TRUE(UglyPollingWaitUntil(
+    EXPECT_TRUE(PollingWaitUntil(
         "getPeerConnectionReadyState()", "active", to_tab));
   }
 
@@ -262,7 +239,7 @@
   }
 
   void WaitUntilHangupVerified(content::WebContents* tab_contents) {
-    EXPECT_TRUE(UglyPollingWaitUntil(
+    EXPECT_TRUE(PollingWaitUntil(
         "getPeerConnectionReadyState()", "no-peer-connection", tab_contents));
   }
 
@@ -498,9 +475,14 @@
   AssertNoAsynchronousErrors(left_tab);
   AssertNoAsynchronousErrors(right_tab);
 
+  // Poll slower here to avoid flooding the log with messages: capturing and
+  // sending frames take quite a bit of time.
+  int polling_interval_msec = 1000;
+
   // TODO(phoglund): (de-dupe later) different from original flow.
-  EXPECT_TRUE(UglyPollingWaitUntil(
-      "doneFrameCapturing()", "done-capturing", right_tab));
+  EXPECT_TRUE(PollingWaitUntil(
+      "doneFrameCapturing()", "done-capturing", right_tab,
+      polling_interval_msec));
 
   HangUp(left_tab);
   WaitUntilHangupVerified(left_tab);
@@ -510,8 +492,9 @@
   AssertNoAsynchronousErrors(right_tab);
 
   // TODO(phoglund): (de-dupe later) different from original flow.
-  EXPECT_TRUE(UglyPollingWaitUntil(
-      "haveMoreFramesToSend()", "no-more-frames", right_tab));
+  EXPECT_TRUE(PollingWaitUntil(
+      "haveMoreFramesToSend()", "no-more-frames", right_tab,
+      polling_interval_msec));
 
   RunARGBtoI420Converter(
       kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName));
diff --git a/chrome/browser/media/webrtc_browsertest_common.cc b/chrome/browser/media/webrtc_browsertest_common.cc
new file mode 100644
index 0000000..83c24fc
--- /dev/null
+++ b/chrome/browser/media/webrtc_browsertest_common.cc
@@ -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.
+
+#include "chrome/browser/media/webrtc_browsertest_common.h"
+
+#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"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/infobars/infobar.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.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 "chrome/test/ui/ui_test.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+const int kDefaultPollIntervalMsec = 250;
+
+bool SleepInJavascript(content::WebContents* tab_contents, int timeout_msec) {
+  const std::string javascript = base::StringPrintf(
+      "setTimeout(function() {"
+      "  window.domAutomationController.send('sleep-ok');"
+      "}, %d)", timeout_msec);
+
+  std::string result;
+  bool ok = content::ExecuteScriptAndExtractString(
+      tab_contents, javascript, &result);
+  return ok && result == "sleep-ok";
+}
+
+bool PollingWaitUntil(const std::string& javascript,
+                      const std::string& evaluates_to,
+                      content::WebContents* tab_contents) {
+  return PollingWaitUntil(javascript, evaluates_to, tab_contents,
+                          kDefaultPollIntervalMsec);
+}
+
+bool PollingWaitUntil(const std::string& javascript,
+                      const std::string& evaluates_to,
+                      content::WebContents* tab_contents,
+                      int poll_interval_msec) {
+  base::Time start_time = base::Time::Now();
+  base::TimeDelta timeout = TestTimeouts::action_max_timeout();
+  std::string result;
+
+  while (base::Time::Now() - start_time < timeout) {
+    std::string result;
+    if (!content::ExecuteScriptAndExtractString(tab_contents, javascript,
+                                                &result)) {
+      LOG(ERROR) << "Failed to execute javascript " << javascript;
+      return false;
+    }
+
+    if (evaluates_to == result)
+      return true;
+
+    // Sleep a bit here to keep this loop from spinlocking too badly.
+    if (!SleepInJavascript(tab_contents, poll_interval_msec)) {
+      // TODO(phoglund): Figure out why this fails every now and then.
+      // It's not a huge deal if it does though.
+      LOG(ERROR) << "Failed to sleep.";
+    }
+  }
+  LOG(ERROR) << "Timed out while waiting for " << javascript <<
+      " to evaluate to " << evaluates_to << "; last result was '" << result <<
+      "'";
+  return false;
+}
diff --git a/chrome/browser/media/webrtc_browsertest_common.h b/chrome/browser/media/webrtc_browsertest_common.h
new file mode 100644
index 0000000..19d7ae9
--- /dev/null
+++ b/chrome/browser/media/webrtc_browsertest_common.h
@@ -0,0 +1,28 @@
+// 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_MEDIA_WEBRTC_BROWSERTEST_COMMON_H_
+#define CHROME_BROWSER_MEDIA_WEBRTC_BROWSERTEST_COMMON_H_
+
+#include <string>
+
+namespace content {
+class WebContents;
+}
+
+// This function will execute the provided |javascript| until it causes a call
+// to window.domAutomationController.send() with |evaluates_to| as the message.
+// That is, we are NOT checking what the javascript evaluates to. Returns false
+// if we exceed the TestTimeouts::action_max_timeout().
+// TODO(phoglund): Consider a better interaction method with the javascript
+// than polling javascript methods.
+bool PollingWaitUntil(const std::string& javascript,
+                      const std::string& evaluates_to,
+                      content::WebContents* tab_contents);
+bool PollingWaitUntil(const std::string& javascript,
+                      const std::string& evaluates_to,
+                      content::WebContents* tab_contents,
+                      int poll_interval_msec);
+
+#endif  // CHROME_BROWSER_MEDIA_WEBRTC_BROWSERTEST_COMMON_H_
diff --git a/chrome/browser/media/webrtc_log_upload_list.cc b/chrome/browser/media/webrtc_log_upload_list.cc
index 9f9922e..fdaaad0 100644
--- a/chrome/browser/media/webrtc_log_upload_list.cc
+++ b/chrome/browser/media/webrtc_log_upload_list.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/media/webrtc_log_upload_list.h"
 
 #include "base/files/file_path.h"
-#include "base/message_loop/message_loop_proxy.h"
 #include "base/path_service.h"
 #include "chrome/common/chrome_paths.h"
 
@@ -24,8 +23,6 @@
 
 WebRtcLogUploadList::WebRtcLogUploadList(Delegate* delegate,
                                          const base::FilePath& upload_log_path)
-    : base::UploadList(delegate,
-                       upload_log_path,
-                       base::MessageLoopProxy::current()) {}
+    : UploadList(delegate, upload_log_path) {}
 
 WebRtcLogUploadList::~WebRtcLogUploadList() {}
diff --git a/chrome/browser/media/webrtc_log_upload_list.h b/chrome/browser/media/webrtc_log_upload_list.h
index 366a41d..b829d8e 100644
--- a/chrome/browser/media/webrtc_log_upload_list.h
+++ b/chrome/browser/media/webrtc_log_upload_list.h
@@ -5,10 +5,10 @@
 #ifndef CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
 #define CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
 
-#include "base/upload_list.h"
+#include "chrome/browser/upload_list.h"
 
 // Loads and parses a text file list of uploaded WebRTC logs.
-class WebRtcLogUploadList : public base::UploadList {
+class WebRtcLogUploadList : public UploadList {
  public:
   // Creates the WebRTC log upload list with the given callback delegate.
   static WebRtcLogUploadList* Create(Delegate* delegate);
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
index 7afab9f..8625186 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/media_galleries/fileapi/supported_image_type_validator.h"
 #include "webkit/browser/fileapi/copy_or_move_file_validator.h"
 #include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/common/blob/shareable_file_reference.h"
 
 namespace chrome {
 
@@ -17,7 +18,14 @@
 class InvalidFileValidator : public fileapi::CopyOrMoveFileValidator {
  public:
   virtual ~InvalidFileValidator() {}
-  virtual void StartValidation(
+  virtual void StartPreWriteValidation(
+      const fileapi::CopyOrMoveFileValidator::ResultCallback&
+          result_callback) OVERRIDE {
+    result_callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
+  }
+
+  virtual void StartPostWriteValidation(
+      const base::FilePath& dest_platform_path,
       const fileapi::CopyOrMoveFileValidator::ResultCallback&
           result_callback) OVERRIDE {
     result_callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
diff --git a/chrome/browser/media_galleries/fileapi/supported_image_type_validator.cc b/chrome/browser/media_galleries/fileapi/supported_image_type_validator.cc
index 00c601d..466b5f9 100644
--- a/chrome/browser/media_galleries/fileapi/supported_image_type_validator.cc
+++ b/chrome/browser/media_galleries/fileapi/supported_image_type_validator.cc
@@ -111,8 +111,8 @@
          extension == FILE_PATH_LITERAL(".webp");
 }
 
-void SupportedImageTypeValidator::StartValidation(
-    const fileapi::CopyOrMoveFileValidator::ResultCallback& result_callback) {
+void SupportedImageTypeValidator::StartPreWriteValidation(
+    const ResultCallback& result_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   DCHECK(callback_.is_null());
   callback_ = result_callback;
@@ -125,6 +125,19 @@
                  weak_factory_.GetWeakPtr()));
 }
 
+void SupportedImageTypeValidator::StartPostWriteValidation(
+    const base::FilePath& dest_platform_path,
+    const ResultCallback& result_callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  post_write_callback_ = result_callback;
+
+  // TODO(gbillock): Insert AV call here in the right validator.
+  BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(post_write_callback_, base::PLATFORM_FILE_OK));
+}
+
 SupportedImageTypeValidator::SupportedImageTypeValidator(
     const base::FilePath& path)
     : path_(path),
diff --git a/chrome/browser/media_galleries/fileapi/supported_image_type_validator.h b/chrome/browser/media_galleries/fileapi/supported_image_type_validator.h
index 8c655b5..c74d762 100644
--- a/chrome/browser/media_galleries/fileapi/supported_image_type_validator.h
+++ b/chrome/browser/media_galleries/fileapi/supported_image_type_validator.h
@@ -25,9 +25,12 @@
 
   static bool SupportsFileType(const base::FilePath& path);
 
-  virtual void StartValidation(
-      const fileapi::CopyOrMoveFileValidator::ResultCallback&
-          result_callback) OVERRIDE;
+  virtual void StartPreWriteValidation(
+      const ResultCallback& result_callback) OVERRIDE;
+
+  virtual void StartPostWriteValidation(
+      const base::FilePath& dest_platform_path,
+      const ResultCallback& result_callback) OVERRIDE;
 
  private:
   friend class MediaFileValidatorFactory;
@@ -39,6 +42,7 @@
   base::FilePath path_;
   scoped_refptr<ImageDecoder> decoder_;
   fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
+  fileapi::CopyOrMoveFileValidator::ResultCallback post_write_callback_;
   base::WeakPtrFactory<SupportedImageTypeValidator> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SupportedImageTypeValidator);
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index c8ee4cf..54e26c7 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 = 9;
+const int ThreadWatcherList::kUnresponsiveCount = 7;
 // static
 const int ThreadWatcherList::kLiveThreadsThreshold = 2;
 
diff --git a/chrome/browser/nacl_host/nacl_broker_host_win.cc b/chrome/browser/nacl_host/nacl_broker_host_win.cc
index bcb250b..2ab2aca 100644
--- a/chrome/browser/nacl_host/nacl_broker_host_win.cc
+++ b/chrome/browser/nacl_host/nacl_broker_host_win.cc
@@ -10,8 +10,8 @@
 #include "ipc/ipc_switches.h"
 #include "chrome/browser/nacl_host/nacl_broker_service_win.h"
 #include "chrome/browser/nacl_host/nacl_browser.h"
-#include "chrome/common/nacl_messages.h"
 #include "components/nacl/common/nacl_cmd_line.h"
+#include "components/nacl/common/nacl_messages.h"
 #include "components/nacl/common/nacl_process_type.h"
 #include "components/nacl/common/nacl_switches.h"
 #include "content/public/browser/browser_child_process_host.h"
diff --git a/chrome/browser/nacl_host/nacl_file_host.cc b/chrome/browser/nacl_host/nacl_file_host.cc
index ca1feb9..8b40b8a 100644
--- a/chrome/browser/nacl_host/nacl_file_host.cc
+++ b/chrome/browser/nacl_host/nacl_file_host.cc
@@ -17,8 +17,8 @@
 #include "chrome/browser/nacl_host/nacl_browser.h"
 #include "chrome/browser/nacl_host/nacl_host_message_filter.h"
 #include "chrome/common/extensions/manifest_handlers/shared_module_info.h"
-#include "chrome/common/nacl_host_messages.h"
 #include "components/nacl/common/nacl_browser_delegate.h"
+#include "components/nacl/common/nacl_host_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
diff --git a/chrome/browser/nacl_host/nacl_host_message_filter.cc b/chrome/browser/nacl_host/nacl_host_message_filter.cc
index ceecc2a..b408a17 100644
--- a/chrome/browser/nacl_host/nacl_host_message_filter.cc
+++ b/chrome/browser/nacl_host/nacl_host_message_filter.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/nacl_host/nacl_file_host.h"
 #include "chrome/browser/nacl_host/nacl_process_host.h"
 #include "chrome/browser/nacl_host/pnacl_host.h"
-#include "chrome/common/nacl_host_messages.h"
+#include "components/nacl/common/nacl_host_messages.h"
 #include "extensions/common/constants.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc
index ee67c58..59879e4 100644
--- a/chrome/browser/nacl_host/nacl_process_host.cc
+++ b/chrome/browser/nacl_host/nacl_process_host.cc
@@ -25,10 +25,10 @@
 #include "build/build_config.h"
 #include "chrome/browser/nacl_host/nacl_browser.h"
 #include "chrome/browser/nacl_host/nacl_host_message_filter.h"
-#include "chrome/common/nacl_host_messages.h"
-#include "chrome/common/nacl_messages.h"
 #include "components/nacl/common/nacl_browser_delegate.h"
 #include "components/nacl/common/nacl_cmd_line.h"
+#include "components/nacl/common/nacl_host_messages.h"
+#include "components/nacl/common/nacl_messages.h"
 #include "components/nacl/common/nacl_process_type.h"
 #include "components/nacl/common/nacl_switches.h"
 #include "content/public/browser/browser_child_process_host.h"
@@ -57,7 +57,7 @@
 #include "base/threading/thread.h"
 #include "base/win/scoped_handle.h"
 #include "chrome/browser/nacl_host/nacl_broker_service_win.h"
-#include "chrome/common/nacl_debug_exception_handler_win.h"
+#include "components/nacl/common/nacl_debug_exception_handler_win.h"
 #include "content/public/common/sandbox_init.h"
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
 #endif
diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h
index 1250b3c..808a274 100644
--- a/chrome/browser/nacl_host/nacl_process_host.h
+++ b/chrome/browser/nacl_host/nacl_process_host.h
@@ -13,7 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/process.h"
-#include "chrome/common/nacl_types.h"
+#include "components/nacl/common/nacl_types.h"
 #include "content/public/browser/browser_child_process_host_delegate.h"
 #include "content/public/browser/browser_child_process_host_iterator.h"
 #include "ipc/ipc_channel_handle.h"
diff --git a/chrome/browser/nacl_host/pnacl_host.h b/chrome/browser/nacl_host/pnacl_host.h
index b55c9a6..e449ce2 100644
--- a/chrome/browser/nacl_host/pnacl_host.h
+++ b/chrome/browser/nacl_host/pnacl_host.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "chrome/browser/nacl_host/nacl_file_host.h"
-#include "chrome/common/pnacl_types.h"
+#include "components/nacl/common/pnacl_types.h"
 #include "ipc/ipc_platform_file.h"
 
 namespace pnacl {
diff --git a/chrome/browser/net/connection_tester.cc b/chrome/browser/net/connection_tester.cc
index 5127d55..7a06aae 100644
--- a/chrome/browser/net/connection_tester.cc
+++ b/chrome/browser/net/connection_tester.cc
@@ -37,7 +37,7 @@
 #include "net/url_request/url_request_context_storage.h"
 
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
-#include "chrome/browser/importer/firefox_proxy_settings.h"
+#include "chrome/browser/net/firefox_proxy_settings.h"
 #endif
 
 namespace {
diff --git a/chrome/browser/importer/firefox_proxy_settings.cc b/chrome/browser/net/firefox_proxy_settings.cc
similarity index 70%
rename from chrome/browser/importer/firefox_proxy_settings.cc
rename to chrome/browser/net/firefox_proxy_settings.cc
index 58aa4f3..aece777 100644
--- a/chrome/browser/importer/firefox_proxy_settings.cc
+++ b/chrome/browser/net/firefox_proxy_settings.cc
@@ -1,10 +1,12 @@
-// Copyright (c) 2010 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/importer/firefox_proxy_settings.h"
+#include "chrome/browser/net/firefox_proxy_settings.h"
 
+#include "base/file_util.h"
 #include "base/files/file_path.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
@@ -57,6 +59,84 @@
   }
 }
 
+// Parses the prefs found in the file |pref_file| and puts the key/value pairs
+// in |prefs|. Keys are strings, and values can be strings, booleans or
+// integers.  Returns true if it succeeded, false otherwise (in which case
+// |prefs| is not filled).
+// Note: for strings, only valid UTF-8 string values are supported. If a
+// key/pair is not valid UTF-8, it is ignored and will not appear in |prefs|.
+bool ParsePrefFile(const base::FilePath& pref_file, DictionaryValue* prefs) {
+  // The string that is before a pref key.
+  const std::string kUserPrefString = "user_pref(\"";
+  std::string contents;
+  if (!file_util::ReadFileToString(pref_file, &contents))
+    return false;
+
+  std::vector<std::string> lines;
+  Tokenize(contents, "\n", &lines);
+
+  for (std::vector<std::string>::const_iterator iter = lines.begin();
+       iter != lines.end(); ++iter) {
+    const std::string& line = *iter;
+    size_t start_key = line.find(kUserPrefString);
+    if (start_key == std::string::npos)
+      continue;  // Could be a comment or a blank line.
+    start_key += kUserPrefString.length();
+    size_t stop_key = line.find('"', start_key);
+    if (stop_key == std::string::npos) {
+      LOG(ERROR) << "Invalid key found in Firefox pref file '" <<
+          pref_file.value() << "' line is '" << line << "'.";
+      continue;
+    }
+    std::string key = line.substr(start_key, stop_key - start_key);
+    size_t start_value = line.find(',', stop_key + 1);
+    if (start_value == std::string::npos) {
+      LOG(ERROR) << "Invalid value found in Firefox pref file '" <<
+          pref_file.value() << "' line is '" << line << "'.";
+      continue;
+    }
+    size_t stop_value = line.find(");", start_value + 1);
+    if (stop_value == std::string::npos) {
+      LOG(ERROR) << "Invalid value found in Firefox pref file '" <<
+          pref_file.value() << "' line is '" << line << "'.";
+      continue;
+    }
+    std::string value = line.substr(start_value + 1,
+                                    stop_value - start_value - 1);
+    TrimWhitespace(value, TRIM_ALL, &value);
+    // Value could be a boolean.
+    bool is_value_true = LowerCaseEqualsASCII(value, "true");
+    if (is_value_true || LowerCaseEqualsASCII(value, "false")) {
+      prefs->SetBoolean(key, is_value_true);
+      continue;
+    }
+
+    // Value could be a string.
+    if (value.size() >= 2U &&
+        value[0] == '"' && value[value.size() - 1] == '"') {
+      value = value.substr(1, value.size() - 2);
+      // ValueString only accept valid UTF-8.  Simply ignore that entry if it is
+      // not UTF-8.
+      if (IsStringUTF8(value))
+        prefs->SetString(key, value);
+      else
+        VLOG(1) << "Non UTF8 value for key " << key << ", ignored.";
+      continue;
+    }
+
+    // Or value could be an integer.
+    int int_value = 0;
+    if (base::StringToInt(value, &int_value)) {
+      prefs->SetInteger(key, int_value);
+      continue;
+    }
+
+    LOG(ERROR) << "Invalid value found in Firefox pref file '"
+               << pref_file.value() << "' value is '" << value << "'.";
+  }
+  return true;
+}
+
 }  // namespace
 
 FirefoxProxySettings::FirefoxProxySettings() {
diff --git a/chrome/browser/importer/firefox_proxy_settings.h b/chrome/browser/net/firefox_proxy_settings.h
similarity index 91%
rename from chrome/browser/importer/firefox_proxy_settings.h
rename to chrome/browser/net/firefox_proxy_settings.h
index 41657a2..34ea9ff 100644
--- a/chrome/browser/importer/firefox_proxy_settings.h
+++ b/chrome/browser/net/firefox_proxy_settings.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2010 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_IMPORTER_FIREFOX_PROXY_SETTINGS_H_
-#define CHROME_BROWSER_IMPORTER_FIREFOX_PROXY_SETTINGS_H_
+#ifndef CHROME_BROWSER_NET_FIREFOX_PROXY_SETTINGS_H_
+#define CHROME_BROWSER_NET_FIREFOX_PROXY_SETTINGS_H_
 
 #include <string>
 #include <vector>
@@ -109,4 +109,4 @@
   DISALLOW_COPY_AND_ASSIGN(FirefoxProxySettings);
 };
 
-#endif  // CHROME_BROWSER_IMPORTER_FIREFOX_PROXY_SETTINGS_H_
+#endif  // CHROME_BROWSER_NET_FIREFOX_PROXY_SETTINGS_H_
diff --git a/chrome/browser/importer/firefox_proxy_settings_unittest.cc b/chrome/browser/net/firefox_proxy_settings_unittest.cc
similarity index 96%
rename from chrome/browser/importer/firefox_proxy_settings_unittest.cc
rename to chrome/browser/net/firefox_proxy_settings_unittest.cc
index 7699e13..f1740e9 100644
--- a/chrome/browser/importer/firefox_proxy_settings_unittest.cc
+++ b/chrome/browser/net/firefox_proxy_settings_unittest.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2010 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 "testing/gtest/include/gtest/gtest.h"
+#include "chrome/browser/net/firefox_proxy_settings.h"
 
 #include "base/files/file_path.h"
 #include "base/path_service.h"
-#include "chrome/browser/importer/firefox_proxy_settings.h"
 #include "chrome/common/chrome_paths.h"
 #include "net/proxy/proxy_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 class FirefoxProxySettingsTest : public testing::Test {
 };
diff --git a/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc b/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc
index 3b64e1d..d8ab2c7 100644
--- a/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc
+++ b/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc
@@ -8,10 +8,10 @@
 #include <string>
 
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "chrome/browser/net/gaia/gaia_oauth_consumer.h"
 #include "chrome/browser/net/gaia/gaia_oauth_fetcher.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -23,8 +23,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using ::testing::_;
-
 class MockGaiaOAuthConsumer : public GaiaOAuthConsumer {
  public:
   MockGaiaOAuthConsumer() {}
@@ -123,7 +121,10 @@
 }
 #endif  // 0  // Suppressing for now
 
-typedef testing::Test GaiaOAuthFetcherTest;
+class GaiaOAuthFetcherTest : public testing::Test {
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+};
 
 TEST_F(GaiaOAuthFetcherTest, OAuthGetAccessToken) {
   const std::string oauth_token =
diff --git a/chrome/browser/notifications/message_center_settings_controller.cc b/chrome/browser/notifications/message_center_settings_controller.cc
index 2a0666a..5e9a588 100644
--- a/chrome/browser/notifications/message_center_settings_controller.cc
+++ b/chrome/browser/notifications/message_center_settings_controller.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/i18n/string_compare.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/app_icon_loader_impl.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/favicon/favicon_service.h"
@@ -18,11 +19,12 @@
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/cancelable_task_tracker.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/favicon/favicon_types.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
 #include "grit/theme_resources.h"
 #include "grit/ui_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -59,7 +61,13 @@
 
 }  // namespace
 
-MessageCenterSettingsController::MessageCenterSettingsController() {
+MessageCenterSettingsController::MessageCenterSettingsController()
+  : profile_(NULL) {
+  // We set the profile associated with the settings at the beginning and fail
+  // silently if this profile is destroyed later. This is a temporary fix for
+  // http://crbug.com/263193
+  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
+                 content::NotificationService::AllSources());
 }
 
 MessageCenterSettingsController::~MessageCenterSettingsController() {
@@ -81,9 +89,9 @@
   // TODO(mukai): Fix this for multi-profile.
   // Temporarily use the last used profile to prevent chrome from crashing when
   // the default profile is not loaded.
-  Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy();
+  profile_ = ProfileManager::GetLastUsedProfileAllowedByPolicy();
   DesktopNotificationService* notification_service =
-      DesktopNotificationServiceFactory::GetForProfile(profile);
+      DesktopNotificationServiceFactory::GetForProfile(profile_);
 
   UErrorCode error;
   scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(error));
@@ -91,7 +99,7 @@
   if (!U_FAILURE(error))
     comparator.reset(new NotifierComparator(collator.get()));
 
-  ExtensionService* extension_service = profile->GetExtensionService();
+  ExtensionService* extension_service = profile_->GetExtensionService();
   const ExtensionSet* extension_set = extension_service->extensions();
   // The extension icon size has to be 32x32 at least to load bigger icons if
   // the icon doesn't exist for the specified size, and in that case it falls
@@ -99,7 +107,7 @@
   // dialog. See chrome/browser/extensions/extension_icon_image.cc and
   // crbug.com/222931
   app_icon_loader_.reset(new extensions::AppIconLoaderImpl(
-      profile, extension_misc::EXTENSION_ICON_SMALL, this));
+      profile_, extension_misc::EXTENSION_ICON_SMALL, this));
   for (ExtensionSet::const_iterator iter = extension_set->begin();
        iter != extension_set->end(); ++iter) {
     const extensions::Extension* extension = iter->get();
@@ -120,7 +128,7 @@
           CommandLine::ForCurrentProcess())) {
     notifier::ChromeNotifierService* sync_notifier_service =
         notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile(
-            profile, Profile::EXPLICIT_ACCESS);
+            profile_, Profile::EXPLICIT_ACCESS);
     sync_notifier_service->GetSyncedNotificationServices(notifiers);
 
     if (comparator)
@@ -134,7 +142,7 @@
   ContentSettingsForOneType settings;
   notification_service->GetNotificationsSettings(&settings);
   FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
-      profile, Profile::EXPLICIT_ACCESS);
+      profile_, Profile::EXPLICIT_ACCESS);
   favicon_tracker_.reset(new CancelableTaskTracker());
   patterns_.clear();
   for (ContentSettingsForOneType::const_iterator iter = settings.begin();
@@ -155,7 +163,7 @@
         notification_service->IsNotifierEnabled(notifier_id)));
     patterns_[name] = iter->primary_pattern;
     FaviconService::FaviconForURLParams favicon_params(
-        profile, url, chrome::FAVICON | chrome::TOUCH_ICON,
+        profile_, url, chrome::FAVICON | chrome::TOUCH_ICON,
         message_center::kSettingsIconSize);
     // Note that favicon service obtains the favicon from history. This means
     // that it will fail to obtain the image if there are no history data for
@@ -194,9 +202,11 @@
     const Notifier& notifier,
     bool enabled) {
   // TODO(mukai): Fix this for multi-profile.
-  Profile* profile = ProfileManager::GetDefaultProfile();
+  // If the profile has been destroyed, fail silently.
+  if (!profile_)
+    return;
   DesktopNotificationService* notification_service =
-      DesktopNotificationServiceFactory::GetForProfile(profile);
+      DesktopNotificationServiceFactory::GetForProfile(profile_);
 
   if (notifier.notifier_id.type == NotifierId::WEB_PAGE) {
     // WEB_PAGE notifier cannot handle in DesktopNotificationService
@@ -233,7 +243,7 @@
     if (notifier.notifier_id.type == NotifierId::SYNCED_NOTIFICATION_SERVICE) {
       notifier::ChromeNotifierService* notifier_service =
           notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile(
-              profile, Profile::EXPLICIT_ACCESS);
+              profile_, Profile::EXPLICIT_ACCESS);
       notifier_service->OnSyncedNotificationServiceEnabled(
           notifier.notifier_id.id, enabled);
     }
@@ -246,6 +256,17 @@
   patterns_.clear();
 }
 
+void MessageCenterSettingsController::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  if (type == chrome::NOTIFICATION_PROFILE_DESTROYED &&
+      content::Source<Profile>(source).ptr() == profile_) {
+    // Our profile just got destroyed, so we delete our pointer to it.
+    profile_ = NULL;
+  }
+}
+
 void MessageCenterSettingsController::OnFaviconLoaded(
     const GURL& url,
     const chrome::FaviconImageResult& favicon_result) {
diff --git a/chrome/browser/notifications/message_center_settings_controller.h b/chrome/browser/notifications/message_center_settings_controller.h
index 71487c5..1a66099 100644
--- a/chrome/browser/notifications/message_center_settings_controller.h
+++ b/chrome/browser/notifications/message_center_settings_controller.h
@@ -12,7 +12,10 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "chrome/browser/extensions/app_icon_loader.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/common/content_settings.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
 #include "ui/message_center/notifier_settings.h"
 
 class CancelableTaskTracker;
@@ -25,7 +28,8 @@
 // storage.
 class MessageCenterSettingsController
     : public message_center::NotifierSettingsProvider,
-      public extensions::AppIconLoader::Delegate {
+      public extensions::AppIconLoader::Delegate,
+      public content::NotificationObserver {
  public:
   MessageCenterSettingsController();
   virtual ~MessageCenterSettingsController();
@@ -48,6 +52,11 @@
                            const gfx::ImageSkia& image) OVERRIDE;
 
  private:
+  // Overridden from content::NotificationObserver.
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
   void OnFaviconLoaded(const GURL& url,
                        const chrome::FaviconImageResult& favicon_result);
 
@@ -61,6 +70,13 @@
 
   std::map<string16, ContentSettingsPattern> patterns_;
 
+  // The Registrar used to register for notifications.
+  content::NotificationRegistrar registrar_;
+
+  // TODO(sidharthms): Fix this for multi-profile.
+  // The profile associated with message center settings.
+  Profile* profile_;
+
   DISALLOW_COPY_AND_ASSIGN(MessageCenterSettingsController);
 };
 
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
index 84643d3..d19153b 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
@@ -8,12 +8,16 @@
 
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
 
+#include <string>
+#include <vector>
+
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/profiles/profile.h"
-#include "grit/ui_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_change_processor.h"
 #include "sync/api/sync_error_factory.h"
@@ -21,13 +25,14 @@
 #include "sync/protocol/synced_notification_specifics.pb.h"
 #include "third_party/WebKit/public/web/WebTextDirection.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/message_center/notifier_settings.h"
 #include "url/gurl.h"
 
 namespace notifier {
 namespace {
 
-const char kSampleSyncedNotificationServiceId[] = "sample-synced-service";
+const char kFirstSyncedNotificationServiceId[] = "Google+";
 
 }
 
@@ -35,7 +40,8 @@
 
 ChromeNotifierService::ChromeNotifierService(Profile* profile,
                                              NotificationUIManager* manager)
-    : profile_(profile), notification_manager_(manager) {}
+    : profile_(profile), notification_manager_(manager) {
+}
 ChromeNotifierService::~ChromeNotifierService() {}
 
 // Methods from BrowserContextKeyedService.
@@ -270,20 +276,31 @@
   // TODO(mukai|petewil): Check the profile's eligibility before adding the
   // sample app.
 
-  // Currently we just use kSampleSyncedNotificationServiceId as a place holder.
-  // TODO(petewil): Really obtain the list of apps from the server and create
-  // the list of ids here.
+  // TODO(petewil): Really obtain the list of synced notification sending
+  // services from the server and create the list of ids here.  Until then, we
+  // are hardcoding the service names.  Once that is done, remove this
+  // hardcoding.
+  // crbug.com/248337
   DesktopNotificationService* desktop_notification_service =
       DesktopNotificationServiceFactory::GetForProfile(profile_);
   message_center::NotifierId notifier_id(
       message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE,
-      kSampleSyncedNotificationServiceId);
-  notifiers->push_back(new message_center::Notifier(
+      kFirstSyncedNotificationServiceId);
+  message_center::Notifier* notifier_service = new message_center::Notifier(
       notifier_id,
       l10n_util::GetStringUTF16(
-          IDS_MESSAGE_CENTER_SAMPLE_SYNCED_NOTIFICATION_SERVICE_NAME),
-      desktop_notification_service->IsNotifierEnabled(notifier_id)));
-  // TODO(mukai): Add icon for the sample app.
+          IDS_FIRST_SYNCED_NOTIFICATION_SERVICE_NAME),
+      desktop_notification_service->IsNotifierEnabled(notifier_id));
+
+  // Add icons for our sending services.
+  // TODO(petewil): Replace this temporary hardcoding with a new sync datatype
+  // to dynamically get the name and icon for each synced notification sending
+  // service.  Until then, we use hardcoded service icons for all services.
+  // crbug.com/248337
+  notifier_service->icon = ui::ResourceBundle::GetSharedInstance().
+      GetImageNamed(IDR_TEMPORARY_GOOGLE_PLUS_ICON);
+
+  notifiers->push_back(notifier_service);
 }
 
 void ChromeNotifierService::MarkNotificationAsDismissed(
@@ -311,6 +328,15 @@
   // Take ownership of the object and put it into our local storage.
   notification_data_.push_back(notification.release());
 
+  // If the user is not interested in this type of notification, ignore it.
+  std::vector<std::string>::iterator iter =
+      find(enabled_sending_services_.begin(),
+           enabled_sending_services_.end(),
+           notification_copy->GetSendingServiceId());
+  if (iter == enabled_sending_services_.end()) {
+    return;
+  }
+
   Display(notification_copy);
 }
 
@@ -320,6 +346,7 @@
   }
 
 void ChromeNotifierService::Display(SyncedNotification* notification) {
+
   // Set up to fetch the bitmaps.
   notification->QueueBitmapFetchJobs(notification_manager_,
                                           this,
@@ -337,7 +364,23 @@
 
 void ChromeNotifierService::OnSyncedNotificationServiceEnabled(
     const std::string& notifier_id, bool enabled) {
-  // TODO(petewil): start/stop syncing
+  std::vector<std::string>::iterator iter;
+
+  iter = find(enabled_sending_services_.begin(),
+              enabled_sending_services_.end(),
+              notifier_id);
+
+  // Add the notifier_id if it is enabled and not already there.
+  if (iter == enabled_sending_services_.end() && enabled) {
+    enabled_sending_services_.push_back(notifier_id);
+    // TODO(petewil) Check now for any outstanding notifications.
+  // Remove the notifier_id if it is disabled and present.
+  } else if (iter != enabled_sending_services_.end() && !enabled) {
+    enabled_sending_services_.erase(iter);
+  }
+
+  // Otherwise, nothing to do, we can exit.
+  return;
 }
 
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
index b423703..13a21f0 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
@@ -98,6 +98,7 @@
   Profile* const profile_;
   NotificationUIManager* const notification_manager_;
   scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
+  std::vector<std::string> enabled_sending_services_;
   static bool avoid_bitmap_fetching_for_test_;
 
   // TODO(petewil): Consider whether a map would better suit our data.
diff --git a/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc b/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc
index e560baf..11b0345 100644
--- a/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc
+++ b/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc
@@ -109,24 +109,24 @@
 
   // Set the title.
   simple_expanded_layout->set_title(title);
+  simple_collapsed_layout->set_heading(title);
 
   // Set the text.
   simple_expanded_layout->set_text(text);
+  simple_collapsed_layout->set_description(text);
+  simple_collapsed_layout->set_annotation(text);
 
   // Set the heading.
   simple_collapsed_layout->set_heading(title);
 
   // Add the collapsed info and set the app_icon_url on it.
-  expanded_info->add_collapsed_info();
-  expanded_info->
-      mutable_collapsed_info(0)->
-      mutable_simple_collapsed_layout()->
+  simple_collapsed_layout->
       mutable_app_icon()->
       set_url(app_icon_url);
 
   // Add the media object and set the image url on it.
-  simple_expanded_layout->add_media();
-  simple_expanded_layout->
+  simple_collapsed_layout->add_media();
+  simple_collapsed_layout->
       mutable_media(0)->
       mutable_image()->
       set_url(image_url);
@@ -136,8 +136,7 @@
   coalesced_notification->set_read_state(read_state);
 
   // Contained notification one.
-  // We re-use the collapsed info we added for the app_icon_url,
-  // so no need to create another one here.
+  expanded_info->add_collapsed_info();
   sync_pb::SimpleCollapsedLayout* notification_layout1 =
       expanded_info->
       mutable_collapsed_info(0)->
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.cc b/chrome/browser/notifications/sync_notifier/synced_notification.cc
index 851c5d6..7dd6c5e 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/notifications/sync_notifier/synced_notification.h"
 
 #include "base/basictypes.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/values.h"
@@ -21,6 +22,14 @@
 
 namespace {
 const char kExtensionScheme[] = "chrome-extension://";
+const char kDefaultSyncedNotificationScheme[] = "https:";
+
+// The name of our first synced notification service.
+// TODO(petewil): remove this hardcoding once we have the synced notification
+// signalling sync data type set up to provide this.
+// crbug.com/248337
+const char kFirstSyncedNotificationServiceId[] = "Google+";
+
 
 // Today rich notifications only supports two buttons, make sure we don't
 // try to supply them with more than this number of buttons.
@@ -30,6 +39,16 @@
   return message_center::IsRichNotificationEnabled();
 }
 
+// Schema-less specs default badly in windows.  If we find one, add the schema
+// we expect instead of allowing windows specific GURL code to make it default
+// to "file:".
+GURL AddDefaultSchemaIfNeeded(std::string& url_spec) {
+  if (StartsWithASCII(url_spec, std::string("//"), false))
+    return GURL(std::string(kDefaultSyncedNotificationScheme) + url_spec);
+
+  return GURL(url_spec);
+}
+
 }  // namespace
 
 namespace notifier {
@@ -76,13 +95,16 @@
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
   // Match the incoming bitmaps to URLs.  In case this is a dup, make sure to
-  // Try all potentially matching urls.
+  // try all potentially matching urls.
   if (GetAppIconUrl() == url && bitmap != NULL) {
     app_icon_bitmap_ = gfx::Image::CreateFrom1xBitmap(*bitmap);
   }
   if (GetImageUrl() == url && bitmap != NULL) {
     image_bitmap_ = gfx::Image::CreateFrom1xBitmap(*bitmap);
   }
+  if (GetProfilePictureUrl(0) == url && bitmap != NULL) {
+    sender_bitmap_ = gfx::Image::CreateFrom1xBitmap(*bitmap);
+  }
 
   // If this URL matches one or more button bitmaps, save them off.
   for (unsigned int i = 0; i < GetButtonCount(); ++i) {
@@ -123,6 +145,13 @@
     AddBitmapToFetchQueue(GetButtonIconUrl(i));
   }
 
+  // If there is a profile image bitmap, fetch it
+  if (GetProfilePictureCount() > 0) {
+    // TODO(petewil): When we have the capacity to display more than one bitmap,
+    // modify this code to fetch as many as we can display
+    AddBitmapToFetchQueue(GetProfilePictureUrl(0));
+  }
+
   // If the URL is non-empty, add it to our queue of URLs to fetch.
   AddBitmapToFetchQueue(GetAppIconUrl());
   AddBitmapToFetchQueue(GetImageUrl());
@@ -171,9 +200,13 @@
   GURL image_url = GetImageUrl();
   string16 text = UTF8ToUTF16(GetText());
   string16 heading = UTF8ToUTF16(GetHeading());
+  string16 description = UTF8ToUTF16(GetDescription());
+  string16 annotation = UTF8ToUTF16(GetAnnotation());
   // TODO(petewil): Eventually put the display name of the sending service here.
   string16 display_source = UTF8ToUTF16(GetOriginUrl().spec());
   string16 replace_key = UTF8ToUTF16(GetKey());
+  string16 notification_heading = heading;
+  string16 notification_text = text;
 
   // The delegate will eventually catch calls that the notification
   // was read or deleted, and send the changes back to the server.
@@ -209,7 +242,7 @@
     // Fill in the button data.
     // TODO(petewil): Today Rich notifiations are limited to two buttons.
     // When rich notifications supports more, remove the
-    // "&& i < kMaxNotificationButtonIndex" below.
+    // "&& i < kMaxNotificationButtonIndex" clause below.
     for (unsigned int i = 0;
          i < button_count
          && i < button_bitmaps_.size()
@@ -239,11 +272,33 @@
       }
     }
 
+    // Set the heading and text appropriately for the message type.
+    notification_text = annotation;
+    if (notification_type == message_center::NOTIFICATION_TYPE_IMAGE) {
+      // For an image, fill in the description field.
+      notification_text = description;
+    } else if (notification_count == 1) {
+      // For a single collapsed info entry, use the contained message if any.
+      std::string comment_body = GetContainedNotificationMessage(0);
+      std::string comment_header = GetContainedNotificationTitle(0);
+      if (!comment_header.empty() && !comment_body.empty())
+        notification_text = UTF8ToUTF16(comment_header) + UTF8ToUTF16(" ") +
+            UTF8ToUTF16(comment_body);
+    }
+
+    // If there is a single person sending, use their picture instead of the app
+    // icon.
+    // TODO(petewil): Someday combine multiple profile photos here.
+    gfx::Image icon_bitmap = app_icon_bitmap_;
+    if (GetProfilePictureCount() == 1)  {
+      icon_bitmap = sender_bitmap_;
+    }
+
     Notification ui_notification(notification_type,
                                  GetOriginUrl(),
-                                 heading,
-                                 text,
-                                 app_icon_bitmap_,
+                                 notification_heading,
+                                 notification_text,
+                                 icon_bitmap,
                                  WebKit::WebTextDirectionDefault,
                                  display_source,
                                  replace_key,
@@ -251,11 +306,11 @@
                                  delegate.get());
     notification_manager->Add(ui_notification, profile);
   } else {
-
+    // In this case we have a Webkit Notification, not a Rich Notification.
     Notification ui_notification(GetOriginUrl(),
                                  GetAppIconUrl(),
-                                 heading,
-                                 text,
+                                 notification_heading,
+                                 notification_text,
                                  WebKit::WebTextDirectionDefault,
                                  display_source,
                                  replace_key,
@@ -272,13 +327,13 @@
 }
 
 // This should detect even small changes in case the server updated the
-// notification.
-// TODO(petewil): Should I also ignore the timestamp if other fields match?
+// notification.  We ignore the timestamp if other fields match.
 bool SyncedNotification::EqualsIgnoringReadState(
     const SyncedNotification& other) const {
   if (GetTitle() == other.GetTitle() &&
       GetHeading() == other.GetHeading() &&
       GetDescription() == other.GetDescription() &&
+      GetAnnotation() == other.GetAnnotation() &&
       GetAppId() == other.GetAppId() &&
       GetKey() == other.GetKey() &&
       GetOriginUrl() == other.GetOriginUrl() &&
@@ -291,7 +346,8 @@
       GetDefaultDestinationTitle() == other.GetDefaultDestinationTitle() &&
       GetDefaultDestinationIconUrl() == other.GetDefaultDestinationIconUrl() &&
       GetNotificationCount() == other.GetNotificationCount() &&
-      GetButtonCount() == other.GetButtonCount()) {
+      GetButtonCount() == other.GetButtonCount() &&
+      GetProfilePictureCount() == other.GetProfilePictureCount()) {
 
     // If all the surface data matched, check, to see if contained data also
     // matches, titles and messages.
@@ -314,6 +370,13 @@
         return false;
     }
 
+    // Make sure profile icons match
+    count = GetButtonCount();
+    for (size_t kk = 0; kk < count; ++kk) {
+      if (GetProfilePictureUrl(kk) != other.GetProfilePictureUrl(kk))
+        return false;
+    }
+
     // If buttons and notifications matched, they are equivalent.
     return true;
   }
@@ -369,6 +432,15 @@
       simple_collapsed_layout().description();
 }
 
+std::string SyncedNotification::GetAnnotation() const {
+  if (!specifics_.coalesced_notification().render_info().collapsed_info().
+      simple_collapsed_layout().has_annotation())
+    return std::string();
+
+  return specifics_.coalesced_notification().render_info().collapsed_info().
+      simple_collapsed_layout().annotation();
+}
+
 std::string SyncedNotification::GetAppId() const {
   if (!specifics_.coalesced_notification().has_app_id())
     return std::string();
@@ -387,35 +459,32 @@
   return GURL(origin_url);
 }
 
-// TODO(petewil): This only returns the first icon. Make all the icons
-// available.
 GURL SyncedNotification::GetAppIconUrl() const {
-  if (specifics_.coalesced_notification().render_info().expanded_info().
-      collapsed_info_size() == 0)
+  if (!specifics_.coalesced_notification().render_info().collapsed_info().
+      simple_collapsed_layout().has_app_icon())
     return GURL();
 
-  if (!specifics_.coalesced_notification().render_info().expanded_info().
-      collapsed_info(0).simple_collapsed_layout().has_app_icon())
-    return GURL();
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+              collapsed_info().simple_collapsed_layout().app_icon().url();
 
-  return GURL(specifics_.coalesced_notification().render_info().
-              expanded_info().collapsed_info(0).simple_collapsed_layout().
-              app_icon().url());
+  return AddDefaultSchemaIfNeeded(url_spec);
 }
 
-// TODO(petewil): This currenly only handles the first image from the first
-// collapsed item, someday return all images.
+// TODO(petewil): This ignores all but the first image.  If Rich Notifications
+// supports more images someday, then fetch all images.
 GURL SyncedNotification::GetImageUrl() const {
-  if (specifics_.coalesced_notification().render_info().expanded_info().
-      simple_expanded_layout().media_size() == 0)
+  if (specifics_.coalesced_notification().render_info().collapsed_info().
+      simple_collapsed_layout().media_size() == 0)
     return GURL();
 
-  if (!specifics_.coalesced_notification().render_info().expanded_info().
-      simple_expanded_layout().media(0).image().has_url())
+  if (!specifics_.coalesced_notification().render_info().collapsed_info().
+      simple_collapsed_layout().media(0).image().has_url())
     return GURL();
 
-  return GURL(specifics_.coalesced_notification().render_info().
-              expanded_info().simple_expanded_layout().media(0).image().url());
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+              collapsed_info().simple_collapsed_layout().media(0).image().url();
+
+  return AddDefaultSchemaIfNeeded(url_spec);
 }
 
 std::string SyncedNotification::GetText() const {
@@ -470,7 +539,9 @@
     return message_center::DEFAULT_PRIORITY;
   } else if (protobuf_priority ==
              sync_pb::CoalescedSyncedNotification_Priority_HIGH) {
-    return message_center::HIGH_PRIORITY;
+    // High priority synced notifications are considered default priority in
+    // Chrome.
+    return message_center::DEFAULT_PRIORITY;
   } else {
     // Complain if this is a new priority we have not seen before.
     DCHECK(protobuf_priority <
@@ -491,6 +562,23 @@
       target_size();
 }
 
+size_t SyncedNotification::GetProfilePictureCount() const {
+  return specifics_.coalesced_notification().render_info().collapsed_info().
+      simple_collapsed_layout().profile_image_size();
+}
+
+GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const {
+  if (GetProfilePictureCount() <= which_url)
+    return GURL();
+
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+      collapsed_info().simple_collapsed_layout().profile_image(which_url).
+      image_url();
+
+  return AddDefaultSchemaIfNeeded(url_spec);
+}
+
+
 std::string SyncedNotification::GetDefaultDestinationTitle() const {
   if (!specifics_.coalesced_notification().render_info().collapsed_info().
       default_destination().icon().has_alt_text()) {
@@ -505,8 +593,10 @@
       default_destination().icon().has_url()) {
     return GURL();
   }
-  return GURL(specifics_.coalesced_notification().render_info().
-              collapsed_info().default_destination().icon().url());
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+              collapsed_info().default_destination().icon().url();
+
+  return AddDefaultSchemaIfNeeded(url_spec);
 }
 
 GURL SyncedNotification::GetDefaultDestinationUrl() const {
@@ -514,8 +604,10 @@
       default_destination().has_url()) {
     return GURL();
   }
-  return GURL(specifics_.coalesced_notification().render_info().
-              collapsed_info().default_destination().url());
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+              collapsed_info().default_destination().url();
+
+  return AddDefaultSchemaIfNeeded(url_spec);
 }
 
 std::string SyncedNotification::GetButtonTitle(
@@ -539,8 +631,10 @@
       target(which_button).action().icon().has_url()) {
     return GURL();
   }
-  return GURL(specifics_.coalesced_notification().render_info().
-              collapsed_info().target(which_button).action().icon().url());
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+              collapsed_info().target(which_button).action().icon().url();
+
+  return AddDefaultSchemaIfNeeded(url_spec);
 }
 
 GURL SyncedNotification::GetButtonUrl(unsigned int which_button) const {
@@ -551,8 +645,10 @@
       target(which_button).action().has_url()) {
     return GURL();
   }
-  return GURL(specifics_.coalesced_notification().render_info().
-              collapsed_info().target(which_button).action().url());
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+              collapsed_info().target(which_button).action().url();
+
+  return AddDefaultSchemaIfNeeded(url_spec);
 }
 
 std::string SyncedNotification::GetContainedNotificationTitle(
@@ -575,4 +671,12 @@
       collapsed_info(index).simple_collapsed_layout().description();
 }
 
+std::string SyncedNotification::GetSendingServiceId() const {
+  // TODO(petewil): We are building a new protocol (a new sync datatype) to send
+  // the service name and icon from the server.  For now this method is
+  // hardcoded to the name of our first service using synced notifications.
+  // Once the new protocol is built, remove this hardcoding.
+  return kFirstSyncedNotificationServiceId;
+}
+
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.h b/chrome/browser/notifications/sync_notifier/synced_notification.h
index fd3ee55..cba6863 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.h
@@ -52,6 +52,7 @@
   std::string GetTitle() const;
   std::string GetHeading() const;
   std::string GetDescription() const;
+  std::string GetAnnotation() const;
   std::string GetAppId() const;
   std::string GetKey() const;
   GURL GetOriginUrl() const;
@@ -67,10 +68,13 @@
   std::string GetButtonTitle(unsigned int which_button) const;
   GURL GetButtonIconUrl(unsigned int which_button) const;
   GURL GetButtonUrl(unsigned int which_button) const;
+  GURL GetProfilePictureUrl(unsigned int which_url) const;
+  size_t GetProfilePictureCount() const;
   size_t GetNotificationCount() const;
   size_t GetButtonCount() const;
   std::string GetContainedNotificationTitle(int index) const;
   std::string GetContainedNotificationMessage(int index) const;
+  std::string GetSendingServiceId() const;
 
 
   bool EqualsIgnoringReadState(const SyncedNotification& other) const;
@@ -112,6 +116,7 @@
   ScopedVector<NotificationBitmapFetcher> fetchers_;
   int active_fetcher_count_;
   gfx::Image app_icon_bitmap_;
+  gfx::Image sender_bitmap_;
   gfx::Image image_bitmap_;
   std::vector<gfx::Image> button_bitmaps_;
 
diff --git a/chrome/browser/page_cycler/page_cycler_unittest.cc b/chrome/browser/page_cycler/page_cycler_unittest.cc
index cbfc07e..2ef95fe 100644
--- a/chrome/browser/page_cycler/page_cycler_unittest.cc
+++ b/chrome/browser/page_cycler/page_cycler_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/file_util.h"
 #include "base/path_service.h"
 #include "base/prefs/testing_pref_service.h"
+#include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -150,7 +151,7 @@
 
   void PumpLoop() {
     content::BrowserThread::GetBlockingPool()->FlushForTesting();
-    message_loop()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   void CloseBrowser() {
@@ -310,7 +311,7 @@
       DidFinishLoad(kFrameID, kAboutURL, kIsMainFrame, _))
       .WillOnce(Invoke(page_cycler(),
                        &MockPageCycler::PageCyclerDidFinishLoad));
-  message_loop()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   FinishLoad();
 
diff --git a/chrome/browser/password_manager/password_generation_manager_unittest.cc b/chrome/browser/password_manager/password_generation_manager_unittest.cc
index ac691d9..22f2050 100644
--- a/chrome/browser/password_manager/password_generation_manager_unittest.cc
+++ b/chrome/browser/password_manager/password_generation_manager_unittest.cc
@@ -44,7 +44,6 @@
 class PasswordGenerationManagerTest : public ChromeRenderViewHostTestHarness {
  protected:
   virtual void SetUp() OVERRIDE {
-
     SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
     ChromeRenderViewHostTestHarness::SetUp();
 
@@ -56,12 +55,6 @@
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
-  virtual content::BrowserContext* CreateBrowserContext() OVERRIDE {
-    TestingProfile* profile = new TestingProfile();
-    profile->CreateRequestContext();
-    return profile;
-  }
-
   void UpdateState(bool new_renderer) {
     password_generation_manager_->UpdateState(NULL, new_renderer);
   }
@@ -77,7 +70,6 @@
     TestingProfile::Builder builder;
     scoped_ptr<TestingProfile> profile = builder.Build();
     profile->set_incognito(true);
-    profile->CreateRequestContext();
     return profile.release();
   }
 };
diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc
index ed6e8fe..a8d718d 100644
--- a/chrome/browser/password_manager/password_store_x_unittest.cc
+++ b/chrome/browser/password_manager/password_store_x_unittest.cc
@@ -9,11 +9,11 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/platform_file.h"
 #include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
 #include "base/time/time.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/password_manager/password_form_data.h"
@@ -23,15 +23,15 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/test/mock_notification_observer.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using base::WaitableEvent;
 using content::BrowserThread;
 using testing::_;
 using testing::DoAll;
@@ -56,44 +56,25 @@
 
 // This class will add and remove a mock notification observer from
 // the DB thread.
-class DBThreadObserverHelper
-    : public base::RefCountedThreadSafe<DBThreadObserverHelper,
-                                        BrowserThread::DeleteOnDBThread> {
+class DBThreadObserverHelper {
  public:
-  DBThreadObserverHelper() : done_event_(true, false) {}
+  DBThreadObserverHelper() {}
+
+  ~DBThreadObserverHelper() {
+    registrar_.RemoveAll();
+  }
 
   void Init(PasswordStore* password_store) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    BrowserThread::PostTask(
-        BrowserThread::DB,
-        FROM_HERE,
-        base::Bind(&DBThreadObserverHelper::AddObserverTask,
-                   this, make_scoped_refptr(password_store)));
-    done_event_.Wait();
+    registrar_.Add(&observer_,
+                   chrome::NOTIFICATION_LOGINS_CHANGED,
+                   content::Source<PasswordStore>(password_store));
   }
 
   content::MockNotificationObserver& observer() {
     return observer_;
   }
 
- protected:
-  friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>;
-  friend class base::DeleteHelper<DBThreadObserverHelper>;
-
-  virtual ~DBThreadObserverHelper() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-    registrar_.RemoveAll();
-  }
-
-  void AddObserverTask(PasswordStore* password_store) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-    registrar_.Add(&observer_,
-                   chrome::NOTIFICATION_LOGINS_CHANGED,
-                   content::Source<PasswordStore>(password_store));
-    done_event_.Signal();
-  }
-
-  WaitableEvent done_event_;
+ private:
   content::NotificationRegistrar registrar_;
   content::MockNotificationObserver observer_;
 };
@@ -269,13 +250,7 @@
 
 class PasswordStoreXTest : public testing::TestWithParam<BackendType> {
  protected:
-  PasswordStoreXTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        db_thread_(BrowserThread::DB) {
-  }
-
   virtual void SetUp() {
-    ASSERT_TRUE(db_thread_.Start());
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 
     profile_.reset(new TestingProfile());
@@ -285,10 +260,7 @@
   }
 
   virtual void TearDown() {
-    base::MessageLoop::current()->PostTask(FROM_HERE,
-                                           base::MessageLoop::QuitClosure());
-    base::MessageLoop::current()->Run();
-    db_thread_.Stop();
+    base::RunLoop().RunUntilIdle();
   }
 
   PasswordStoreX::NativeBackend* GetBackend() {
@@ -302,10 +274,7 @@
     }
   }
 
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  // PasswordStore, WDS schedule work on this thread.
-  content::TestBrowserThread db_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   scoped_ptr<LoginDatabase> login_db_;
   scoped_ptr<TestingProfile> profile_;
@@ -316,11 +285,6 @@
   STLDeleteContainerPointers(arg0.begin(), arg0.end());
 }
 
-ACTION(QuitUIMessageLoop) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  base::MessageLoop::current()->Quit();
-}
-
 TEST_P(PasswordStoreXTest, Notifications) {
   scoped_refptr<PasswordStoreX> store(
       new PasswordStoreX(login_db_.release(),
@@ -341,15 +305,15 @@
     true, false, 1 };
   scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
 
-  scoped_refptr<DBThreadObserverHelper> helper = new DBThreadObserverHelper;
-  helper->Init(store.get());
+  DBThreadObserverHelper helper;
+  helper.Init(store.get());
 
   const PasswordStoreChange expected_add_changes[] = {
     PasswordStoreChange(PasswordStoreChange::ADD, *form),
   };
 
   EXPECT_CALL(
-      helper->observer(),
+      helper.observer(),
       Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED),
               content::Source<PasswordStore>(store.get()),
               Property(&content::Details<const PasswordStoreChangeList>::ptr,
@@ -358,12 +322,9 @@
   // Adding a login should trigger a notification.
   store->AddLogin(*form);
 
-  // The PasswordStore schedules tasks to run on the DB thread so we schedule
-  // yet another task to notify us that it's safe to carry on with the test.
-  WaitableEvent done(false, false);
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
+  // The PasswordStore schedules tasks to run on the DB thread. Wait for them
+  // to complete.
+  base::RunLoop().RunUntilIdle();
 
   // Change the password.
   form->password_value = WideToUTF16(L"a different password");
@@ -373,7 +334,7 @@
   };
 
   EXPECT_CALL(
-      helper->observer(),
+      helper.observer(),
       Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED),
               content::Source<PasswordStore>(store.get()),
               Property(&content::Details<const PasswordStoreChangeList>::ptr,
@@ -382,17 +343,15 @@
   // Updating the login with the new password should trigger a notification.
   store->UpdateLogin(*form);
 
-  // Wait for PasswordStore to send the notification.
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
+  // Wait for PasswordStore to send execute.
+  base::RunLoop().RunUntilIdle();
 
   const PasswordStoreChange expected_delete_changes[] = {
     PasswordStoreChange(PasswordStoreChange::REMOVE, *form),
   };
 
   EXPECT_CALL(
-      helper->observer(),
+      helper.observer(),
       Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED),
               content::Source<PasswordStore>(store.get()),
               Property(&content::Details<const PasswordStoreChangeList>::ptr,
@@ -401,10 +360,8 @@
   // Deleting the login should trigger a notification.
   store->RemoveLogin(*form);
 
-  // Wait for PasswordStore to send the notification.
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
+  // Wait for PasswordStore to execute.
+  base::RunLoop().RunUntilIdle();
 
   // Public in PasswordStore, protected in PasswordStoreX.
   static_cast<PasswordStore*>(store.get())->ShutdownOnUIThread();
@@ -428,26 +385,13 @@
   // Populate the login DB with logins that should be migrated.
   for (VectorOfForms::iterator it = expected_autofillable.begin();
        it != expected_autofillable.end(); ++it) {
-    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-                            base::Bind(
-                                base::IgnoreResult(&LoginDatabase::AddLogin),
-                                base::Unretained(login_db), **it));
+    login_db->AddLogin(**it);
   }
   for (VectorOfForms::iterator it = expected_blacklisted.begin();
        it != expected_blacklisted.end(); ++it) {
-    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-                            base::Bind(
-                                base::IgnoreResult(&LoginDatabase::AddLogin),
-                                base::Unretained(login_db), **it));
+    login_db->AddLogin(**it);
   }
 
-  // Schedule another task on the DB thread to notify us that it's safe to
-  // carry on with the test.
-  WaitableEvent done(false, false);
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
-
   // Get the new size of the login DB file. We expect it to be larger.
   base::PlatformFileInfo db_file_full_info;
   ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_full_info));
@@ -462,27 +406,23 @@
 
   MockPasswordStoreConsumer consumer;
 
-  // Make sure we quit the MessageLoop even if the test fails.
-  ON_CALL(consumer, OnPasswordStoreRequestDone(_, _))
-      .WillByDefault(QuitUIMessageLoop());
-
   // The autofillable forms should have been migrated to the native backend.
   EXPECT_CALL(consumer,
       OnPasswordStoreRequestDone(_,
           ContainsAllPasswordForms(expected_autofillable)))
-      .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop()));
+      .WillOnce(WithArg<1>(STLDeleteElements0()));
 
   store->GetAutofillableLogins(&consumer);
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 
   // The blacklisted forms should have been migrated to the native backend.
   EXPECT_CALL(consumer,
       OnPasswordStoreRequestDone(_,
           ContainsAllPasswordForms(expected_blacklisted)))
-      .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop()));
+      .WillOnce(WithArg<1>(STLDeleteElements0()));
 
   store->GetBlacklistLogins(&consumer);
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
 
   VectorOfForms empty;
   MockLoginDatabaseReturn ld_return;
@@ -499,14 +439,10 @@
         .WillOnce(WithArg<0>(STLDeleteElements0()));
   }
 
-  BrowserThread::PostTask(
-      BrowserThread::DB, FROM_HERE,
-      base::Bind(&LoginDatabaseQueryCallback, login_db, true, &ld_return));
+  LoginDatabaseQueryCallback(login_db, true, &ld_return);
 
-  // Wait for the login DB methods to execute on the DB thread.
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
+  // Wait for the login DB methods to execute.
+  base::RunLoop().RunUntilIdle();
 
   if (GetParam() == WORKING_BACKEND) {
     // Likewise, no blacklisted logins should be left in the login DB.
@@ -520,14 +456,10 @@
         .WillOnce(WithArg<0>(STLDeleteElements0()));
   }
 
-  BrowserThread::PostTask(
-      BrowserThread::DB, FROM_HERE,
-      base::Bind(&LoginDatabaseQueryCallback, login_db, false, &ld_return));
+  LoginDatabaseQueryCallback(login_db, false, &ld_return);
 
-  // Wait for the login DB methods to execute on the DB thread.
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
+  // Wait for the login DB methods to execute.
+  base::RunLoop().RunUntilIdle();
 
   if (GetParam() == WORKING_BACKEND) {
     // If the migration succeeded, then not only should there be no logins left
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 2a1d1cf..fa84816 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -60,7 +60,6 @@
 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
 #include "chrome/browser/chromeos/policy/network_configuration_updater.h"
 #include "chrome/browser/chromeos/policy/network_configuration_updater_impl.h"
-#include "chrome/browser/chromeos/policy/network_configuration_updater_impl_cros.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/cros_settings_provider.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
@@ -208,19 +207,10 @@
   policy_statistics_collector_->Initialize();
 
 #if defined(OS_CHROMEOS)
-  if (command_line->HasSwitch(
-          chromeos::switches::kUseNewNetworkConfigurationHandlers)) {
-    network_configuration_updater_.reset(
-        new NetworkConfigurationUpdaterImpl(
-            GetPolicyService(),
-            make_scoped_ptr(new chromeos::CertificateHandler)));
-  } else {
-    network_configuration_updater_.reset(
-        new NetworkConfigurationUpdaterImplCros(
-            GetPolicyService(),
-            chromeos::NetworkLibrary::Get(),
-            make_scoped_ptr(new chromeos::CertificateHandler)));
-  }
+  network_configuration_updater_.reset(
+      new NetworkConfigurationUpdaterImpl(
+          GetPolicyService(),
+          make_scoped_ptr(new chromeos::CertificateHandler)));
 #endif
 
   is_initialized_ = true;
diff --git a/chrome/browser/policy/cloud/device_management_service_unittest.cc b/chrome/browser/policy/cloud/device_management_service_unittest.cc
index e1b1f2f..2838bfc 100644
--- a/chrome/browser/policy/cloud/device_management_service_unittest.cc
+++ b/chrome/browser/policy/cloud/device_management_service_unittest.cc
@@ -6,12 +6,12 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
 #include "chrome/browser/policy/cloud/device_management_service.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
@@ -22,7 +22,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
 using testing::Mock;
 using testing::_;
 
@@ -49,16 +48,14 @@
 // without calling into the actual network stack.
 class DeviceManagementServiceTestBase : public testing::Test {
  protected:
-  DeviceManagementServiceTestBase()
-      : ui_thread_(BrowserThread::UI, &loop_),
-        io_thread_(BrowserThread::IO, &loop_) {
+  DeviceManagementServiceTestBase() {
     ResetService();
     InitializeService();
   }
 
-  virtual void TearDown() {
+  ~DeviceManagementServiceTestBase() {
     service_.reset();
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   void ResetService() {
@@ -67,7 +64,7 @@
 
   void InitializeService() {
     service_->ScheduleInitialization(0);
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   net::TestURLFetcher* GetFetcher() {
@@ -166,9 +163,7 @@
   scoped_ptr<DeviceManagementService> service_;
 
  private:
-  base::MessageLoopForUI loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 struct FailedRequestParams {
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
index 82539a3..70b0c46 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -28,7 +28,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/http/http_status_code.h"
@@ -140,10 +140,7 @@
 class UserPolicySigninServiceTest : public testing::Test {
  public:
   UserPolicySigninServiceTest()
-      : loop_(base::MessageLoop::TYPE_IO),
-        ui_thread_(content::BrowserThread::UI, &loop_),
-        file_thread_(content::BrowserThread::FILE, &loop_),
-        io_thread_(content::BrowserThread::IO, &loop_),
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
         register_completed_(false) {}
 
   MOCK_METHOD1(OnPolicyRefresh, void(bool));
@@ -186,7 +183,6 @@
     TestingProfile::Builder builder;
     builder.SetPrefService(scoped_ptr<PrefServiceSyncable>(prefs.Pass()));
     profile_ = builder.Build().Pass();
-    profile_->CreateRequestContext();
 
     mock_store_ = new MockUserCloudPolicyStore();
     EXPECT_CALL(*mock_store_, Load()).Times(AnyNumber());
@@ -340,10 +336,7 @@
 
   // BrowserPolicyConnector and UrlFetcherFactory want to initialize and free
   // various components asynchronously via tasks, so create fake threads here.
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   net::TestURLFetcherFactory url_factory_;
 
diff --git a/chrome/browser/policy/policy_service_impl_unittest.cc b/chrome/browser/policy/policy_service_impl_unittest.cc
index f185abc..508ae44 100644
--- a/chrome/browser/policy/policy_service_impl_unittest.cc
+++ b/chrome/browser/policy/policy_service_impl_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/policy/external_data_fetcher.h"
@@ -18,7 +17,7 @@
 #include "chrome/browser/policy/policy_domain_descriptor.h"
 #include "chrome/common/policy/policy_schema.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -155,7 +154,7 @@
   PolicyMap policy1_;
   PolicyMap policy2_;
   scoped_ptr<PolicyServiceImpl> policy_service_;
-  base::MessageLoop loop_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PolicyServiceTest);
@@ -436,10 +435,6 @@
 }
 
 TEST_F(PolicyServiceTest, RefreshPolicies) {
-  content::TestBrowserThread ui_thread(content::BrowserThread::UI, &loop_);
-  content::TestBrowserThread file_thread(content::BrowserThread::FILE, &loop_);
-  content::TestBrowserThread io_thread(content::BrowserThread::IO, &loop_);
-
   EXPECT_CALL(provider0_, RefreshPolicies()).Times(AnyNumber());
   EXPECT_CALL(provider1_, RefreshPolicies()).Times(AnyNumber());
   EXPECT_CALL(provider2_, RefreshPolicies()).Times(AnyNumber());
diff --git a/chrome/browser/policy/policy_statistics_collector_unittest.cc b/chrome/browser/policy/policy_statistics_collector_unittest.cc
index aafea13..caee502 100644
--- a/chrome/browser/policy/policy_statistics_collector_unittest.cc
+++ b/chrome/browser/policy/policy_statistics_collector_unittest.cc
@@ -34,7 +34,7 @@
 using testing::ReturnRef;
 
 // Arbitrary policy names used for testing.
-const char* const kTestPolicy1 = key::kHomepageIsNewTabPage;
+const char* const kTestPolicy1 = key::kAlternateErrorPagesEnabled;
 const char* const kTestPolicy2 = key::kSearchSuggestEnabled;
 
 class TestPolicyStatisticsCollector : public PolicyStatisticsCollector {
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 14cc6a7..5e90827 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -145,6 +145,7 @@
 #include "chrome/browser/chromeos/status/data_promo_notification.h"
 #include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
 #include "chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
+#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #else
 #include "chrome/browser/extensions/default_apps.h"
 #endif
@@ -262,6 +263,7 @@
   chromeos::proxy_config::RegisterPrefs(registry);
   chromeos::RegisterDisplayLocalStatePrefs(registry);
   chromeos::ServicesCustomizationDocument::RegisterPrefs(registry);
+  chromeos::SigninScreenHandler::RegisterPrefs(registry);
   chromeos::system::AutomaticRebootManager::RegisterPrefs(registry);
   chromeos::UserImageManager::RegisterPrefs(registry);
   chromeos::UserManager::RegisterPrefs(registry);
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 957809f..12ba041 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -95,8 +95,11 @@
       WindowContainerType window_container_type,
       const string16& frame_name,
       const GURL& target_url,
+      const content::Referrer& referrer,
       WindowOpenDisposition disposition,
-      bool user_gesture) OVERRIDE {
+      const WebKit::WebWindowFeatures& features,
+      bool user_gesture,
+      bool opener_suppressed) OVERRIDE {
     // Since we don't want to permit child windows that would have a
     // window.opener property, terminate prerendering.
     prerender_contents_->Destroy(FINAL_STATUS_CREATE_NEW_WINDOW);
diff --git a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
index 79e0280..7064156 100644
--- a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
+++ b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
@@ -11,9 +11,12 @@
 #include "base/message_loop/message_loop.h"
 #include "base/process_util.h"
 #include "base/rand_util.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/test/multiprocess_test.h"
 #include "base/test/test_timeouts.h"
+#include "base/time/default_tick_clock.h"
 #include "base/time/time.h"
+#include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
 #include "chrome/browser/service/service_process_control.h"
@@ -26,13 +29,14 @@
 #include "chrome/service/service_process.h"
 #include "chrome/test/base/test_launcher_utils.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_io_thread_state.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "ipc/ipc_descriptors.h"
 #include "ipc/ipc_multiprocess_test.h"
 #include "ipc/ipc_switches.h"
@@ -57,6 +61,7 @@
 using ::testing::Return;
 using ::testing::WithoutArgs;
 using ::testing::_;
+using content::BrowserThread;
 
 namespace {
 
@@ -205,17 +210,23 @@
 int CloudPrintMockService_Main(SetExpectationsCallback set_expectations) {
   base::MessageLoopForUI main_message_loop;
   main_message_loop.set_thread_name("Main Thread");
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
 
 #if defined(OS_MACOSX)
-  CommandLine* cl = CommandLine::ForCurrentProcess();
-  if (!cl->HasSwitch(kTestExecutablePath))
+  if (!command_line->HasSwitch(kTestExecutablePath))
     return kMissingSwitch;
-  base::FilePath executable_path = cl->GetSwitchValuePath(kTestExecutablePath);
+  base::FilePath executable_path =
+      command_line->GetSwitchValuePath(kTestExecutablePath);
   EXPECT_FALSE(executable_path.empty());
   MockLaunchd mock_launchd(executable_path, &main_message_loop, true, true);
   Launchd::ScopedInstance use_mock(&mock_launchd);
 #endif
 
+  base::FilePath user_data_dir =
+      command_line->GetSwitchValuePath(switches::kUserDataDir);
+  CHECK(!user_data_dir.empty());
+  CHECK(test_launcher_utils::OverrideUserDataDir(user_data_dir));
+
   ServiceProcessState* state(new ServiceProcessState);
   bool service_process_state_initialized = state->Initialize();
   EXPECT_TRUE(service_process_state_initialized);
@@ -289,8 +300,8 @@
   virtual ~CloudPrintProxyPolicyStartupTest();
 
   virtual void SetUp();
-  base::MessageLoopProxy* IOMessageLoopProxy() {
-    return io_thread_.message_loop_proxy().get();
+  scoped_refptr<base::MessageLoopProxy> IOMessageLoopProxy() {
+    return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
   }
   base::ProcessHandle Launch(const std::string& name);
   void WaitForConnect();
@@ -316,9 +327,8 @@
   }
 
  protected:
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  base::Thread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
+  base::ScopedTempDir temp_user_data_dir_;
 
   std::string startup_channel_id_;
   scoped_ptr<IPC::ChannelProxy> startup_channel_;
@@ -359,28 +369,43 @@
 };
 
 CloudPrintProxyPolicyStartupTest::CloudPrintProxyPolicyStartupTest()
-    : ui_thread_(content::BrowserThread::UI, &message_loop_),
-      io_thread_("CloudPrintProxyPolicyTestThread") {
+    : thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) {
 }
 
 CloudPrintProxyPolicyStartupTest::~CloudPrintProxyPolicyStartupTest() {
 }
 
 void CloudPrintProxyPolicyStartupTest::SetUp() {
-  base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
-  ASSERT_TRUE(io_thread_.StartWithOptions(options));
-
 #if defined(OS_MACOSX)
   EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
   EXPECT_TRUE(MockLaunchd::MakeABundle(temp_dir_.path(),
                                        "CloudPrintProxyTest",
                                        &bundle_path_,
                                        &executable_path_));
-  mock_launchd_.reset(new MockLaunchd(executable_path_, &message_loop_,
+  mock_launchd_.reset(new MockLaunchd(executable_path_,
+                                      base::MessageLoopForUI::current(),
                                       true, false));
   scoped_launchd_instance_.reset(
       new Launchd::ScopedInstance(mock_launchd_.get()));
 #endif
+
+  // Ensure test does not use the standard profile directory. This is copied
+  // from InProcessBrowserTest::SetUp(). These tests require a more complex
+  // process startup so they are unable to just inherit from
+  // InProcessBrowserTest.
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  base::FilePath user_data_dir =
+      command_line->GetSwitchValuePath(switches::kUserDataDir);
+  if (user_data_dir.empty()) {
+    ASSERT_TRUE(temp_user_data_dir_.CreateUniqueTempDir() &&
+                temp_user_data_dir_.IsValid())
+        << "Could not create temporary user data directory \""
+        << temp_user_data_dir_.path().value() << "\".";
+
+    user_data_dir = temp_user_data_dir_.path();
+    command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
+  }
+  ASSERT_TRUE(test_launcher_utils::OverrideUserDataDir(user_data_dir));
 }
 
 base::ProcessHandle CloudPrintProxyPolicyStartupTest::Launch(
@@ -452,10 +477,21 @@
 }
 
 TEST_F(CloudPrintProxyPolicyStartupTest, StartAndShutdown) {
+  TestingBrowserProcess* browser_process =
+      TestingBrowserProcess::GetGlobal();
+  TestingProfileManager profile_manager(browser_process);
+  ASSERT_TRUE(profile_manager.SetUp());
+
+  // Must be created after the TestingProfileManager since that creates the
+  // LocalState for the BrowserProcess.  Must be created before profiles are
+  // constructed.
+  chrome::TestingIOThreadState testing_io_thread_state;
+
   base::ProcessHandle handle =
       Launch("CloudPrintMockService_StartEnabledWaitForQuit");
   WaitForConnect();
   ShutdownAndWaitForExitWithTimeout(handle);
+  content::RunAllPendingInMessageLoop();
 }
 
 BrowserContextKeyedService* CloudPrintProxyServiceFactoryForPolicyTest(
@@ -470,11 +506,18 @@
   base::ProcessHandle handle =
       Launch("CloudPrintMockService_StartEnabledWaitForQuit");
 
+  // Setup the Browser Process with a full IOThread::Globals.
   TestingBrowserProcess* browser_process =
       TestingBrowserProcess::GetGlobal();
+
   TestingProfileManager profile_manager(browser_process);
   ASSERT_TRUE(profile_manager.SetUp());
 
+  // Must be created after the TestingProfileManager since that creates the
+  // LocalState for the BrowserProcess.  Must be created before profiles are
+  // constructed.
+  chrome::TestingIOThreadState testing_io_thread_state;
+
   TestingProfile* profile =
       profile_manager.CreateTestingProfile("StartBrowserWithoutPolicy");
   CloudPrintProxyServiceFactory::GetInstance()->
@@ -490,20 +533,22 @@
   test_launcher_utils::PrepareBrowserCommandLineForTests(&command_line);
 
   WaitForConnect();
+  base::RunLoop run_loop;
   base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
-      base::MessageLoop::QuitClosure(),
+      run_loop.QuitClosure(),
       TestTimeouts::action_timeout());
 
-  bool run_loop = LaunchBrowser(command_line, profile);
-  EXPECT_FALSE(run_loop);
-  if (run_loop)
-    base::MessageLoop::current()->Run();
+  bool should_run_loop = LaunchBrowser(command_line, profile);
+  EXPECT_FALSE(should_run_loop);
+  if (should_run_loop)
+    run_loop.Run();
 
   EXPECT_EQ(MockServiceIPCServer::EnabledUserId(),
             prefs->GetString(prefs::kCloudPrintEmail));
 
   ShutdownAndWaitForExitWithTimeout(handle);
+  content::RunAllPendingInMessageLoop();
   profile_manager.DeleteTestingProfile("StartBrowserWithoutPolicy");
 }
 
@@ -516,6 +561,11 @@
   TestingProfileManager profile_manager(browser_process);
   ASSERT_TRUE(profile_manager.SetUp());
 
+  // Must be created after the TestingProfileManager since that creates the
+  // LocalState for the BrowserProcess.  Must be created before profiles are
+  // constructed.
+  chrome::TestingIOThreadState testing_io_thread_state;
+
   TestingProfile* profile =
       profile_manager.CreateTestingProfile("StartBrowserWithPolicy");
   CloudPrintProxyServiceFactory::GetInstance()->
@@ -533,20 +583,22 @@
   test_launcher_utils::PrepareBrowserCommandLineForTests(&command_line);
 
   WaitForConnect();
+  base::RunLoop run_loop;
   base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
-      base::MessageLoop::QuitClosure(),
+      run_loop.QuitClosure(),
       TestTimeouts::action_timeout());
 
-  bool run_loop = LaunchBrowser(command_line, profile);
+  bool should_run_loop = LaunchBrowser(command_line, profile);
 
   // No expectations on run_loop being true here; that would be a race
   // condition.
-  if (run_loop)
-    base::MessageLoop::current()->Run();
+  if (should_run_loop)
+    run_loop.Run();
 
   EXPECT_EQ("", prefs->GetString(prefs::kCloudPrintEmail));
 
   ShutdownAndWaitForExitWithTimeout(handle);
+  content::RunAllPendingInMessageLoop();
   profile_manager.DeleteTestingProfile("StartBrowserWithPolicy");
 }
diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc
index 0ffcaf2..a3298f5 100644
--- a/chrome/browser/printing/print_job_worker.cc
+++ b/chrome/browser/printing/print_job_worker.cc
@@ -40,13 +40,12 @@
                           JobEventDetails::Type detail_type,
                           PrintedDocument* document,
                           PrintedPage* page) {
-  scoped_refptr<JobEventDetails> details(new JobEventDetails(detail_type,
-                                                             document, page));
+  JobEventDetails* details = new JobEventDetails(detail_type, document, page);
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_PRINT_JOB_EVENT,
       // We know that is is a PrintJob object in this circumstance.
       content::Source<PrintJob>(static_cast<PrintJob*>(print_job)),
-      content::Details<JobEventDetails>(details.get()));
+      content::Details<JobEventDetails>(details));
 }
 
 PrintJobWorker::PrintJobWorker(PrintJobWorkerOwner* owner)
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index 3228c41..a14d3ab 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -286,7 +286,7 @@
       int render_view_id,
       const GURL& requesting_frame,
       const MIDISysExPermissionCallback& callback) {
-  // TODO(toyoshim): Implement.
+  // TODO(toyoshim): Implement. http://crbug.com/257618 .
   callback.Run(false);
 }
 
diff --git a/chrome/browser/profiles/off_the_record_profile_impl_unittest.cc b/chrome/browser/profiles/off_the_record_profile_impl_unittest.cc
index 0b9a9b9..630fc6e 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl_unittest.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl_unittest.cc
@@ -6,16 +6,19 @@
 
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
 #include "chrome/browser/net/ssl_config_service_manager.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_io_thread_state.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 #include "content/public/browser/host_zoom_map.h"
+#include "net/dns/mock_host_resolver.h"
 
 using content::HostZoomMap;
 
@@ -68,7 +71,7 @@
   scoped_ptr<Profile> off_the_record_profile_;
   scoped_ptr<SSLConfigServiceManager> ssl_config_service_manager_;
 
-  content::HostZoomMap::ZoomLevelChangedCallback zoom_callback_;
+  HostZoomMap::ZoomLevelChangedCallback zoom_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(TestingProfileWithHostZoomMap);
 };
@@ -85,19 +88,21 @@
   virtual ~OffTheRecordProfileImplTest() {}
 
   virtual void SetUp() OVERRIDE {
-    prefs_.reset(new TestingPrefServiceSimple);
+    prefs_.reset(new TestingPrefServiceSimple());
     chrome::RegisterLocalState(prefs_->registry());
 
     browser_process()->SetLocalState(prefs_.get());
-
+    testing_io_thread_state_.reset(new chrome::TestingIOThreadState());
+    testing_io_thread_state_->io_thread_state()->globals()->host_resolver.reset(
+        new net::MockHostResolver());
     BrowserWithTestWindowTest::SetUp();
   }
 
   virtual void TearDown() OVERRIDE {
     BrowserWithTestWindowTest::TearDown();
+    testing_io_thread_state_.reset();
     browser_process()->SetLocalState(NULL);
     DestroyBrowserAndProfile();
-    prefs_.reset();
   }
 
  private:
@@ -106,6 +111,7 @@
   }
 
   scoped_ptr<TestingPrefServiceSimple> prefs_;
+  scoped_ptr<chrome::TestingIOThreadState> testing_io_thread_state_;
 
   DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImplTest);
 };
@@ -178,4 +184,5 @@
   EXPECT_EQ(parent_zoom_map->GetZoomLevelForHostAndScheme("http", host),
             child_zoom_map->GetZoomLevelForHostAndScheme("http", host)) <<
                 "Parent change should propagate to child.";
+  base::RunLoop().RunUntilIdle();
 }
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 6d128a7..0386d22 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -186,6 +186,7 @@
   // for README creation).
   profile.reset();
   content::RunAllPendingInMessageLoop();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
   content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
 }
 
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 57ffb8f..731f032 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -867,7 +867,7 @@
       int render_view_id,
       const GURL& requesting_frame,
       const MIDISysExPermissionCallback& callback) {
-  // TODO(toyoshim): Implement.
+  // TODO(toyoshim): Implement. http://crbug.com/257618 .
   callback.Run(false);
 }
 
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index 57ad936..ca66dba 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -34,7 +34,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -95,10 +95,7 @@
   };
 
   ProfileManagerTest()
-      : local_state_(TestingBrowserProcess::GetGlobal()),
-        ui_thread_(BrowserThread::UI, &message_loop_),
-        db_thread_(BrowserThread::DB, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_) {
+      : local_state_(TestingBrowserProcess::GetGlobal()) {
   }
 
   virtual void SetUp() {
@@ -115,7 +112,7 @@
 
   virtual void TearDown() {
     TestingBrowserProcess::GetGlobal()->SetProfileManager(NULL);
-    message_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   // Helper function to create a profile with |name| for a profile |manager|.
@@ -139,10 +136,8 @@
   // The path to temporary directory used to contain the test operations.
   base::ScopedTempDir temp_dir_;
   ScopedTestingLocalState local_state_;
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread file_thread_;
+
+  content::TestBrowserThreadBundle thread_bundle_;
 
 #if defined(OS_CHROMEOS)
   chromeos::ScopedTestUserManager test_user_manager_;
@@ -232,12 +227,12 @@
                                                    Profile::EXPLICIT_ACCESS));
 
   // Make sure any pending tasks run before we destroy the profiles.
-  message_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
 
   TestingBrowserProcess::GetGlobal()->SetProfileManager(NULL);
 
   // Make sure history cleans up correctly.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 MATCHER(NotFail, "Profile creation failure status is not reported.") {
@@ -255,7 +250,7 @@
   CreateProfileAsync(g_browser_process->profile_manager(),
                      "New Profile", &mock_observer);
 
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 MATCHER(SameNotNull, "The same non-NULL value for all calls.") {
@@ -283,7 +278,7 @@
   CreateProfileAsync(profile_manager, profile_name, &mock_observer2);
   CreateProfileAsync(profile_manager, profile_name, &mock_observer3);
 
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(ProfileManagerTest, CreateProfilesAsync) {
@@ -299,7 +294,7 @@
   CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
   CreateProfileAsync(profile_manager, profile_name2, &mock_observer);
 
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(ProfileManagerTest, GetGuestProfilePath) {
@@ -645,7 +640,7 @@
 
   CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
   CreateProfileAsync(profile_manager, profile_name2, &mock_observer);
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size());
   EXPECT_EQ(2u, profile_manager->GetProfileInfoCache().GetNumberOfProfiles());
@@ -658,7 +653,7 @@
   profile_manager->ScheduleProfileForDeletion(dest_path1,
                                               ProfileManager::CreateCallback());
   // Spin the message loop so that all the callbacks can finish running.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(dest_path2, profile_manager->GetLastUsedProfile()->GetPath());
   EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed));
@@ -684,13 +679,13 @@
   EXPECT_CALL(mock_observer, OnProfileCreated(
       testing::NotNull(), NotFail())).Times(testing::AtLeast(2));
   CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Track the profile, but don't load it.
   ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
   cache.AddProfileToCache(dest_path2, ASCIIToUTF16(profile_name2),
                           string16(), 0, false);
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size());
   EXPECT_EQ(2u, cache.GetNumberOfProfiles());
@@ -706,7 +701,7 @@
                                               ProfileManager::CreateCallback());
 
   // Spin the message loop so that all the callbacks can finish running.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(dest_path2, profile_manager->GetLastUsedProfile()->GetPath());
   EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed));
@@ -735,7 +730,7 @@
   EXPECT_CALL(mock_observer, OnProfileCreated(
       testing::NotNull(), NotFail())).Times(testing::AtLeast(2));
   CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Create the other profiles, but don't load them. Assign a fake avatar icon
   // to ensure that profiles in the info cache are sorted by the profile name,
@@ -746,7 +741,7 @@
   cache.AddProfileToCache(dest_path3, ASCIIToUTF16(profile_name3),
                           ASCIIToUTF16(profile_name3), 2, false);
 
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size());
   EXPECT_EQ(3u, cache.GetNumberOfProfiles());
@@ -770,7 +765,7 @@
   profile_manager->ScheduleProfileForDeletion(dest_path2,
                                               ProfileManager::CreateCallback());
   // Spin the message loop so that all the callbacks can finish running.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(dest_path3, profile_manager->GetLastUsedProfile()->GetPath());
   EXPECT_EQ(profile_name3, local_state->GetString(prefs::kProfileLastUsed));
diff --git a/chrome/browser/resources/chromeos/echo/manifest.json b/chrome/browser/resources/chromeos/echo/manifest.json
index 1cd7fbc..1f69e5a 100644
--- a/chrome/browser/resources/chromeos/echo/manifest.json
+++ b/chrome/browser/resources/chromeos/echo/manifest.json
@@ -20,7 +20,8 @@
   "default_locale": "en",
   "web_accessible_resources": [
     "broker.html",
-    "broker.js"
+    "broker.js",
+    "error.html"
   ],
   "background": {
     "scripts": ["main.js"],
diff --git a/chrome/browser/resources/downloads/downloads.css b/chrome/browser/resources/downloads/downloads.css
index 5cc5578..b032792 100644
--- a/chrome/browser/resources/downloads/downloads.css
+++ b/chrome/browser/resources/downloads/downloads.css
@@ -60,6 +60,10 @@
   -webkit-margin-start: 0;
 }
 
+#open-downloads-folder {
+  -webkit-margin-end: 16px;
+}
+
 #downloads-display {
   max-width: 740px;
 }
diff --git a/chrome/browser/resources/downloads/downloads.js b/chrome/browser/resources/downloads/downloads.js
index 6d5f311..dd9b457 100644
--- a/chrome/browser/resources/downloads/downloads.js
+++ b/chrome/browser/resources/downloads/downloads.js
@@ -386,7 +386,8 @@
   DANGEROUS_URL: 'DANGEROUS_URL',
   DANGEROUS_CONTENT: 'DANGEROUS_CONTENT',
   UNCOMMON_CONTENT: 'UNCOMMON_CONTENT',
-  DANGEROUS_HOST: 'DANGEROUS_HOST'
+  DANGEROUS_HOST: 'DANGEROUS_HOST',
+  POTENTIALLY_UNWANTED: 'POTENTIALLY_UNWANTED',
 };
 
 /**
@@ -442,6 +443,9 @@
     } else if (this.dangerType_ == Download.DangerType.UNCOMMON_CONTENT) {
       this.dangerDesc_.textContent = loadTimeData.getStringF(
           'danger_uncommon_desc', this.fileName_);
+    } else if (this.dangerType_ == Download.DangerType.POTENTIALLY_UNWANTED) {
+      this.dangerDesc_.textContent = loadTimeData.getStringF(
+          'danger_potentially_unwanted_desc', this.fileName_);
     }
     this.danger_.style.display = 'block';
     this.safe_.style.display = 'none';
diff --git a/chrome/browser/resources/extensions/extension_focus_manager.js b/chrome/browser/resources/extensions/extension_focus_manager.js
index e578eba..b220024 100644
--- a/chrome/browser/resources/extensions/extension_focus_manager.js
+++ b/chrome/browser/resources/extensions/extension_focus_manager.js
@@ -6,6 +6,7 @@
   var FocusManager = cr.ui.FocusManager;
 
   function ExtensionFocusManager() {
+    FocusManager.disableMouseFocusOnButtons();
   }
 
   cr.addSingletonGetter(ExtensionFocusManager);
diff --git a/chrome/browser/resources/file_manager/js/butter_bar.js b/chrome/browser/resources/file_manager/js/butter_bar.js
index 69d8187..a280aee 100644
--- a/chrome/browser/resources/file_manager/js/butter_bar.js
+++ b/chrome/browser/resources/file_manager/js/butter_bar.js
@@ -237,10 +237,13 @@
 
 /**
  * Set up butter bar for showing copy progress.
+ *
+ * @param {Object} progress Copy status object created by
+ *     FileCopyManager.getStatus().
  * @private
  */
-ButterBar.prototype.showProgress_ = function() {
-  this.progress_ = this.copyManager_.getStatus();
+ButterBar.prototype.showProgress_ = function(progress) {
+  this.progress_ = progress;
   var options = {
     progress: this.progress_.percentage,
     actions: {},
@@ -278,12 +281,12 @@
     case 'BEGIN':
       this.showTimeout_ = setTimeout(function() {
         this.showTimeout_ = null;
-        this.showProgress_();
+        this.showProgress_(event.status);
       }.bind(this), 500);
       break;
 
     case 'PROGRESS':
-      this.showProgress_();
+      this.showProgress_(event.status);
       break;
 
     case 'SUCCESS':
@@ -296,7 +299,7 @@
       break;
 
     case 'ERROR':
-      this.progress_ = this.copyManager_.getStatus();
+      this.progress_ = event.status;
       if (event.error.reason === 'TARGET_EXISTS') {
         var name = event.error.data.name;
         if (event.error.data.isDirectory)
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 5e55a13..fccce39 100644
--- a/chrome/browser/resources/file_manager/js/file_copy_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_copy_manager.js
@@ -14,26 +14,24 @@
   this.cancelRequested_ = false;
   this.cancelCallback_ = null;
   this.unloadTimeout_ = null;
+  this.listeners_ = [];
 
   window.addEventListener('error', function(e) {
     this.log_('Unhandled error: ', e.message, e.filename + ':' + e.lineno);
   }.bind(this));
 }
 
-var fileCopyManagerInstance = null;
-
 /**
  * Get FileCopyManager instance. In case is hasn't been initialized, a new
  * instance is created.
  *
- * @param {DirectoryEntry} root Root entry.
  * @return {FileCopyManager} A FileCopyManager instance.
  */
-FileCopyManager.getInstance = function(root) {
-  if (fileCopyManagerInstance === null) {
-    fileCopyManagerInstance = new FileCopyManager(root);
-  }
-  return fileCopyManagerInstance;
+FileCopyManager.getInstance = function() {
+  if (!FileCopyManager.instance_)
+    FileCopyManager.instance_ = new FileCopyManager();
+
+  return FileCopyManager.instance_;
 };
 
 /**
@@ -347,16 +345,31 @@
     return;  // Swallow events until cancellation complete.
 
   eventArgs.status = this.getStatus();
-
-  var windows = getContentWindows();
-  for (var i = 0; i < windows.length; i++) {
-    var w = windows[i];
-    if (w.FileCopyManagerWrapper)
-      w.FileCopyManagerWrapper.getInstance().onEvent(eventName, eventArgs);
+  for (var i = 0; i < this.listeners_.length; ++i) {
+    this.listeners_[i](eventName, eventArgs);
   }
 };
 
 /**
+ * Adds a listener for running task events.
+ * @param {function(string, Object)} listener A listener to be added.
+ */
+FileCopyManager.prototype.addListener = function(listener) {
+  this.listeners_.push(listener);
+};
+
+/**
+ * Removes the listener for running task events. If the listener is not added
+ * by addListener(), it is simply ignored.
+ * @param {function(string, Object)} listener A listener to be removed.
+ */
+FileCopyManager.prototype.removeListener = function(listener) {
+  var index = this.listeners_.indexOf(listener);
+  if (index >= 0)
+    this.listeners_.splice(index, 1);
+};
+
+/**
  * Says if there are any tasks in the queue.
  * @return {boolean} True, if there are any tasks.
  */
@@ -633,9 +646,14 @@
     self.resetQueue_();
   };
 
-  var onTaskSuccess = function(task) {
+  var onTaskSuccess = function() {
     if (self.maybeCancel_())
       return;
+
+    // The task at the front of the queue is completed. Pop it from the queue.
+    self.copyTasks_.shift();
+    self.maybeScheduleCloseBackgroundPage_();
+
     if (!self.copyTasks_.length) {
       // All tasks have been serviced, clean up and exit.
       self.sendProgressEvent_('SUCCESS');
@@ -649,38 +667,55 @@
     // these continuous tasks.
     self.sendProgressEvent_('PROGRESS');
 
-    self.serviceNextTask_(onTaskSuccess, onTaskError);
+    self.serviceTask_(self.copyTasks_[0], onTaskSuccess, onTaskError);
   };
 
   // If the queue size is 1 after pushing our task, it was empty before,
   // so we need to kick off queue processing and dispatch BEGIN event.
 
   this.sendProgressEvent_('BEGIN');
-  this.serviceNextTask_(onTaskSuccess, onTaskError);
+  this.serviceTask_(this.copyTasks_[0], onTaskSuccess, onTaskError);
 };
 
 /**
- * Service all entries in the next copy task.
+ * Runs a given task.
+ * Note that the responsibility of this method is just dispatching to the
+ * appropriate serviceXxxTask_() method.
+ * TODO(hidehiko): Remove this method by introducing FileCopyManager.Task.run()
+ *     (crbug.com/246976).
  *
- * @param {function} successCallback On success.
- * @param {function} errorCallback On error.
+ * @param {FileCopyManager.Task} task A task to be run.
+ * @param {function()} successCallback Callback run on success.
+ * @param {function(FileCopyManager.Error)} errorCallback Callback run on error.
  * @private
  */
-FileCopyManager.prototype.serviceNextTask_ = function(
-    successCallback, errorCallback) {
+FileCopyManager.prototype.serviceTask_ = function(
+    task, successCallback, errorCallback) {
+  if (task.zip)
+    this.serviceZipTask_(task, successCallback, errorCallback);
+  else
+    this.serviceCopyTask_(task, successCallback, errorCallback);
+};
+
+/**
+ * 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.
+ * @param {function(FileCopyManager.Error)} errorCallback On error.
+ * @private
+ */
+FileCopyManager.prototype.serviceCopyTask_ = function(
+    task, successCallback, errorCallback) {
   var self = this;
-  var task = this.copyTasks_[0];
 
   var onFilesystemError = function(err) {
     errorCallback(new FileCopyManager.Error('FILESYSTEM_ERROR', err));
   };
 
-  var onTaskComplete = function() {
-    self.copyTasks_.shift();
-    self.maybeScheduleCloseBackgroundPage_();
-    successCallback(task);
-  };
-
   var deleteOriginals = function() {
     var count = task.originalEntries.length;
 
@@ -688,7 +723,7 @@
       self.sendOperationEvent_('deleted', [entry]);
       count--;
       if (!count)
-        onTaskComplete();
+        successCallback();
     };
 
     for (var i = 0; i < task.originalEntries.length; i++) {
@@ -698,14 +733,14 @@
     }
   };
 
-  var onEntryServiced = function(targetEntry, size) {
+  var onEntryServiced = function() {
     // We should not dispatch a PROGRESS event when there is no pending items
     // in the task.
     if (task.pendingDirectories.length + task.pendingFiles.length == 0) {
       if (task.deleteAfterCopy) {
         deleteOriginals();
       } else {
-        onTaskComplete();
+        successCallback();
       }
       return;
     }
@@ -715,14 +750,11 @@
     // We yield a few ms between copies to give the browser a chance to service
     // events (like perhaps the user clicking to cancel the copy, for example).
     setTimeout(function() {
-      self.serviceNextTaskEntry_(task, onEntryServiced, errorCallback);
+      self.serviceNextCopyTaskEntry_(task, onEntryServiced, errorCallback);
     }, 10);
   };
 
-  if (!task.zip)
-    this.serviceNextTaskEntry_(task, onEntryServiced, errorCallback);
-  else
-    this.serviceZipTask_(task, onTaskComplete, errorCallback);
+  this.serviceNextCopyTaskEntry_(task, onEntryServiced, errorCallback);
 };
 
 /**
@@ -730,11 +762,11 @@
  * TODO(olege): Refactor this method into a separate class.
  *
  * @param {FileManager.Task} task A task.
- * @param {function} successCallback On success.
- * @param {function} errorCallback On error.
+ * @param {function()} successCallback On success.
+ * @param {function(FileCopyManager.Error)} errorCallback On error.
  * @private
  */
-FileCopyManager.prototype.serviceNextTaskEntry_ = function(
+FileCopyManager.prototype.serviceNextCopyTaskEntry_ = function(
     task, successCallback, errorCallback) {
   if (this.maybeCancel_())
     return;
@@ -744,10 +776,15 @@
 
   if (!sourceEntry) {
     // All entries in this task have been copied.
-    successCallback(null);
+    successCallback();
     return;
   }
 
+  var onError = function(reason, data) {
+    self.log_('serviceNextCopyTaskEntry 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) {
@@ -763,7 +800,7 @@
 
   var onCopyCompleteBase = function(entry, size) {
     task.markEntryComplete(entry, size);
-    successCallback(entry, size);
+    successCallback();
   };
 
   var onCopyComplete = function(entry, size) {
@@ -776,11 +813,6 @@
     self.sendProgressEvent_('PROGRESS');
   };
 
-  var onError = function(reason, data) {
-    self.log_('serviceNextTaskEntry error: ' + reason + ':', data);
-    errorCallback(new FileCopyManager.Error(reason, data));
-  };
-
   var onFilesystemCopyComplete = function(sourceEntry, targetEntry) {
     // TODO(benchan): We currently do not know the size of data being
     // copied by FileEntry.copyTo(), so task.completedBytes will not be
@@ -1006,13 +1038,13 @@
 /**
  * Service a zip file creation task.
  *
- * @param {FileManager.Task} task A task.
- * @param {function} completeCallback On complete.
- * @param {function} errorCallback On error.
+ * @param {FileCopyManager.Task} task A zip task to be run.
+ * @param {function()} successCallback On complete.
+ * @param {function(FileCopyManager.Error)} errorCallback On error.
  * @private
  */
-FileCopyManager.prototype.serviceZipTask_ = function(task, completeCallback,
-                                                     errorCallback) {
+FileCopyManager.prototype.serviceZipTask_ = function(
+    task, successCallback, errorCallback) {
   var self = this;
   var dirURL = task.zipBaseDirEntry.toURL();
   var selectionURLs = [];
@@ -1043,7 +1075,7 @@
         self.sendProgressEvent_('ERROR',
             new FileCopyManager.Error('FILESYSTEM_ERROR', ''));
       }
-      completeCallback(task);
+      successCallback();
     };
 
     self.sendProgressEvent_('PROGRESS');
diff --git a/chrome/browser/resources/file_manager/js/file_copy_manager_wrapper.js b/chrome/browser/resources/file_manager/js/file_copy_manager_wrapper.js
index f955ff4..6f902b9 100644
--- a/chrome/browser/resources/file_manager/js/file_copy_manager_wrapper.js
+++ b/chrome/browser/resources/file_manager/js/file_copy_manager_wrapper.js
@@ -10,27 +10,18 @@
  * @constructor
  */
 function FileCopyManagerWrapper() {
-  this.status_ = {
-    pendingItems: 0,
-    pendingFiles: 0,
-    pendingDirectories: 0,
-    pendingBytes: 0,
+  this.running_ = false;
 
-    completedItems: 0,
-    completedFiles: 0,
-    completedDirectories: 0,
-    completedBytes: 0,
+  var onEventBound = this.onEvent_.bind(this);
+  chrome.runtime.getBackgroundPage(function(backgroundPage) {
+    var fileCopyManager = backgroundPage.FileCopyManager.getInstance();
+    fileCopyManager.addListener(onEventBound);
 
-    totalItems: 0,
-    totalFiles: 0,
-    totalDirectories: 0,
-    totalBytes: 0,
-
-    percentage: NaN,
-    pendingCopies: 0,
-    pendingMoves: 0,
-    filename: ''  // In case pendingItems == 1
-  };
+    // Register removing the listener when the window is closed.
+    chrome.app.window.current().onClosed.addListener(function() {
+      fileCopyManager.removeListener(onEventBound);
+    });
+  });
 }
 
 /**
@@ -50,24 +41,13 @@
 };
 
 /**
- * Load background page and call callback with copy manager as an argument.
- * @param {function} callback Function with FileCopyManager as a parameter.
- * @private
- */
-FileCopyManagerWrapper.prototype.getCopyManagerAsync_ = function(callback) {
-  chrome.runtime.getBackgroundPage(function(backgroundPage) {
-    var fileCopyManager = backgroundPage.FileCopyManager.getInstance();
-    fileCopyManager.initialize(callback.bind(this, fileCopyManager));
-  });
-};
-
-/**
  * Called be FileCopyManager to raise an event in this instance of FileManager.
  * @param {string} eventName Event name.
  * @param {Object} eventArgs Arbitratry field written to event object.
+ * @private
  */
-FileCopyManagerWrapper.prototype.onEvent = function(eventName, eventArgs) {
-  this.status_ = eventArgs.status;
+FileCopyManagerWrapper.prototype.onEvent_ = function(eventName, eventArgs) {
+  this.running_ = eventArgs.status.totalFiles > 0;
 
   var event = new cr.Event(eventName);
   for (var arg in eventArgs)
@@ -78,10 +58,22 @@
 };
 
 /**
- * @return {Object} Status object.
+ * @return {boolean} True if there is a running task.
  */
-FileCopyManagerWrapper.prototype.getStatus = function() {
-  return this.status_;
+FileCopyManagerWrapper.prototype.isRunning = function() {
+  return this.running_;
+};
+
+/**
+ * Load background page and call callback with copy manager as an argument.
+ * @param {function} callback Function with FileCopyManager as a parameter.
+ * @private
+ */
+FileCopyManagerWrapper.prototype.getCopyManagerAsync_ = function(callback) {
+  chrome.runtime.getBackgroundPage(function(backgroundPage) {
+    var fileCopyManager = backgroundPage.FileCopyManager.getInstance();
+    fileCopyManager.initialize(callback.bind(this, fileCopyManager));
+  });
 };
 
 /**
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 823d2a7..029af9c 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -2956,8 +2956,7 @@
         return;
 
       case '27':  // Escape => Cancel dialog.
-        if (this.copyManager_ &&
-            this.copyManager_.getStatus().totalFiles != 0) {
+        if (this.copyManager_ && this.copyManager_.isRunning()) {
           // If there is a copy in progress, ESC will cancel it.
           event.preventDefault();
           this.copyManager_.requestCancel();
diff --git a/chrome/browser/resources/history/history.js b/chrome/browser/resources/history/history.js
index d5a8ef8..b6eb19a 100644
--- a/chrome/browser/resources/history/history.js
+++ b/chrome/browser/resources/history/history.js
@@ -1772,6 +1772,9 @@
  * @param {!MouseEvent} event A click event.
  */
 function entryBoxClick(event) {
+  // Do nothing if a bookmark star is clicked.
+  if (event.defaultPrevented)
+    return;
   var tagName = event.target.tagName;
   if (tagName == 'BUTTON' || tagName == 'INPUT' || tagName == 'A')
     return;
diff --git a/chrome/browser/resources/inspect/inspect.html b/chrome/browser/resources/inspect/inspect.html
index 389a7a3..f9e9d33 100644
--- a/chrome/browser/resources/inspect/inspect.html
+++ b/chrome/browser/resources/inspect/inspect.html
@@ -33,6 +33,10 @@
       <div class="content-header">Extensions</div>
       <div id="extensions" class="list"></div>
     </div>
+    <div id="apps-tab">
+      <div class="content-header">Apps</div>
+      <div id="apps" class="list"></div>
+    </div>
     <div id="workers-tab">
       <div class="content-header">Shared workers</div>
       <div id="workers" class="list"></div>
diff --git a/chrome/browser/resources/inspect/inspect.js b/chrome/browser/resources/inspect/inspect.js
index 819272b..6920b3f 100644
--- a/chrome/browser/resources/inspect/inspect.js
+++ b/chrome/browser/resources/inspect/inspect.js
@@ -63,6 +63,7 @@
 
   removeChildren('pages');
   removeChildren('extensions');
+  removeChildren('apps');
   removeChildren('workers');
   removeChildren('others');
 
@@ -73,6 +74,8 @@
       addToWorkersList(data[i]);
     else if (data[i].type === 'extension')
       addToExtensionsList(data[i]);
+    else if (data[i].type === 'app')
+      addToAppsList(data[i]);
     else
       addToOthersList(data[i]);
   }
@@ -135,6 +138,10 @@
   addTargetToList(data, 'extensions', ['name', 'url']);
 }
 
+function addToAppsList(data) {
+  addTargetToList(data, 'apps', ['name', 'url']);
+}
+
 function addToWorkersList(data) {
   addTargetToList(data,
                   'workers',
diff --git a/chrome/browser/resources/local_ntp/most_visited_util.js b/chrome/browser/resources/local_ntp/most_visited_util.js
index 088ea6d..5352128 100644
--- a/chrome/browser/resources/local_ntp/most_visited_util.js
+++ b/chrome/browser/resources/local_ntp/most_visited_util.js
@@ -107,13 +107,23 @@
 function fillMostVisited(location, fill) {
   var params = parseQueryParams(document.location);
   params.rid = parseInt(params.rid, 10);
-  if (!isFinite(params.rid))
+  if (!isFinite(params.rid) && !params.url)
     return;
-  var apiHandle = chrome.embeddedSearch.searchBox;
-  var data = apiHandle.getMostVisitedItemData(params.rid);
-  if (!data)
-    return;
-  if (/^javascript:/i.test(data.url))
+  var data = {};
+  if (params.url) {
+    // Means that we get suggestion data from the server. Create data object.
+    data.url = params.url;
+    data.thumbnailUrl = params.tu || '';
+    data.title = params.ti || '';
+    data.direction = params.di || '';
+  } else {
+    var apiHandle = chrome.embeddedSearch.searchBox;
+    data = apiHandle.getMostVisitedItemData(params.rid);
+    if (!data)
+      return;
+  }
+  if (/^javascript:/i.test(data.url) ||
+      /^javascript:/i.test(data.thumbnailUrl))
     return;
   if (data.direction)
     document.body.dir = data.direction;
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index ef02f53..97dacf6 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -642,6 +642,22 @@
           </span>
         </div>
       </div>
+      <div id="accessibility-sticky-keys" class="option-name" hidden>
+        <div class="checkbox">
+          <span class="controlled-setting-with-label">
+            <input id="accessibility-sticky-keys-check"
+                pref="settings.a11y.sticky_keys_enabled" type="checkbox">
+            <span>
+              <label for="accessibility-sticky-keys-check"
+                  i18n-content="accessibilityStickyKeys">
+              </label>
+              <span class="controlled-setting-indicator"
+                  pref="settings.a11y.sticky_keys_enabled">
+              </span>
+            </span>
+          </span>
+        </div>
+      </div>
       <div class="option-name">
         <div class="checkbox">
           <span class="controlled-setting-with-label">
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index f221e88..f14ae61 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -430,6 +430,8 @@
           chrome.send('highContrastChange',
                       [$('accessibility-high-contrast-check').checked]);
         };
+        $('accessibility-sticky-keys').hidden =
+            !loadTimeData.getBoolean('enableStickyKeys');
       }
 
       // Display management section (CrOS only).
diff --git a/chrome/browser/resources/options/managed_user_create_confirm.css b/chrome/browser/resources/options/managed_user_create_confirm.css
index 718d346..37b3770 100644
--- a/chrome/browser/resources/options/managed_user_create_confirm.css
+++ b/chrome/browser/resources/options/managed_user_create_confirm.css
@@ -6,6 +6,10 @@
   width: 722px;
 }
 
+#managed-user-created-title {
+  word-wrap: break-word;
+}
+
 #managed-user-created-image {
   background-image: -webkit-image-set(
       url('../../../../ui/resources/default_100_percent/supervised_illustration_done.png') 1x,
@@ -18,3 +22,8 @@
   white-space: pre-wrap;
   word-wrap: break-word;
 }
+
+#managed-user-created-switch {
+  max-width: 600px;
+  word-wrap: break-word;
+}
diff --git a/chrome/browser/resources/options/managed_user_create_confirm.js b/chrome/browser/resources/options/managed_user_create_confirm.js
index d1538ac..64922b7 100644
--- a/chrome/browser/resources/options/managed_user_create_confirm.js
+++ b/chrome/browser/resources/options/managed_user_create_confirm.js
@@ -67,19 +67,27 @@
                        .replace(/'/g, '&#39;');
       }
 
+      var MAX_LENGTH = 50;
+      function elide(original) {
+        if (original.length <= MAX_LENGTH)
+          return original;
+        return original.substring(0, MAX_LENGTH - 3) + '...';
+      }
+
       this.profileInfo_ = info;
+      var elidedName = elide(info.name);
       $('managed-user-created-title').textContent =
-          loadTimeData.getStringF('managedUserCreatedTitle', info.name);
+          loadTimeData.getStringF('managedUserCreatedTitle', elidedName);
       $('managed-user-created-switch').textContent =
-          loadTimeData.getStringF('managedUserCreatedSwitch', info.name);
+          loadTimeData.getStringF('managedUserCreatedSwitch', elidedName);
 
       // HTML-escape the user-supplied strings before putting them into
       // innerHTML. This is probably excessive for the email address, but
       // belt-and-suspenders is cheap here.
       $('managed-user-created-text').innerHTML =
           loadTimeData.getStringF('managedUserCreatedText',
-                                  HTMLEscape(info.name),
-                                  HTMLEscape(info.custodianEmail));
+                                  HTMLEscape(elidedName),
+                                  HTMLEscape(elide(info.custodianEmail)));
     },
 
     /** @override */
diff --git a/chrome/browser/resources/sync_setup_overlay.html b/chrome/browser/resources/sync_setup_overlay.html
index 246ff77..7a37299 100644
--- a/chrome/browser/resources/sync_setup_overlay.html
+++ b/chrome/browser/resources/sync_setup_overlay.html
@@ -34,11 +34,10 @@
             <select id="sync-select-datatypes">
               <option i18n-content="syncAllDataTypes" selected></option>
               <option i18n-content="chooseDataTypes"></option>
-              <!-- The syncNothing element is to be hidden for M29.
+              <!-- The syncNothing element is to be removed for M29.
                    TODO(rsimha): Revisit this for M30.
                    See http://crbug.com/252049.
               -->
-              <option i18n-content="syncNothing" hidden></option>
             </select>
             <div id="choose-data-types-body">
               <div id="apps-item" class="sync-type-checkbox checkbox">
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index 2c5f590..62c12fa 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -417,6 +417,10 @@
       } else if (response.verdict() == ClientDownloadResponse::DANGEROUS_HOST) {
         reason = REASON_DOWNLOAD_DANGEROUS_HOST;
         result = DANGEROUS_HOST;
+      } else if (
+          response.verdict() == ClientDownloadResponse::POTENTIALLY_UNWANTED) {
+        reason = REASON_DOWNLOAD_POTENTIALLY_UNWANTED;
+        result = POTENTIALLY_UNWANTED;
       } else {
         LOG(DFATAL) << "Unknown download response verdict: "
                     << response.verdict();
@@ -864,8 +868,12 @@
 void DownloadProtectionService::ShowDetailsForDownload(
     const content::DownloadItem& item,
     content::PageNavigator* navigator) {
+  GURL learn_more_url(chrome::kDownloadScanningLearnMoreURL);
+  if (item.GetDangerType() ==
+      content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED)
+    learn_more_url = GURL(chrome::kDownloadPotentiallyUnwantedLearnMoreURL);
   navigator->OpenURL(
-      content::OpenURLParams(GURL(chrome::kDownloadScanningLearnMoreURL),
+      content::OpenURLParams(learn_more_url,
                              content::Referrer(),
                              NEW_FOREGROUND_TAB,
                              content::PAGE_TRANSITION_LINK,
diff --git a/chrome/browser/safe_browsing/download_protection_service.h b/chrome/browser/safe_browsing/download_protection_service.h
index 48ab04a..0b61b6d 100644
--- a/chrome/browser/safe_browsing/download_protection_service.h
+++ b/chrome/browser/safe_browsing/download_protection_service.h
@@ -45,6 +45,7 @@
     DANGEROUS,
     UNCOMMON,
     DANGEROUS_HOST,
+    POTENTIALLY_UNWANTED
   };
 
   // Callback type which is invoked once the download request is done.
@@ -130,6 +131,7 @@
     REASON_INVALID_RESPONSE_VERDICT,
     REASON_ARCHIVE_WITHOUT_BINARIES,
     REASON_DOWNLOAD_DANGEROUS_HOST,
+    REASON_DOWNLOAD_POTENTIALLY_UNWANTED,
     REASON_MAX  // Always add new values before this one.
   };
 
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
index 6d5bfee..91cf222 100644
--- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -455,8 +455,8 @@
   std::string hash = "hash";
 
   content::MockDownloadItem item;
-  EXPECT_CALL(item, AddObserver(_)).Times(5);
-  EXPECT_CALL(item, RemoveObserver(_)).Times(5);
+  EXPECT_CALL(item, AddObserver(_)).Times(6);
+  EXPECT_CALL(item, RemoveObserver(_)).Times(6);
   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
@@ -469,7 +469,7 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(a_tmp, _)).Times(5);
+  EXPECT_CALL(*signature_util_.get(), CheckSignature(a_tmp, _)).Times(6);
 
   download_service_->CheckClientDownload(
       &item,
@@ -561,6 +561,25 @@
 #else
   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
 #endif
+
+  // If the response is POTENTIALLY_UNWANTED the result should also be marked as
+  // POTENTIALLY_UNWANTED.
+  response.set_verdict(ClientDownloadResponse::POTENTIALLY_UNWANTED);
+  factory.SetFakeResponse(
+      DownloadProtectionService::GetDownloadRequestUrl(),
+      response.SerializeAsString(),
+      true);
+
+  download_service_->CheckClientDownload(
+      &item,
+      base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
+                 base::Unretained(this)));
+  MessageLoop::current()->Run();
+#if defined(OS_WIN)
+  EXPECT_TRUE(IsResult(DownloadProtectionService::POTENTIALLY_UNWANTED));
+#else
+  EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
+#endif
 }
 
 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadHTTPS) {
diff --git a/chrome/browser/safe_browsing/malware_details_unittest.cc b/chrome/browser/safe_browsing/malware_details_unittest.cc
index 37ada0c..3e8ee59 100644
--- a/chrome/browser/safe_browsing/malware_details_unittest.cc
+++ b/chrome/browser/safe_browsing/malware_details_unittest.cc
@@ -531,7 +531,6 @@
   UnsafeResource resource;
   InitResource(&resource, true, GURL(kMalwareURL));
 
-  profile()->CreateRequestContext();
   scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
       ui_manager_.get(), web_contents(), resource,
       profile()->GetRequestContext());
@@ -594,7 +593,6 @@
   expected.set_complete(true);
 
   VerifyResults(actual, expected);
-  profile()->ResetRequestContext();
 }
 
 // Tests the interaction with the HTTP cache (where the cache is empty).
@@ -605,7 +603,6 @@
   UnsafeResource resource;
   InitResource(&resource, true, GURL(kMalwareURL));
 
-  profile()->CreateRequestContext();
   scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
       ui_manager_.get(), web_contents(), resource,
       profile()->GetRequestContext());
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index 720836f..7ad5e86 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -482,8 +482,8 @@
   if (navigation_entry_index_to_remove_ != -1 &&
       navigation_entry_index_to_remove_ != last_committed_index &&
       !web_contents_->IsBeingDestroyed()) {
-    web_contents_->GetController().RemoveEntryAtIndex(
-        navigation_entry_index_to_remove_);
+    CHECK(web_contents_->GetController().RemoveEntryAtIndex(
+        navigation_entry_index_to_remove_));
     navigation_entry_index_to_remove_ = -1;
   }
 }
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
index 483a464..ec50a66 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "crypto/sha2.h"
 #include "sql/connection.h"
 #include "sql/statement.h"
@@ -21,7 +21,6 @@
 #include "url/gurl.h"
 
 using base::Time;
-using content::BrowserThread;
 
 namespace {
 
@@ -1252,10 +1251,9 @@
 // Checks that the whitelists are handled properly.
 TEST_F(SafeBrowsingDatabaseTest, Whitelists) {
   database_.reset();
-  base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
   // We expect all calls to ContainsCsdWhitelistedUrl in particular to be made
   // from the IO thread.  In general the whitelist lookups are thread-safe.
-  content::TestBrowserThread io_thread(BrowserThread::IO, &loop);
+  content::TestBrowserThreadBundle thread_bundle_;
 
   // If the whitelist is disabled everything should match the whitelist.
   database_.reset(new SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile(),
diff --git a/chrome/browser/safe_browsing/two_phase_testserver.py b/chrome/browser/safe_browsing/two_phase_testserver.py
index c054047..b385e15 100755
--- a/chrome/browser/safe_browsing/two_phase_testserver.py
+++ b/chrome/browser/safe_browsing/two_phase_testserver.py
@@ -99,12 +99,6 @@
 
     return server
 
-  def add_options(self):
-    testserver_base.TestServerRunner.add_options(self)
-    self.option_parser.add_option('--data-file', dest='data_file',
-                                  help='File containing safebrowsing test '
-                                  'data and expectations')
-
 
 if __name__ == '__main__':
   sys.exit(ServerRunner().main())
diff --git a/chrome/browser/search/iframe_source_unittest.cc b/chrome/browser/search/iframe_source_unittest.cc
index 0dfee16..38cbba9 100644
--- a/chrome/browser/search/iframe_source_unittest.cc
+++ b/chrome/browser/search/iframe_source_unittest.cc
@@ -12,10 +12,11 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/test/mock_resource_context.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "grit/browser_resources.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -73,11 +74,10 @@
   // else happen on the IO thread. This setup is a hacky way to satisfy all
   // those constraints.
   IframeSourceTest()
-    : message_loop_(base::MessageLoop::TYPE_IO),
-      ui_thread_(content::BrowserThread::UI, &message_loop_),
-      io_thread_(content::BrowserThread::IO, &message_loop_),
-      instant_io_context_(NULL),
-      response_(NULL) {
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+        resource_context_(&test_url_request_context_),
+        instant_io_context_(NULL),
+        response_(NULL) {
   }
 
   TestIframeSource* source() { return source_.get(); }
@@ -121,7 +121,7 @@
   }
 
  private:
-  virtual void SetUp() {
+  virtual void SetUp() OVERRIDE {
     source_.reset(new TestIframeSource());
     callback_ = base::Bind(&IframeSourceTest::SaveResponse,
                            base::Unretained(this));
@@ -140,10 +140,9 @@
     response_ = data;
   }
 
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
+  net::TestURLRequestContext test_url_request_context_;
   content::MockResourceContext resource_context_;
   scoped_ptr<TestIframeSource> source_;
   content::URLDataSource::GotDataCallback callback_;
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h
index 789d5c7..f8c88e5 100644
--- a/chrome/browser/search/instant_service.h
+++ b/chrome/browser/search/instant_service.h
@@ -112,6 +112,7 @@
                            MANUAL_ShowsGoogleNTP);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedManualTest,
                            MANUAL_SearchesFromFakebox);
+  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ProcessIsolation);
 
   // Overridden from BrowserContextKeyedService:
   virtual void Shutdown() OVERRIDE;
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index ec6b193..883c43e 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -296,6 +296,12 @@
           IsInstantURL(url, profile));
 }
 
+bool ShouldUseProcessPerSiteForInstantURL(const GURL& url, Profile* profile) {
+  return ShouldAssignURLToInstantRenderer(url, profile) &&
+      (url.host() == chrome::kChromeSearchLocalNtpHost ||
+       url.host() == chrome::kChromeSearchOnlineNtpHost);
+}
+
 bool IsInstantNTP(const content::WebContents* contents) {
   if (!contents)
     return false;
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h
index f7630a5..7f1bf78 100644
--- a/chrome/browser/search/search.h
+++ b/chrome/browser/search/search.h
@@ -75,6 +75,9 @@
 // Returns true if |url| should be rendered in the Instant renderer process.
 bool ShouldAssignURLToInstantRenderer(const GURL& url, Profile* profile);
 
+// Returns true if the Instant |url| should use process per site.
+bool ShouldUseProcessPerSiteForInstantURL(const GURL& url, Profile* profile);
+
 // Returns true if the visible entry of |contents| is a New Tab Page rendered
 // by Instant. A page that matches the search or Instant URL of the default
 // search provider but does not have any search terms is considered an Instant
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index b718e06..c986500 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -290,6 +290,35 @@
   }
 }
 
+TEST_F(SearchTest, ShouldUseProcessPerSiteForInstantURL) {
+  EnableInstantExtendedAPIForTesting();
+
+  const SearchTestCase kTestCases[] = {
+    {"chrome-search://local-ntp",      true,  "Local NTP"},
+    {"chrome-search://online-ntp",     true,  "Online NTP"},
+    {"invalid-scheme://local-ntp",     false, "Invalid Local NTP URL"},
+    {"invalid-scheme://online-ntp",    false, "Invalid Online NTP URL"},
+    {"chrome-search://foo.com",        false, "Search result page"},
+    {"https://foo.com/instant?strk",   false,  ""},
+    {"https://foo.com/instant#strk",   false,  ""},
+    {"https://foo.com/instant?strk=0", false,  ""},
+    {"https://foo.com/url?strk",       false,  ""},
+    {"https://foo.com/alt?strk",       false,  ""},
+    {"http://foo.com/instant",         false,  "Non-HTTPS"},
+    {"http://foo.com/instant?strk",    false,  "Non-HTTPS"},
+    {"http://foo.com/instant?strk=1",  false,  "Non-HTTPS"},
+    {"https://foo.com/instant",        false,  "No search terms replacement"},
+    {"https://foo.com/?strk",          false,  "Non-exact path"},
+  };
+
+  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+    const SearchTestCase& test = kTestCases[i];
+    EXPECT_EQ(test.expected_result,
+              ShouldUseProcessPerSiteForInstantURL(GURL(test.url), profile()))
+        << test.url << " " << test.comment;
+  }
+}
+
 struct PrivilegedURLTestCase {
   bool add_as_alternate_url;
   const char* input_url;
diff --git a/chrome/browser/search_engines/search_provider_install_data_unittest.cc b/chrome/browser/search_engines/search_provider_install_data_unittest.cc
index 019c2c1..15aa4df 100644
--- a/chrome/browser/search_engines/search_provider_install_data_unittest.cc
+++ b/chrome/browser/search_engines/search_provider_install_data_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/search_engines/search_provider_install_data.h"
@@ -30,113 +31,72 @@
 // TestGetInstallState --------------------------------------------------------
 
 // Test the SearchProviderInstallData::GetInstallState.
-class TestGetInstallState :
-    public base::RefCountedThreadSafe<TestGetInstallState> {
+class TestGetInstallState {
  public:
   explicit TestGetInstallState(SearchProviderInstallData* install_data);
 
-  void set_search_provider_host(
-      const std::string& search_provider_host) {
-    search_provider_host_ = search_provider_host;
-  }
-
-  void set_default_search_provider_host(
-      const std::string& default_search_provider_host) {
-    default_search_provider_host_ = default_search_provider_host;
-  }
-
-  // Runs the test. Returns true if all passed. False if any failed.
-  bool RunTests();
+  // Runs all of the test cases.
+  void RunTests(const std::string& search_provider_host,
+                const std::string& default_search_provider_host);
 
  private:
-  friend class base::RefCountedThreadSafe<TestGetInstallState>;
-  ~TestGetInstallState();
-
-  // Starts the test run on the IO thread.
-  void StartTestOnIOThread();
-
   // Callback for when SearchProviderInstallData is ready to have
   // GetInstallState called. Runs all of the test cases.
-  void DoInstallStateTests();
+  void DoInstallStateTests(const std::string& search_provider_host,
+                           const std::string& default_search_provider_host);
 
   // Does a verification for one url and its expected state.
   void VerifyInstallState(SearchProviderInstallData::State expected_state,
                           const std::string& url);
 
   SearchProviderInstallData* install_data_;
-  base::MessageLoop* main_loop_;
-
-  // A host which should be a search provider but not the default.
-  std::string search_provider_host_;
-
-  // A host which should be a search provider but not the default.
-  std::string default_search_provider_host_;
-
-  // Used to indicate if DoInstallStateTests passed all test.
-  bool passed_;
 
   DISALLOW_COPY_AND_ASSIGN(TestGetInstallState);
 };
 
 TestGetInstallState::TestGetInstallState(
     SearchProviderInstallData* install_data)
-    : install_data_(install_data),
-      main_loop_(NULL),
-      passed_(false) {
+    : install_data_(install_data) {
 }
 
-bool TestGetInstallState::RunTests() {
-  passed_ = true;
-
-  main_loop_ = base::MessageLoop::current();
-
-  BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)->PostTask(
-      FROM_HERE,
-      base::Bind(&TestGetInstallState::StartTestOnIOThread, this));
-  // Run the current message loop. When the test is finished on the I/O thread,
-  // it invokes Quit, which unblocks this.
-  base::MessageLoop::current()->Run();
-  main_loop_ = NULL;
-
-  // Let the testing code know what the result is.
-  return passed_;
-}
-
-TestGetInstallState::~TestGetInstallState() {
-}
-
-void TestGetInstallState::StartTestOnIOThread() {
+void TestGetInstallState::RunTests(
+    const std::string& search_provider_host,
+    const std::string& default_search_provider_host) {
   install_data_->CallWhenLoaded(
-      base::Bind(&TestGetInstallState::DoInstallStateTests, this));
+      base::Bind(&TestGetInstallState::DoInstallStateTests,
+                 base::Unretained(this),
+                 search_provider_host, default_search_provider_host));
+  base::RunLoop().RunUntilIdle();
 }
 
-void TestGetInstallState::DoInstallStateTests() {
+void TestGetInstallState::DoInstallStateTests(
+    const std::string& search_provider_host,
+    const std::string& default_search_provider_host) {
+  SCOPED_TRACE("search provider: " + search_provider_host +
+               ", default search provider: " + default_search_provider_host);
   // Installed but not default.
   VerifyInstallState(SearchProviderInstallData::INSTALLED_BUT_NOT_DEFAULT,
-                     "http://" + search_provider_host_ + "/");
+                     "http://" + search_provider_host + "/");
   VerifyInstallState(SearchProviderInstallData::INSTALLED_BUT_NOT_DEFAULT,
-                     "http://" + search_provider_host_ + ":80/");
+                     "http://" + search_provider_host + ":80/");
 
   // Not installed.
   VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED,
-                     "http://" + search_provider_host_ + ":96/");
+                     "http://" + search_provider_host + ":96/");
 
   // Not installed due to different scheme.
   VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED,
-                     "https://" + search_provider_host_ + "/");
+                     "https://" + search_provider_host + "/");
 
   // Not installed.
   VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED,
-                     "http://a" + search_provider_host_ + "/");
+                     "http://a" + search_provider_host + "/");
 
   // Installed as default.
-  if (!default_search_provider_host_.empty()) {
+  if (!default_search_provider_host.empty()) {
     VerifyInstallState(SearchProviderInstallData::INSTALLED_AS_DEFAULT,
-                       "http://" + default_search_provider_host_ + "/");
+                       "http://" + default_search_provider_host + "/");
   }
-
-  // All done.
-  main_loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 void TestGetInstallState::VerifyInstallState(
@@ -145,16 +105,12 @@
 
   SearchProviderInstallData::State actual_state =
       install_data_->GetInstallState(GURL(url));
-  if (expected_state == actual_state)
-    return;
-
-  passed_ = false;
-  LOG(ERROR) << "GetInstallState for " << url << " failed. Expected " <<
-      expected_state << ".  Actual " << actual_state << ".";
+  EXPECT_EQ(expected_state, actual_state)
+      << "GetInstallState for " << url << " failed. Expected "
+      << expected_state << ".  Actual " << actual_state << ".";
 }
 
-};  // namespace
-
+}  // namespace
 
 // SearchProviderInstallDataTest ----------------------------------------------
 
@@ -193,7 +149,6 @@
       std::string() /* unknown country code */);
 #endif
   util_.SetUp();
-  util_.StartIOThread();
   install_data_ = new SearchProviderInstallData(util_.profile(),
       content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
       content::Source<SearchProviderInstallDataTest>(this));
@@ -247,7 +202,6 @@
   return t_url;
 }
 
-
 // Actual tests ---------------------------------------------------------------
 
 TEST_F(SearchProviderInstallDataTest, GetInstallState) {
@@ -257,24 +211,20 @@
   AddNewTemplateURL("http://" + host + "/path", ASCIIToUTF16("unittest"));
 
   // Wait for the changes to be saved.
-  TemplateURLServiceTestUtil::BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Verify the search providers install state (with no default set).
-  scoped_refptr<TestGetInstallState> test_get_install_state(
-      new TestGetInstallState(install_data_));
-  test_get_install_state->set_search_provider_host(host);
-  EXPECT_TRUE(test_get_install_state->RunTests());
+  TestGetInstallState test_get_install_state(install_data_);
+  test_get_install_state.RunTests(host, std::string());
 
   // Set-up a default and try it all one more time.
   std::string default_host = "www.mmm.com";
   TemplateURL* default_url =
       AddNewTemplateURL("http://" + default_host + "/", ASCIIToUTF16("mmm"));
   util_.model()->SetDefaultSearchProvider(default_url);
-  test_get_install_state->set_default_search_provider_host(default_host);
-  EXPECT_TRUE(test_get_install_state->RunTests());
+  test_get_install_state.RunTests(host, default_host);
 }
 
-
 TEST_F(SearchProviderInstallDataTest, ManagedDefaultSearch) {
   // Set up the database.
   util_.ChangeModelToLoadState();
@@ -288,28 +238,23 @@
   EXPECT_TRUE(util_.model()->is_default_search_managed());
 
   // Wait for the changes to be saved.
-  util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Verify the search providers install state.  The default search should be
   // the managed one we previously set.
-  scoped_refptr<TestGetInstallState> test_get_install_state(
-      new TestGetInstallState(install_data_));
-  test_get_install_state->set_search_provider_host(host);
-  test_get_install_state->set_default_search_provider_host(host2);
-  EXPECT_TRUE(test_get_install_state->RunTests());
+  TestGetInstallState test_get_install_state(install_data_);
+  test_get_install_state.RunTests(host, host2);
 }
 
-
 TEST_F(SearchProviderInstallDataTest, GoogleBaseUrlChange) {
-  scoped_refptr<TestGetInstallState> test_get_install_state(
-      new TestGetInstallState(install_data_));
+  TestGetInstallState test_get_install_state(install_data_);
 
   // Set up the database.
   util_.ChangeModelToLoadState();
   std::string google_host = "w.com";
   util_.SetGoogleBaseURL(GURL("http://" + google_host + "/"));
   // Wait for the I/O thread to process the update notification.
-  TemplateURLServiceTestUtil::BlockTillIOThreadProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   AddNewTemplateURL("{google:baseURL}?q={searchTerms}", ASCIIToUTF16("t"));
   TemplateURL* default_url =
@@ -317,19 +262,17 @@
   util_.model()->SetDefaultSearchProvider(default_url);
 
   // Wait for the changes to be saved.
-  TemplateURLServiceTestUtil::BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Verify the search providers install state (with no default set).
-  test_get_install_state->set_search_provider_host(google_host);
-  EXPECT_TRUE(test_get_install_state->RunTests());
+  test_get_install_state.RunTests(google_host, std::string());
 
   // Change the Google base url.
   google_host = "foo.com";
   util_.SetGoogleBaseURL(GURL("http://" + google_host + "/"));
   // Wait for the I/O thread to process the update notification.
-  TemplateURLServiceTestUtil::BlockTillIOThreadProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Verify that the change got picked up.
-  test_get_install_state->set_search_provider_host(google_host);
-  EXPECT_TRUE(test_get_install_state->RunTests());
+  test_get_install_state.RunTests(google_host, std::string());
 }
diff --git a/chrome/browser/search_engines/template_url_fetcher_unittest.cc b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
index e2eaec1..f55aca1 100644
--- a/chrome/browser/search_engines/template_url_fetcher_unittest.cc
+++ b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/search_engines/template_url_service_test_util.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_thread.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -46,12 +47,10 @@
 
   virtual void SetUp() OVERRIDE {
     test_util_.SetUp();
-    test_util_.StartIOThread();
     TestingProfile* profile = test_util_.profile();
     ASSERT_TRUE(profile);
     ASSERT_TRUE(TemplateURLFetcherFactory::GetForProfile(profile));
 
-    profile->CreateRequestContext();
     ASSERT_TRUE(profile->GetRequestContext());
     ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady());
   }
diff --git a/chrome/browser/search_engines/template_url_service_sync_unittest.cc b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
index 9b8461b..643e7d3 100644
--- a/chrome/browser/search_engines/template_url_service_sync_unittest.cc
+++ b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
+#include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -1895,7 +1896,7 @@
 
   // Merge the prepopulate search engines.
   base::Time pre_merge_time = base::Time::Now();
-  test_util_a_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
   test_util_a_.ResetModel(true);
 
   // The newly added search engine should have been safely merged, with an
diff --git a/chrome/browser/search_engines/template_url_service_test_util.cc b/chrome/browser/search_engines/template_url_service_test_util.cc
index 850b5e3..5c5e43c 100644
--- a/chrome/browser/search_engines/template_url_service_test_util.cc
+++ b/chrome/browser/search_engines/template_url_service_test_util.cc
@@ -5,9 +5,7 @@
 #include "chrome/browser/search_engines/template_url_service_test_util.h"
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/run_loop.h"
 #include "base/threading/thread.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/google/google_url_tracker.h"
@@ -20,43 +18,12 @@
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/google/google_util_chromeos.h"
 #endif
 
-using content::BrowserThread;
-
-namespace {
-
-// A callback used to coordinate when the database has finished processing
-// requests. See note in BlockTillServiceProcessesRequests for details.
-//
-// Schedules a QuitClosure on the message loop it was created with.
-void QuitCallback(base::MessageLoop* message_loop) {
-  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
-// Blocks the caller until thread has finished servicing all pending
-// requests.
-static void WaitForThreadToProcessRequests(BrowserThread::ID identifier) {
-  // Schedule a task on the thread that is processed after all
-  // pending requests on the thread.
-  BrowserThread::PostTask(
-      identifier,
-      FROM_HERE,
-      base::Bind(&QuitCallback, base::MessageLoop::current()));
-  base::MessageLoop::current()->Run();
-}
-
-}  // namespace
-
-
-// TestingTemplateURLService --------------------------------------------------
-
 // Trivial subclass of TemplateURLService that records the last invocation of
 // SetKeywordSearchTermsForURL.
 class TestingTemplateURLService : public TemplateURLService {
@@ -88,14 +55,14 @@
   DISALLOW_COPY_AND_ASSIGN(TestingTemplateURLService);
 };
 
-
 // TemplateURLServiceTestUtilBase ---------------------------------------------
 
 TemplateURLServiceTestUtilBase::TemplateURLServiceTestUtilBase()
     : changed_count_(0) {
 }
 
-TemplateURLServiceTestUtilBase::~TemplateURLServiceTestUtilBase() {}
+TemplateURLServiceTestUtilBase::~TemplateURLServiceTestUtilBase() {
+}
 
 void TemplateURLServiceTestUtilBase::CreateTemplateUrlService() {
   profile()->CreateWebDataService();
@@ -118,18 +85,10 @@
   changed_count_ = 0;
 }
 
-void TemplateURLServiceTestUtilBase::BlockTillServiceProcessesRequests() {
-  WaitForThreadToProcessRequests(BrowserThread::DB);
-}
-
-void TemplateURLServiceTestUtilBase::BlockTillIOThreadProcessesRequests() {
-  WaitForThreadToProcessRequests(BrowserThread::IO);
-}
-
 void TemplateURLServiceTestUtilBase::VerifyLoad() {
   ASSERT_FALSE(model()->loaded());
   model()->Load();
-  BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, GetObserverCount());
   ResetObserverCount();
 }
@@ -140,7 +99,7 @@
   // any changes made.
 
   model()->service_ = WebDataService::FromBrowserContext(profile());
-  BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 }
 
 void TemplateURLServiceTestUtilBase::ClearModel() {
@@ -238,9 +197,7 @@
 // TemplateURLServiceTestUtil -------------------------------------------------
 
 TemplateURLServiceTestUtil::TemplateURLServiceTestUtil()
-    : ui_thread_(BrowserThread::UI, &message_loop_),
-      db_thread_(BrowserThread::DB),
-      io_thread_(BrowserThread::IO) {
+    : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
 }
 
 TemplateURLServiceTestUtil::~TemplateURLServiceTestUtil() {
@@ -250,7 +207,6 @@
   // Make unique temp directory.
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
   profile_.reset(new TestingProfile(temp_dir_.path()));
-  db_thread_.Start();
 
   TemplateURLServiceTestUtilBase::CreateTemplateUrlService();
 
@@ -260,49 +216,14 @@
 }
 
 void TemplateURLServiceTestUtil::TearDown() {
-  if (profile_.get()) {
-    // Clear the request context so it will get deleted. This should be done
-    // before shutting down the I/O thread to avoid memory leaks.
-    profile_->ResetRequestContext();
-    profile_.reset();
-  }
-
-  // Wait for the delete of the request context to happen.
-  if (io_thread_.IsRunning())
-    TemplateURLServiceTestUtilBase::BlockTillIOThreadProcessesRequests();
-
-  // The I/O thread must be shutdown before the DB thread.
-  io_thread_.Stop();
-
-  // Note that we must ensure the DB thread is stopped after WDS
-  // shutdown (so it can commit pending transactions) but before
-  // deleting the test profile directory, otherwise we may not be
-  // able to delete it due to an open transaction.
-  // Schedule another task on the DB thread to notify us that it's safe to
-  // carry on with the test.
-  base::WaitableEvent done(false, false);
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
-  base::MessageLoop::current()->PostTask(FROM_HERE,
-                                         base::MessageLoop::QuitClosure());
-  base::MessageLoop::current()->Run();
-  db_thread_.Stop();
+  profile_.reset();
 
   UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
 
   // Flush the message loop to make application verifiers happy.
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 TestingProfile* TemplateURLServiceTestUtil::profile() const {
   return profile_.get();
 }
-
-void TemplateURLServiceTestUtil::StartIOThread() {
-  io_thread_.StartIOThread();
-}
-
-void TemplateURLServiceTestUtil::PumpLoop() {
-  message_loop_.RunUntilIdle();
-}
diff --git a/chrome/browser/search_engines/template_url_service_test_util.h b/chrome/browser/search_engines/template_url_service_test_util.h
index 7ddd4fd..6c7c379 100644
--- a/chrome/browser/search_engines/template_url_service_test_util.h
+++ b/chrome/browser/search_engines/template_url_service_test_util.h
@@ -15,7 +15,7 @@
 #include "base/strings/string16.h"
 #include "chrome/browser/search_engines/template_url_service_observer.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 
 class GURL;
 class TemplateURLService;
@@ -42,14 +42,6 @@
   // Sets the observer count to 0.
   void ResetObserverCount();
 
-  // Blocks the caller until the service has finished servicing all pending
-  // requests.
-  static void BlockTillServiceProcessesRequests();
-
-  // Blocks the caller until the I/O thread has finished servicing all pending
-  // requests.
-  static void BlockTillIOThreadProcessesRequests();
-
   // Makes sure the load was successful and sent the correct notification.
   void VerifyLoad();
 
@@ -119,19 +111,10 @@
   // Returns the TestingProfile.
   virtual TestingProfile* profile() const OVERRIDE;
 
-  // Starts an I/O thread.
-  void StartIOThread();
-
-  // Runs all pending tasks on the UI loop.
-  void PumpLoop();
-
  private:
-  base::MessageLoopForUI message_loop_;
   // Needed to make the DeleteOnUIThread trait of WebDataService work
   // properly.
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
   base::ScopedTempDir temp_dir_;
 
diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc
index b1e95de..a230386 100644
--- a/chrome/browser/search_engines/template_url_service_unittest.cc
+++ b/chrome/browser/search_engines/template_url_service_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
+#include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -41,72 +42,6 @@
 
 namespace {
 
-// TestGenerateSearchURL ------------------------------------------------------
-
-// Test the GenerateSearchURL on a thread or the main thread.
-class TestGenerateSearchURL
-    : public base::RefCountedThreadSafe<TestGenerateSearchURL> {
- public:
-  explicit TestGenerateSearchURL(SearchTermsData* search_terms_data);
-
-  // Run the test cases for GenerateSearchURL.
-  void RunTest();
-
-  // Did the test pass?
-  bool passed() const { return passed_; }
-
- private:
-  friend class base::RefCountedThreadSafe<TestGenerateSearchURL>;
-  ~TestGenerateSearchURL();
-
-  SearchTermsData* search_terms_data_;
-  bool passed_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestGenerateSearchURL);
-};
-
-TestGenerateSearchURL::TestGenerateSearchURL(SearchTermsData* search_terms_data)
-    : search_terms_data_(search_terms_data),
-      passed_(false) {
-}
-
-void TestGenerateSearchURL::RunTest() {
-  struct GenerateSearchURLCase {
-    const char* test_name;
-    const char* url;
-    const char* expected;
-  } generate_url_cases[] = {
-    { "invalid URL", "foo{searchTerms}", "" },
-    { "URL with no replacements", "http://foo/", "http://foo/" },
-    { "basic functionality", "http://foo/{searchTerms}",
-      "http://foo/blah.blah.blah.blah.blah" }
-  };
-
-  // Don't use ASSERT/EXPECT since this is run on a thread in one test
-  // and those macros aren't meant for threads at this time according to
-  // gtest documentation.
-  bool everything_passed = true;
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) {
-    TemplateURLData data;
-    data.SetURL(generate_url_cases[i].url);
-    TemplateURL t_url(NULL, data);
-    std::string result = (search_terms_data_ ?
-        TemplateURLService::GenerateSearchURLUsingTermsData(&t_url,
-            *search_terms_data_) :
-        TemplateURLService::GenerateSearchURL(&t_url)).spec();
-    if (result != generate_url_cases[i].expected) {
-      LOG(ERROR) << generate_url_cases[i].test_name << " failed. Expected " <<
-          generate_url_cases[i].expected << " Actual " << result;
-      everything_passed = false;
-    }
-  }
-  passed_ = everything_passed;
-}
-
-TestGenerateSearchURL::~TestGenerateSearchURL() {
-}
-
-
 // TestSearchTermsData --------------------------------------------------------
 
 // Simple implementation of SearchTermsData.
@@ -303,6 +238,36 @@
  protected:
   TemplateURLServiceTestUtil test_util_;
 
+  void TestGenerateSearchURL(SearchTermsData* search_terms_data) {
+    struct GenerateSearchURLCase {
+      const char* test_name;
+      const char* url;
+      const char* expected;
+    } generate_url_cases[] = {
+      { "invalid URL", "foo{searchTerms}", "" },
+      { "URL with no replacements", "http://foo/", "http://foo/" },
+      { "basic functionality", "http://foo/{searchTerms}",
+        "http://foo/blah.blah.blah.blah.blah" }
+    };
+
+    for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) {
+      TemplateURLData data;
+      data.SetURL(generate_url_cases[i].url);
+      TemplateURL t_url(NULL, data);
+      std::string result;
+      if (search_terms_data) {
+          result = TemplateURLService::GenerateSearchURLUsingTermsData(
+              &t_url, *search_terms_data).spec();
+      } else {
+          result = TemplateURLService::GenerateSearchURL(&t_url).spec();
+      }
+      EXPECT_EQ(result,  generate_url_cases[i].expected)
+          << generate_url_cases[i].test_name << " failed. Expected "
+          << generate_url_cases[i].expected << " Actual " << result;
+    }
+  }
+
+
   DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTest);
 };
 
@@ -405,7 +370,7 @@
   ASSERT_TRUE(keyword_url != NULL);
   EXPECT_EQ(t_url, keyword_url);
   EXPECT_EQ(original_url, keyword_url->url_ref().DisplayURL());
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Now reload the model and verify that the merge updates the url, and
   // preserves the sync GUID.
@@ -416,7 +381,7 @@
   EXPECT_EQ(original_guid, keyword_url->sync_guid());
 
   // Wait for any saves to finish.
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Reload the model to verify that change was saved correctly.
   test_util_.ResetModel(true);
@@ -462,7 +427,7 @@
   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
                                          NULL));
   VerifyObserverCount(1);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(t_url->keyword()));
   // We need to make a second copy as the model takes ownership of |t_url| and
@@ -499,7 +464,7 @@
                                          NULL));
   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL));
   cloned_url.reset(new TemplateURL(loaded_url->profile(), loaded_url->data()));
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
   test_util_.ResetModel(true);
   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
@@ -676,25 +641,14 @@
 }
 
 TEST_F(TemplateURLServiceTest, GenerateSearchURL) {
-  scoped_refptr<TestGenerateSearchURL> test_generate_search_url(
-      new TestGenerateSearchURL(NULL));
-  test_generate_search_url->RunTest();
-  EXPECT_TRUE(test_generate_search_url->passed());
+  TestGenerateSearchURL(NULL);
 }
 
 TEST_F(TemplateURLServiceTest, GenerateSearchURLUsingTermsData) {
   // Run the test for GenerateSearchURLUsingTermsData on the "IO" thread and
   // wait for it to finish.
   TestSearchTermsData search_terms_data("http://google.com/");
-  scoped_refptr<TestGenerateSearchURL> test_generate_search_url(
-      new TestGenerateSearchURL(&search_terms_data));
-
-  test_util_.StartIOThread();
-  BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)->PostTask(
-          FROM_HERE, base::Bind(&TestGenerateSearchURL::RunTest,
-                                test_generate_search_url.get()));
-  TemplateURLServiceTestUtil::BlockTillIOThreadProcessesRequests();
-  EXPECT_TRUE(test_generate_search_url->passed());
+  TestGenerateSearchURL(&search_terms_data);
 }
 
 TEST_F(TemplateURLServiceTest, ClearBrowsingData_Keywords) {
@@ -826,7 +780,7 @@
   model()->Add(t_url);
 
   VerifyObserverCount(1);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   StrictMock<base::MockTimeProvider> mock_time;
   model()->set_time_provider(&base::MockTimeProvider::StaticNow);
@@ -874,7 +828,7 @@
 
   // Setting the default search provider should have caused notification.
   VerifyObserverCount(1);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
                                                      t_url->data()));
@@ -953,7 +907,7 @@
   const TemplateURLID id = t_url->id();
 
   model()->SetDefaultSearchProvider(t_url);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
                                                      t_url->data()));
 
@@ -1243,7 +1197,7 @@
   model()->Add(t_url);
   ASSERT_TRUE(
       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Ensure that merging clears this engine.
   test_util_.ResetModel(true);
@@ -1251,7 +1205,7 @@
       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
 
   // Wait for any saves to finish.
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Reload the model to verify that the database was updated as a result of the
   // merge.
@@ -1274,7 +1228,7 @@
   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
 
   // Wait for any saves to finish.
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Ensure that merging won't clear it if the user has edited it.
   test_util_.ResetModel(true);
@@ -1284,7 +1238,7 @@
   AssertEquals(*cloned_url, *url_for_unittest);
 
   // Wait for any saves to finish.
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Reload the model to verify that save/reload retains the item.
   test_util_.ResetModel(true);
@@ -1304,7 +1258,7 @@
                                                      default_search->data()));
 
   // Wait for any saves to finish.
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Reload the model and check that the default search provider
   // was properly saved.
@@ -1368,7 +1322,7 @@
 
   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Ensure that merging won't clear the prepopulated template url
   // which is no longer present if it's the default engine.
@@ -1382,7 +1336,7 @@
   }
 
   // Wait for any saves to finish.
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Reload the model to verify that the update was saved.
   test_util_.ResetModel(true);
@@ -1418,7 +1372,7 @@
   // Now remove it.
   model()->SetDefaultSearchProvider(NULL);
   model()->Remove(old_default);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(model()->GetDefaultSearchProvider());
 
@@ -1432,7 +1386,7 @@
   model()->ResetTemplateURL(model()->GetDefaultSearchProvider(),
                             ASCIIToUTF16("test"), ASCIIToUTF16("test"),
                             "http://example.com/");
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   // Reset the model and load it. There should be a usable default search
   // provider.
@@ -1454,7 +1408,7 @@
 
   test_util_.ResetModel(false);
   model()->Load();
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_TRUE(model()->GetDefaultSearchProvider());
 }
@@ -1610,7 +1564,7 @@
   model()->Add(t_url);
 
   VerifyObserverCount(1);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
 
   // Reload the model to verify it was actually saved to the database and
@@ -1647,7 +1601,7 @@
   model()->Add(t_url);
 
   VerifyObserverCount(1);
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   const TemplateURL* loaded_url =
       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
diff --git a/chrome/browser/signin/oauth2_token_service_unittest.cc b/chrome/browser/signin/oauth2_token_service_unittest.cc
index 6859f37..ba68353 100644
--- a/chrome/browser/signin/oauth2_token_service_unittest.cc
+++ b/chrome/browser/signin/oauth2_token_service_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <string>
 
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
@@ -11,6 +12,7 @@
 #include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/browser/signin/token_service_unittest.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
@@ -70,19 +72,13 @@
  public:
   virtual void SetUp() OVERRIDE {
     TokenServiceTestHarness::SetUp();
-    io_thread_.reset(new content::TestBrowserThread(content::BrowserThread::IO,
-                                                    &message_loop_));
     oauth2_service_.reset(
         new TestOAuth2TokenService(new net::TestURLRequestContextGetter(
-            message_loop_.message_loop_proxy())));
-  }
-
-  virtual void TearDown() OVERRIDE {
-    TokenServiceTestHarness::TearDown();
+            BrowserThread::GetMessageLoopProxyForThread(
+                BrowserThread::IO))));
   }
 
  protected:
-  scoped_ptr<content::TestBrowserThread> io_thread_;
   net::TestURLFetcherFactory factory_;
   scoped_ptr<TestOAuth2TokenService> oauth2_service_;
   TestingOAuth2TokenServiceConsumer consumer_;
@@ -91,7 +87,7 @@
 TEST_F(OAuth2TokenServiceTest, NoOAuth2RefreshToken) {
   scoped_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(1, consumer_.number_of_errors_);
@@ -101,7 +97,7 @@
   oauth2_service_->set_refresh_token("refreshToken");
   scoped_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
@@ -119,7 +115,7 @@
   oauth2_service_->set_refresh_token("refreshToken");
   scoped_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
@@ -148,7 +144,7 @@
   // First request.
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       scopes1, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
@@ -165,7 +161,7 @@
   // without needing a network request.
   scoped_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(scopes1_same, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // No new network fetcher.
   EXPECT_EQ(fetcher, factory_.GetFetcherByID(0));
@@ -176,7 +172,7 @@
   // Third request to a new set of scopes, should return another token.
   scoped_ptr<OAuth2TokenService::Request> request3(
       oauth2_service_->StartRequest(scopes2, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   fetcher = factory_.GetFetcherByID(0);
@@ -195,7 +191,7 @@
   // First request.
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
@@ -210,7 +206,7 @@
   // Second request must try to access the network as the token has expired.
   scoped_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
 
@@ -230,7 +226,7 @@
   // First request.
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
@@ -245,7 +241,7 @@
   // Second request must try to access the network as the token has expired.
   scoped_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
 
@@ -264,7 +260,7 @@
 
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
@@ -284,7 +280,7 @@
 
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
   fetcher->set_response_code(net::HTTP_OK);
   fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
@@ -305,10 +301,10 @@
 
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   scoped_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   request.reset();
 
@@ -325,7 +321,7 @@
   oauth2_service_->set_refresh_token("refreshToken");
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
   fetcher->set_response_code(net::HTTP_OK);
   fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
@@ -337,7 +333,7 @@
   // The refresh token is no longer available; subsequent requests fail.
   oauth2_service_->set_refresh_token("");
   request = oauth2_service_->StartRequest(std::set<std::string>(), &consumer_);
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(fetcher, factory_.GetFetcherByID(0));
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(1, consumer_.number_of_errors_);
@@ -352,7 +348,7 @@
 
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       scopes, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   net::TestURLFetcher* fetcher1 = factory_.GetFetcherByID(0);
 
   // Note |request| is still pending when the refresh token changes.
@@ -363,7 +359,7 @@
   TestingOAuth2TokenServiceConsumer consumer2;
   scoped_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(scopes, &consumer2));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   net::TestURLFetcher* fetcher2 = factory_.GetFetcherByID(0);
   fetcher2->set_response_code(net::HTTP_OK);
@@ -385,7 +381,7 @@
   oauth2_service_->set_refresh_token("refreshToken");
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
 
@@ -401,7 +397,7 @@
   RetryingTestingOAuth2TokenServiceConsumer consumer(oauth2_service_.get());
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       std::set<std::string>(), &consumer));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer.number_of_errors_);
 
@@ -429,7 +425,7 @@
   // First request.
   scoped_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(scopes, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
@@ -446,7 +442,7 @@
   // request.
   scoped_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(scopes, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // No new network fetcher.
   EXPECT_EQ(fetcher, factory_.GetFetcherByID(0));
@@ -458,7 +454,7 @@
   oauth2_service_->InvalidateToken(scopes, consumer_.last_token_);
   scoped_ptr<OAuth2TokenService::Request> request3(
       oauth2_service_->StartRequest(scopes, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   fetcher = factory_.GetFetcherByID(0);
diff --git a/chrome/browser/signin/profile_oauth2_token_service_unittest.cc b/chrome/browser/signin/profile_oauth2_token_service_unittest.cc
index 8170bfe..0cbb571 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_unittest.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/run_loop.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
 #include "chrome/browser/signin/oauth2_token_service_test_util.h"
 #include "chrome/browser/signin/profile_oauth2_token_service.h"
@@ -27,12 +28,9 @@
 
   virtual void SetUp() OVERRIDE {
     TokenServiceTestHarness::SetUp();
-    io_thread_.reset(new content::TestBrowserThread(content::BrowserThread::IO,
-                                                    &message_loop_));
-    service_->UpdateCredentials(credentials_);
-    profile_->CreateRequestContext();
+    UpdateCredentialsOnService();
     oauth2_service_ = ProfileOAuth2TokenServiceFactory::GetForProfile(
-        profile_.get());
+        profile());
 
     oauth2_service_->AddObserver(this);
   }
@@ -106,7 +104,6 @@
   }
 
  protected:
-  scoped_ptr<content::TestBrowserThread> io_thread_;
   net::TestURLFetcherFactory factory_;
   ProfileOAuth2TokenService* oauth2_service_;
   TestingOAuth2TokenServiceConsumer consumer_;
@@ -118,12 +115,12 @@
 
 TEST_F(ProfileOAuth2TokenServiceTest, Notifications) {
   EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                  "refreshToken");
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
   ExpectOneTokenAvailableNotification();
 
-  service_->EraseTokensFromDB();
-  service_->ResetCredentialsInMemory();
+  service()->EraseTokensFromDB();
+  service()->ResetCredentialsInMemory();
   ExpectOneTokensClearedNotification();
 }
 
@@ -133,11 +130,11 @@
   EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
 
   // Get a valid token.
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                  "refreshToken");
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
   ExpectOneTokenAvailableNotification();
 
-  service_->OnIssueAuthTokenFailure(
+  service()->OnIssueAuthTokenFailure(
       GaiaConstants::kLSOService,
       GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
   ExpectOneTokenRevokedNotification();
@@ -147,22 +144,22 @@
 // should translate to finish token loading in ProfileOAuth2TokenService.
 TEST_F(ProfileOAuth2TokenServiceTest, TokensLoaded) {
   EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
-  service_->LoadTokensFromDB();
-  WaitForDBLoadCompletion();
+  service()->LoadTokensFromDB();
+  base::RunLoop().RunUntilIdle();
   ExpectOneTokensLoadedNotification();
 }
 
 TEST_F(ProfileOAuth2TokenServiceTest, UnknownNotificationsAreNoops) {
   EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
-  service_->IssueAuthTokenForTest("foo", "toto");
+  service()->IssueAuthTokenForTest("foo", "toto");
   ExpectNoNotifications();
 
   // Get a valid token.
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                  "refreshToken");
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
   ExpectOneTokenAvailableNotification();
 
-  service_->IssueAuthTokenForTest("bar", "baz");
+  service()->IssueAuthTokenForTest("bar", "baz");
   ExpectNoNotifications();
 }
 
@@ -170,12 +167,12 @@
   EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
   std::set<std::string> scope_list;
   scope_list.insert("scope");
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                  "refreshToken");
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
   ExpectOneTokenAvailableNotification();
   scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
       scope_list, &consumer_));
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
   fetcher->set_response_code(net::HTTP_OK);
   fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
@@ -186,19 +183,19 @@
   EXPECT_EQ(1, oauth2_service_->cache_size_for_testing());
 
   // Signs out and signs in
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
                                   "");
   ExpectOneTokenAvailableNotification();
-  service_->EraseTokensFromDB();
+  service()->EraseTokensFromDB();
   ExpectOneTokensClearedNotification();
 
   EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
                                   "refreshToken");
   ExpectOneTokenAvailableNotification();
 
   request = oauth2_service_->StartRequest(scope_list, &consumer_);
-  message_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   fetcher = factory_.GetFetcherByID(0);
   fetcher->set_response_code(net::HTTP_OK);
   fetcher->SetResponseString(GetValidTokenResponse("another token", 3600));
@@ -212,19 +209,19 @@
 // Android doesn't use the current profile's TokenService login refresh token.
 #if !defined(OS_ANDROID)
 TEST_F(ProfileOAuth2TokenServiceTest, StaleRefreshTokensNotCached) {
-  EXPECT_FALSE(service_->HasOAuthLoginToken());
-  EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T1"));
+  EXPECT_FALSE(service()->HasOAuthLoginToken());
+  EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T1"));
 
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
                                   "T1");
   ExpectOneTokenAvailableNotification();
-  EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T1"));
-  EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T2"));
+  EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T1"));
+  EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T2"));
 
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
                                   "T2");
   ExpectOneTokenAvailableNotification();
-  EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T2"));
+  EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T2"));
   EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(NULL, "T2"));
 }
 #endif
diff --git a/chrome/browser/signin/signin_browsertest.cc b/chrome/browser/signin/signin_browsertest.cc
index 14ee972..4cfde8d 100644
--- a/chrome/browser/signin/signin_browsertest.cc
+++ b/chrome/browser/signin/signin_browsertest.cc
@@ -17,9 +17,12 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/content_switches.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/url_request/test_url_fetcher_factory.h"
@@ -161,4 +164,72 @@
   EXPECT_FALSE(signin->HasSigninProcess());
 }
 
+class BackOnNTPCommitObserver : public content::WebContentsObserver {
+ public:
+  explicit BackOnNTPCommitObserver(content::WebContents* web_contents)
+      : content::WebContentsObserver(web_contents) {
+  }
+
+  virtual void DidCommitProvisionalLoadForFrame(
+      int64 frame_id,
+      bool is_main_frame,
+      const GURL& url,
+      content::PageTransition transition_type,
+      content::RenderViewHost* render_view_host) OVERRIDE {
+    if (url == GURL(chrome::kChromeUINewTabURL)) {
+      content::WindowedNotificationObserver observer(
+          content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+          content::NotificationService::AllSources());
+      web_contents()->GetController().GoBack();
+      observer.Wait();
+    }
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BackOnNTPCommitObserver);
+};
+
+// This is a test for http://crbug.com/257277. It simulates the navigations
+// that occur if the user clicks on the "Skip for now" link at the signin page
+// and initiates a back navigation between the point of Commit and
+// DidStopLoading of the NTP.
+IN_PROC_BROWSER_TEST_F(SigninBrowserTest, SigninSkipForNowAndGoBack) {
+  GURL ntp_url(chrome::kChromeUINewTabURL);
+  GURL start_url =
+      SyncPromoUI::GetSyncPromoURL(SyncPromoUI::SOURCE_START_PAGE, true);
+  GURL skip_url(SyncPromoUI::GetSyncLandingURL("ntp", 1));
+
+  SigninManager* signin = SigninManagerFactory::GetForProfile(
+      browser()->profile());
+  EXPECT_FALSE(signin->HasSigninProcess());
+
+  ui_test_utils::NavigateToURL(browser(), start_url);
+  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Simulate clicking on the Skip for now link by navigating to the URL.
+  ui_test_utils::NavigateToURL(browser(), skip_url);
+
+  // Register an observer that will navigate back immediately on the commit of
+  // the NTP. This will allow us to hit the race condition of navigating back
+  // before the DidStopLoading message of NTP gets delivered. This must be
+  // created after the navigation to the skip_url has finished loading,
+  // otherwise this observer will navigate back, before the history cleaner
+  // has had a chance to remove the navigation entry.
+  BackOnNTPCommitObserver commit_observer(web_contents);
+
+  // Since the navigation to the blank URL is monitored for, the
+  // OneClickSigninHelper initiates immediately a navigation to the NTP.
+  // Thus, we expect the visible URL to be the NTP.
+  EXPECT_EQ(skip_url, web_contents->GetLastCommittedURL());
+  EXPECT_EQ(ntp_url, web_contents->GetVisibleURL());
+
+  content::WindowedNotificationObserver observer(
+      content::NOTIFICATION_LOAD_STOP,
+      content::NotificationService::AllSources());
+  observer.Wait();
+  EXPECT_EQ(start_url, web_contents->GetLastCommittedURL());
+}
 #endif  // CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
diff --git a/chrome/browser/signin/signin_manager_unittest.cc b/chrome/browser/signin/signin_manager_unittest.cc
index 232d9c5..f008430 100644
--- a/chrome/browser/signin/signin_manager_unittest.cc
+++ b/chrome/browser/signin/signin_manager_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/testing_pref_service.h"
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -22,7 +23,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/webdata/encryptor/encryptor.h"
 #include "content/public/browser/child_process_security_policy.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/cookies/cookie_monster.h"
@@ -34,8 +35,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 namespace {
 
 const char kGetTokenPairValidResponse[] =
@@ -53,18 +52,6 @@
 
 class SigninManagerTest : public TokenServiceTestHarness {
  public:
-  void SetUpOnIOThread(base::WaitableEvent* io_setup_complete) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    // This is a workaround for a bug in the TestingProfile.
-    // The URLRequestContext will be created by GetCookieMonster on the UI
-    // thread, if it does not already exist. But it must be created on the IO
-    // thread or else it will DCHECK upon destruction.
-    // Force it to be created here.
-    profile_->CreateRequestContext();
-    profile_->GetRequestContext()->GetURLRequestContext();
-    io_setup_complete->Signal();
-  }
-
   virtual void SetUp() OVERRIDE {
     prefs_.reset(new TestingPrefServiceSimple);
     chrome::RegisterLocalState(prefs_->registry());
@@ -73,32 +60,22 @@
     TokenServiceTestHarness::SetUp();
     manager_.reset(new SigninManager(
         scoped_ptr<SigninManagerDelegate>(
-            new ChromeSigninManagerDelegate(profile_.get()))));
+            new ChromeSigninManagerDelegate(profile()))));
     google_login_success_.ListenFor(
         chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-        content::Source<Profile>(profile_.get()));
+        content::Source<Profile>(profile()));
     google_login_failure_.ListenFor(chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
-                                    content::Source<Profile>(profile_.get()));
-
-    io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO));
-    ASSERT_TRUE(io_thread_->Start());
-    base::WaitableEvent io_setup_complete(true, false);
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::Bind(&SigninManagerTest::SetUpOnIOThread,
-                   base::Unretained(this), &io_setup_complete));
-    io_setup_complete.Wait();
+                                    content::Source<Profile>(profile()));
   }
 
   virtual void TearDown() OVERRIDE {
-    // Destroy the SigninManager here, because it relies on profile_ which is
+    // Destroy the SigninManager here, because it relies on profile() which is
     // freed in the base class.
     manager_->Shutdown();
     manager_.reset(NULL);
     TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
     prefs_.reset(NULL);
     TokenServiceTestHarness::TearDown();
-    io_thread_->Stop();
   }
 
   void SetupFetcherAndComplete(const std::string& url,
@@ -170,26 +147,6 @@
                             cookies, "<html></html>");
   }
 
-  void WaitUntilUIDone() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::Bind(&SigninManagerTest::NotifyUIOnComplete,
-                   base::Unretained(this)));
-    base::MessageLoop::current()->Run();
-  }
-
-  void NotifyUIOnComplete () {
-    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-      // Redo on UI thread.
-      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-          base::Bind(&SigninManagerTest::NotifyUIOnComplete,
-                     base::Unretained(this)));
-      return;
-    }
-    base::MessageLoop::current()->Quit();
-  }
-
   void ExpectSignInWithCredentialsSuccess() {
     EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
@@ -199,7 +156,7 @@
 
     // This is flow, the oauth2 credentials should already be available in
     // the token service.
-    EXPECT_TRUE(service_->HasOAuthLoginToken());
+    EXPECT_TRUE(service()->HasOAuthLoginToken());
 
     // Should go into token service and stop.
     EXPECT_EQ(1U, google_login_success_.size());
@@ -209,8 +166,8 @@
     manager_->Shutdown();
     manager_.reset(new SigninManager(
         scoped_ptr<SigninManagerDelegate>(
-            new ChromeSigninManagerDelegate(profile_.get()))));
-    manager_->Initialize(profile_.get(), NULL);
+            new ChromeSigninManagerDelegate(profile()))));
+    manager_->Initialize(profile(), NULL);
     EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedUsername());
   }
 
@@ -226,7 +183,7 @@
 
     // The oauth2 credentials should not be available in the token service
     // because the email was incorrect.
-    EXPECT_FALSE(service_->HasOAuthLoginToken());
+    EXPECT_FALSE(service()->HasOAuthLoginToken());
 
     // Should go into token service and stop.
     EXPECT_EQ(0U, google_login_success_.size());
@@ -249,14 +206,13 @@
   content::TestNotificationTracker google_login_failure_;
   std::vector<std::string> oauth_tokens_fetched_;
   scoped_ptr<TestingPrefServiceSimple> prefs_;
-  scoped_ptr<content::TestBrowserThread> io_thread_;
   std::vector<std::string> cookies_;
 };
 
 // NOTE: ClientLogin's "StartSignin" is called after collecting credentials
 //       from the user.
 TEST_F(SigninManagerTest, SignInClientLogin) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->StartSignIn(
@@ -270,8 +226,9 @@
   EXPECT_EQ(1U, google_login_success_.size());
   EXPECT_EQ(0U, google_login_failure_.size());
 
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                    "oauth2Token");
+  service()->OnIssueAuthTokenSuccess(
+      GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+      "oauth2Token");
   SimulateValidUberToken();
   // Check that the login cookie has been sent.
   ASSERT_NE(std::find(cookies_.begin(), cookies_.end(), "checkCookie = true"),
@@ -281,13 +238,13 @@
   manager_->Shutdown();
   manager_.reset(new SigninManager(
       scoped_ptr<SigninManagerDelegate>(
-          new ChromeSigninManagerDelegate(profile_.get()))));
-  manager_->Initialize(profile_.get(), NULL);
+          new ChromeSigninManagerDelegate(profile()))));
+  manager_->Initialize(profile(), NULL);
   EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedUsername());
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentials) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->StartSignInWithCredentials(
@@ -300,7 +257,7 @@
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentialsNonCanonicalEmail) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->StartSignInWithCredentials(
@@ -313,7 +270,7 @@
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentialsWrongEmail) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   // If the email address used to start the sign in does not match the
@@ -328,12 +285,12 @@
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentialsEmptyPasswordValidCookie) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   // Set a valid LSID cookie in the test cookie store.
   scoped_refptr<net::CookieMonster> cookie_monster =
-      profile_->GetCookieMonster();
+      profile()->GetCookieMonster();
   net::CookieOptions options;
   options.set_include_httponly();
   cookie_monster->SetCookieWithOptionsAsync(
@@ -348,14 +305,14 @@
       std::string(),
       SigninManager::OAuthTokenFetchedCallback());
 
-  WaitUntilUIDone();
+  base::RunLoop().RunUntilIdle();
 
   // Verification should succeed and continue with auto signin.
   ExpectSignInWithCredentialsSuccess();
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentialsEmptyPasswordNoValidCookie) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   // Since the password is empty, will verify the gaia cookies first.
@@ -365,7 +322,7 @@
       std::string(),
       SigninManager::OAuthTokenFetchedCallback());
 
-  WaitUntilUIDone();
+  base::RunLoop().RunUntilIdle();
 
   // Since the test cookie store is empty, verification should fail and throws
   // a login error.
@@ -373,12 +330,12 @@
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentialsEmptyPasswordInValidCookie) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   // Set an invalid LSID cookie in the test cookie store.
   scoped_refptr<net::CookieMonster> cookie_monster =
-      profile_->GetCookieMonster();
+      profile()->GetCookieMonster();
   net::CookieOptions options;
   options.set_include_httponly();
   cookie_monster->SetCookieWithOptionsAsync(
@@ -393,7 +350,7 @@
       std::string(),
       SigninManager::OAuthTokenFetchedCallback());
 
-  WaitUntilUIDone();
+  base::RunLoop().RunUntilIdle();
 
   // Since the LSID cookie is invalid, verification should fail and throws
   // a login error.
@@ -401,7 +358,7 @@
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentialsCallbackComplete) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   // Since the password is empty, must verify the gaia cookies first.
@@ -420,7 +377,7 @@
 }
 
 TEST_F(SigninManagerTest, SignInWithCredentialsCallbackCancel) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   // Since the password is empty, must verify the gaia cookies first.
@@ -440,7 +397,7 @@
 }
 
 TEST_F(SigninManagerTest, SignInClientLoginNoGPlus) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->StartSignIn("username", "password", std::string(), std::string());
@@ -451,7 +408,7 @@
 }
 
 TEST_F(SigninManagerTest, ClearTransientSigninData) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->StartSignIn("username", "password", std::string(), std::string());
@@ -472,24 +429,24 @@
 
   // Ensure preferences are not modified.
   EXPECT_FALSE(
-     profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername).empty());
+     profile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername).empty());
 
   // On reset it should be regenerated.
   manager_->Shutdown();
   manager_.reset(new SigninManager(
       scoped_ptr<SigninManagerDelegate>(
-          new ChromeSigninManagerDelegate(profile_.get()))));
-  manager_->Initialize(profile_.get(), NULL);
+          new ChromeSigninManagerDelegate(profile()))));
+  manager_->Initialize(profile(), NULL);
 
   // Now make sure we have the right user name.
   EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedUsername());
 }
 
 TEST_F(SigninManagerTest, SignOutClientLogin) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   manager_->StartSignIn("username", "password", std::string(), std::string());
   SimulateValidResponseClientLogin(false);
-  manager_->OnClientLoginSuccess(credentials_);
+  manager_->OnClientLoginSuccess(credentials());
 
   EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedUsername());
   manager_->SignOut();
@@ -498,13 +455,13 @@
   manager_->Shutdown();
   manager_.reset(new SigninManager(
       scoped_ptr<SigninManagerDelegate>(
-          new ChromeSigninManagerDelegate(profile_.get()))));
-  manager_->Initialize(profile_.get(), NULL);
+          new ChromeSigninManagerDelegate(profile()))));
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 }
 
 TEST_F(SigninManagerTest, SignInFailureClientLogin) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   manager_->StartSignIn("username", "password", std::string(), std::string());
   GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
   manager_->OnClientLoginFailure(error);
@@ -518,13 +475,13 @@
   manager_->Shutdown();
   manager_.reset(new SigninManager(
       scoped_ptr<SigninManagerDelegate>(
-          new ChromeSigninManagerDelegate(profile_.get()))));
-  manager_->Initialize(profile_.get(), NULL);
+          new ChromeSigninManagerDelegate(profile()))));
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 }
 
 TEST_F(SigninManagerTest, ProvideSecondFactorSuccess) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   manager_->StartSignIn("username", "password", std::string(), std::string());
   GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR);
   manager_->OnClientLoginFailure(error);
@@ -543,7 +500,7 @@
 }
 
 TEST_F(SigninManagerTest, ProvideSecondFactorFailure) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   manager_->StartSignIn("username", "password", std::string(), std::string());
   GoogleServiceAuthError error1(GoogleServiceAuthError::TWO_FACTOR);
   manager_->OnClientLoginFailure(error1);
@@ -573,7 +530,7 @@
 }
 
 TEST_F(SigninManagerTest, SignOutMidConnect) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   manager_->StartSignIn("username", "password", std::string(), std::string());
   EXPECT_EQ("username", manager_->GetUsernameForAuthInProgress());
   manager_->SignOut();
@@ -585,7 +542,7 @@
 }
 
 TEST_F(SigninManagerTest, SignOutWhileProhibited) {
-  manager_->Initialize(profile_.get(), NULL);
+  manager_->Initialize(profile(), NULL);
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->SetAuthenticatedUsername("user@gmail.com");
@@ -617,7 +574,7 @@
 TEST_F(SigninManagerTest, Prohibited) {
   g_browser_process->local_state()->SetString(
       prefs::kGoogleServicesUsernamePattern, ".*@google.com");
-  manager_->Initialize(profile_.get(), g_browser_process->local_state());
+  manager_->Initialize(profile(), g_browser_process->local_state());
   EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
   EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
   EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
@@ -630,7 +587,7 @@
   // the admin entered ".*@google.com").
   g_browser_process->local_state()->SetString(
       prefs::kGoogleServicesUsernamePattern, "*@google.com");
-  manager_->Initialize(profile_.get(), g_browser_process->local_state());
+  manager_->Initialize(profile(), g_browser_process->local_state());
   EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
   EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
   EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
@@ -639,19 +596,19 @@
 }
 
 TEST_F(SigninManagerTest, ProhibitedAtStartup) {
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                  "monkey@invalid.com");
+  profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                   "monkey@invalid.com");
   g_browser_process->local_state()->SetString(
       prefs::kGoogleServicesUsernamePattern, ".*@google.com");
-  manager_->Initialize(profile_.get(), g_browser_process->local_state());
+  manager_->Initialize(profile(), g_browser_process->local_state());
   // Currently signed in user is prohibited by policy, so should be signed out.
   EXPECT_EQ("", manager_->GetAuthenticatedUsername());
 }
 
 TEST_F(SigninManagerTest, ProhibitedAfterStartup) {
   std::string user("monkey@invalid.com");
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, user);
-  manager_->Initialize(profile_.get(), g_browser_process->local_state());
+  profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername, user);
+  manager_->Initialize(profile(), g_browser_process->local_state());
   EXPECT_EQ(user, manager_->GetAuthenticatedUsername());
   // Update the profile - user should be signed out.
   g_browser_process->local_state()->SetString(
@@ -660,9 +617,9 @@
 }
 
 TEST_F(SigninManagerTest, ExternalSignIn) {
-  manager_->Initialize(profile_.get(), g_browser_process->local_state());
+  manager_->Initialize(profile(), g_browser_process->local_state());
   EXPECT_EQ("",
-            profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
+            profile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
   EXPECT_EQ("", manager_->GetAuthenticatedUsername());
   EXPECT_EQ(0u, google_login_success_.size());
 
@@ -670,6 +627,6 @@
   EXPECT_EQ(1u, google_login_success_.size());
   EXPECT_EQ(0u, google_login_failure_.size());
   EXPECT_EQ("external@example.com",
-            profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
+            profile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
   EXPECT_EQ("external@example.com", manager_->GetAuthenticatedUsername());
 }
diff --git a/chrome/browser/signin/token_service_unittest.cc b/chrome/browser/signin/token_service_unittest.cc
index 50dc429..0617ae5 100644
--- a/chrome/browser/signin/token_service_unittest.cc
+++ b/chrome/browser/signin/token_service_unittest.cc
@@ -9,8 +9,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/run_loop.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/browser/webdata/token_web_data.h"
@@ -20,8 +19,6 @@
 #include "google_apis/gaia/mock_url_fetcher_factory.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 
-using content::BrowserThread;
-
 TokenAvailableTracker::TokenAvailableTracker() {}
 
 TokenAvailableTracker::~TokenAvailableTracker() {}
@@ -52,10 +49,7 @@
   }
 }
 
-TokenServiceTestHarness::TokenServiceTestHarness()
-    : ui_thread_(BrowserThread::UI, &message_loop_),
-      db_thread_(BrowserThread::DB) {
-}
+TokenServiceTestHarness::TokenServiceTestHarness() {}
 
 TokenServiceTestHarness::~TokenServiceTestHarness() {}
 
@@ -70,12 +64,13 @@
   oauth_token_ = "oauth";
   oauth_secret_ = "secret";
 
-  ASSERT_TRUE(db_thread_.Start());
-
   profile_.reset(new TestingProfile());
   profile_->CreateWebDataService();
 
-  WaitForDBLoadCompletion();
+  // Force the loading of the WebDataService.
+  TokenWebData::FromBrowserContext(profile_.get());
+  base::RunLoop().RunUntilIdle();
+
   service_ = TokenServiceFactory::GetForProfile(profile_.get());
 
   success_tracker_.ListenFor(chrome::NOTIFICATION_TOKEN_AVAILABLE,
@@ -83,103 +78,78 @@
   failure_tracker_.ListenFor(chrome::NOTIFICATION_TOKEN_REQUEST_FAILED,
                              content::Source<TokenService>(service_));
 
-  service_->Initialize("test", profile_.get());
+  service()->Initialize("test", profile_.get());
 }
 
 void TokenServiceTestHarness::TearDown() {
-  // You have to destroy the profile before the db_thread_ stops.
-  if (profile_.get()) {
-    profile_.reset(NULL);
-  }
-  // Schedule another task on the DB thread to notify us that it's safe to
-  // carry on with the test.
-  base::WaitableEvent done(false, false);
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
-  base::MessageLoop::current()->PostTask(FROM_HERE,
-                                         base::MessageLoop::QuitClosure());
-  base::MessageLoop::current()->Run();
-  db_thread_.Stop();
+  // You have to destroy the profile before the threads are shut down.
+  profile_.reset();
 }
 
-void TokenServiceTestHarness::WaitForDBLoadCompletion() {
-  // Force the loading of the WebDataService.
-  TokenWebData::FromBrowserContext(profile_.get());
-
-  // The WebDB does all work on the DB thread. This will add an event
-  // to the end of the DB thread, so when we reach this task, all DB
-  // operations should be complete.
-  base::WaitableEvent done(false, false);
-  BrowserThread::PostTask(
-      BrowserThread::DB,
-      FROM_HERE,
-      base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
-  done.Wait();
-
-  // Notifications should be returned from the DB thread onto the UI thread.
-  message_loop_.RunUntilIdle();
+void TokenServiceTestHarness::UpdateCredentialsOnService() {
+  service()->UpdateCredentials(credentials_);
 }
 
 class TokenServiceTest : public TokenServiceTestHarness {
  public:
   virtual void SetUp() {
     TokenServiceTestHarness::SetUp();
-    service_->UpdateCredentials(credentials_);
+    UpdateCredentialsOnService();
   }
  protected:
   void TestLoadSingleToken(
       std::map<std::string, std::string>* db_tokens,
       std::map<std::string, std::string>* memory_tokens,
-      const std::string& service) {
-    std::string token = service + "_token";
-    (*db_tokens)[service] = token;
-    size_t prev_success_size = success_tracker_.size();
-    service_->LoadTokensIntoMemory(*db_tokens, memory_tokens);
+      const std::string& service_name) {
+    std::string token = service_name + "_token";
+    (*db_tokens)[service_name] = token;
+    size_t prev_success_size = success_tracker()->size();
+    service()->LoadTokensIntoMemory(*db_tokens, memory_tokens);
 
     // Check notification.
-    EXPECT_EQ(prev_success_size + 1, success_tracker_.size());
-    TokenService::TokenAvailableDetails details = success_tracker_.details();
-    EXPECT_EQ(details.service(), service);
+    EXPECT_EQ(prev_success_size + 1, success_tracker()->size());
+    TokenService::TokenAvailableDetails details = success_tracker()->details();
+    EXPECT_EQ(details.service(), service_name);
     EXPECT_EQ(details.token(), token);
     // Check memory tokens.
-    EXPECT_EQ(1U, memory_tokens->count(service));
-    EXPECT_EQ((*memory_tokens)[service], token);
+    EXPECT_EQ(1U, memory_tokens->count(service_name));
+    EXPECT_EQ((*memory_tokens)[service_name], token);
   }
 };
 
 TEST_F(TokenServiceTest, SanityCheck) {
-  EXPECT_FALSE(service_->HasTokenForService("nonexistent service"));
-  EXPECT_FALSE(service_->TokensLoadedFromDB());
+  EXPECT_FALSE(service()->HasTokenForService("nonexistent service"));
+  EXPECT_FALSE(service()->TokensLoadedFromDB());
 }
 
 TEST_F(TokenServiceTest, NoToken) {
-  EXPECT_FALSE(service_->HasTokenForService("nonexistent service"));
-  EXPECT_EQ(service_->GetTokenForService("nonexistent service"), std::string());
+  EXPECT_FALSE(service()->HasTokenForService("nonexistent service"));
+  EXPECT_EQ(service()->GetTokenForService("nonexistent service"),
+            std::string());
 }
 
 TEST_F(TokenServiceTest, NotificationSuccess) {
-  EXPECT_EQ(0U, success_tracker_.size());
-  EXPECT_EQ(0U, failure_tracker_.size());
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
-  EXPECT_EQ(1U, success_tracker_.size());
-  EXPECT_EQ(0U, failure_tracker_.size());
+  EXPECT_EQ(0U, success_tracker()->size());
+  EXPECT_EQ(0U, failure_tracker()->size());
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
+  EXPECT_EQ(1U, success_tracker()->size());
+  EXPECT_EQ(0U, failure_tracker()->size());
 
-  TokenService::TokenAvailableDetails details = success_tracker_.details();
+  TokenService::TokenAvailableDetails details = success_tracker()->details();
   // MSVC doesn't like this comparison as EQ.
   EXPECT_TRUE(details.service() == GaiaConstants::kSyncService);
   EXPECT_EQ(details.token(), "token");
 }
 
 TEST_F(TokenServiceTest, NotificationOAuthLoginTokenSuccess) {
-  EXPECT_EQ(0U, success_tracker_.size());
-  EXPECT_EQ(0U, failure_tracker_.size());
-  service_->OnClientOAuthSuccess(
+  EXPECT_EQ(0U, success_tracker()->size());
+  EXPECT_EQ(0U, failure_tracker()->size());
+  service()->OnClientOAuthSuccess(
       GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600));
-  EXPECT_EQ(1U, success_tracker_.size());
-  EXPECT_EQ(0U, failure_tracker_.size());
+  EXPECT_EQ(1U, success_tracker()->size());
+  EXPECT_EQ(0U, failure_tracker()->size());
 
-  TokenService::TokenAvailableDetails details = success_tracker_.details();
+  TokenService::TokenAvailableDetails details = success_tracker()->details();
   // MSVC doesn't like this comparison as EQ.
   EXPECT_TRUE(details.service() ==
       GaiaConstants::kGaiaOAuth2LoginRefreshToken);
@@ -187,28 +157,30 @@
 }
 
 TEST_F(TokenServiceTest, NotificationFailed) {
-  EXPECT_EQ(0U, success_tracker_.size());
-  EXPECT_EQ(0U, failure_tracker_.size());
+  EXPECT_EQ(0U, success_tracker()->size());
+  EXPECT_EQ(0U, failure_tracker()->size());
   GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
-  service_->OnIssueAuthTokenFailure(GaiaConstants::kSyncService, error);
-  EXPECT_EQ(0U, success_tracker_.size());
-  EXPECT_EQ(1U, failure_tracker_.size());
+  service()->OnIssueAuthTokenFailure(GaiaConstants::kSyncService, error);
+  EXPECT_EQ(0U, success_tracker()->size());
+  EXPECT_EQ(1U, failure_tracker()->size());
 
-  TokenService::TokenRequestFailedDetails details = failure_tracker_.details();
+  TokenService::TokenRequestFailedDetails details =
+      failure_tracker()->details();
   // MSVC doesn't like this comparison as EQ.
   EXPECT_TRUE(details.service() == GaiaConstants::kSyncService);
   EXPECT_TRUE(details.error() == error);  // Struct has no print function.
 }
 
 TEST_F(TokenServiceTest, NotificationOAuthLoginTokenFailed) {
-  EXPECT_EQ(0U, success_tracker_.size());
-  EXPECT_EQ(0U, failure_tracker_.size());
+  EXPECT_EQ(0U, success_tracker()->size());
+  EXPECT_EQ(0U, failure_tracker()->size());
   GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
-  service_->OnClientOAuthFailure(error);
-  EXPECT_EQ(0U, success_tracker_.size());
-  EXPECT_EQ(1U, failure_tracker_.size());
+  service()->OnClientOAuthFailure(error);
+  EXPECT_EQ(0U, success_tracker()->size());
+  EXPECT_EQ(1U, failure_tracker()->size());
 
-  TokenService::TokenRequestFailedDetails details = failure_tracker_.details();
+  TokenService::TokenRequestFailedDetails details =
+      failure_tracker()->details();
 
   // MSVC doesn't like this comparison as EQ.
   EXPECT_TRUE(details.service() ==
@@ -217,69 +189,73 @@
 }
 
 TEST_F(TokenServiceTest, OnTokenSuccessUpdate) {
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
-  EXPECT_EQ(service_->GetTokenForService(GaiaConstants::kSyncService), "token");
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_EQ(service()->GetTokenForService(GaiaConstants::kSyncService),
+            "token");
 
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token2");
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
-  EXPECT_EQ(service_->GetTokenForService(GaiaConstants::kSyncService),
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token2");
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_EQ(service()->GetTokenForService(GaiaConstants::kSyncService),
             "token2");
 
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, std::string());
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
-  EXPECT_EQ(service_->GetTokenForService(GaiaConstants::kSyncService), "");
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService,
+                                     std::string());
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_EQ(service()->GetTokenForService(GaiaConstants::kSyncService), "");
 }
 
 TEST_F(TokenServiceTest, OnOAuth2LoginTokenSuccessUpdate) {
-  EXPECT_FALSE(service_->HasOAuthLoginToken());
+  EXPECT_FALSE(service()->HasOAuthLoginToken());
 
-  service_->OnClientOAuthSuccess(
+  service()->OnClientOAuthSuccess(
       GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600));
-  EXPECT_TRUE(service_->HasOAuthLoginToken());
-  EXPECT_EQ(service_->GetOAuth2LoginRefreshToken(), "rt1");
+  EXPECT_TRUE(service()->HasOAuthLoginToken());
+  EXPECT_EQ(service()->GetOAuth2LoginRefreshToken(), "rt1");
 
-  service_->OnClientOAuthSuccess(
+  service()->OnClientOAuthSuccess(
       GaiaAuthConsumer::ClientOAuthResult("rt2", "at2", 3600));
-  EXPECT_TRUE(service_->HasOAuthLoginToken());
-  EXPECT_EQ(service_->GetOAuth2LoginRefreshToken(), "rt2");
+  EXPECT_TRUE(service()->HasOAuthLoginToken());
+  EXPECT_EQ(service()->GetOAuth2LoginRefreshToken(), "rt2");
 
-  service_->OnClientOAuthSuccess(
+  service()->OnClientOAuthSuccess(
       GaiaAuthConsumer::ClientOAuthResult("rt3", "at3", 3600));
-  EXPECT_TRUE(service_->HasOAuthLoginToken());
-  EXPECT_EQ(service_->GetOAuth2LoginRefreshToken(), "rt3");
+  EXPECT_TRUE(service()->HasOAuthLoginToken());
+  EXPECT_EQ(service()->GetOAuth2LoginRefreshToken(), "rt3");
 }
 
 TEST_F(TokenServiceTest, OnTokenSuccess) {
   // Don't "start fetching", just go ahead and issue the callback.
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
   // Gaia returns the entire result as the token so while this is a shared
   // result with ClientLogin, it doesn't matter, we should still get it back.
-  EXPECT_EQ(service_->GetTokenForService(GaiaConstants::kSyncService), "token");
+  EXPECT_EQ(service()->GetTokenForService(GaiaConstants::kSyncService),
+            "token");
 }
 
 TEST_F(TokenServiceTest, Reset) {
   net::TestURLFetcherFactory factory;
-  service_->StartFetchingTokens();
+  service()->StartFetchingTokens();
   // You have to call delegates by hand with the test fetcher,
   // Let's pretend only one returned.
 
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "eraseme");
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
-  EXPECT_EQ(service_->GetTokenForService(GaiaConstants::kSyncService),
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "eraseme");
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_EQ(service()->GetTokenForService(GaiaConstants::kSyncService),
             "eraseme");
 
-  service_->ResetCredentialsInMemory();
-  EXPECT_FALSE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  service()->ResetCredentialsInMemory();
+  EXPECT_FALSE(service()->HasTokenForService(GaiaConstants::kSyncService));
 
   // Now start using it again.
-  service_->UpdateCredentials(credentials_);
-  service_->StartFetchingTokens();
+  UpdateCredentialsOnService();
+  service()->StartFetchingTokens();
 
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
 
-  EXPECT_EQ(service_->GetTokenForService(GaiaConstants::kSyncService), "token");
+  EXPECT_EQ(service()->GetTokenForService(GaiaConstants::kSyncService),
+            "token");
 }
 
 TEST_F(TokenServiceTest, FullIntegration) {
@@ -288,17 +264,17 @@
   {
     MockURLFetcherFactory<MockFetcher> factory;
     factory.set_results(result);
-    EXPECT_FALSE(service_->HasTokenForService(GaiaConstants::kSyncService));
-    service_->StartFetchingTokens();
+    EXPECT_FALSE(service()->HasTokenForService(GaiaConstants::kSyncService));
+    service()->StartFetchingTokens();
   }
 
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
   // Gaia returns the entire result as the token so while this is a shared
   // result with ClientLogin, it doesn't matter, we should still get it back.
-  EXPECT_EQ(service_->GetTokenForService(GaiaConstants::kSyncService), result);
+  EXPECT_EQ(service()->GetTokenForService(GaiaConstants::kSyncService), result);
 
-  service_->ResetCredentialsInMemory();
-  EXPECT_FALSE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  service()->ResetCredentialsInMemory();
+  EXPECT_FALSE(service()->HasTokenForService(GaiaConstants::kSyncService));
 }
 
 TEST_F(TokenServiceTest, LoadTokensIntoMemoryBasic) {
@@ -306,11 +282,11 @@
   std::map<std::string, std::string> db_tokens;
   std::map<std::string, std::string> memory_tokens;
 
-  EXPECT_FALSE(service_->TokensLoadedFromDB());
-  service_->LoadTokensIntoMemory(db_tokens, &memory_tokens);
+  EXPECT_FALSE(service()->TokensLoadedFromDB());
+  service()->LoadTokensIntoMemory(db_tokens, &memory_tokens);
   EXPECT_TRUE(db_tokens.empty());
   EXPECT_TRUE(memory_tokens.empty());
-  EXPECT_EQ(0U, success_tracker_.size());
+  EXPECT_EQ(0U, success_tracker()->size());
 
   std::vector<std::string> services;
   TokenService::GetServiceNames(&services);
@@ -331,80 +307,80 @@
 
   db_tokens["ignore"] = "token";
 
-  service_->LoadTokensIntoMemory(db_tokens, &memory_tokens);
+  service()->LoadTokensIntoMemory(db_tokens, &memory_tokens);
   EXPECT_TRUE(memory_tokens.empty());
   db_tokens[GaiaConstants::kSyncService] = "pepper";
 
-  service_->LoadTokensIntoMemory(db_tokens, &memory_tokens);
+  service()->LoadTokensIntoMemory(db_tokens, &memory_tokens);
   EXPECT_EQ(1U, memory_tokens.count(GaiaConstants::kSyncService));
   EXPECT_EQ(memory_tokens[GaiaConstants::kSyncService], "pepper");
-  EXPECT_EQ(1U, success_tracker_.size());
-  success_tracker_.Reset();
+  EXPECT_EQ(1U, success_tracker()->size());
+  success_tracker()->Reset();
 
   // SyncService token is already in memory. Pretend we got it off
   // the disk as well, but an older token.
   db_tokens[GaiaConstants::kSyncService] = "ignoreme";
-  service_->LoadTokensIntoMemory(db_tokens, &memory_tokens);
+  service()->LoadTokensIntoMemory(db_tokens, &memory_tokens);
 
   EXPECT_EQ(1U, memory_tokens.size());
-  EXPECT_EQ(0U, success_tracker_.size());
+  EXPECT_EQ(0U, success_tracker()->size());
   EXPECT_EQ(1U, memory_tokens.count(GaiaConstants::kSyncService));
   EXPECT_EQ(memory_tokens[GaiaConstants::kSyncService], "pepper");
 }
 
 TEST_F(TokenServiceTest, WebDBLoadIntegration) {
-  service_->LoadTokensFromDB();
-  WaitForDBLoadCompletion();
-  EXPECT_TRUE(service_->TokensLoadedFromDB());
-  EXPECT_EQ(0U, success_tracker_.size());
+  service()->LoadTokensFromDB();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(service()->TokensLoadedFromDB());
+  EXPECT_EQ(0U, success_tracker()->size());
 
   // Should result in DB write.
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
-  EXPECT_EQ(1U, success_tracker_.size());
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
+  EXPECT_EQ(1U, success_tracker()->size());
 
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
   // Clean slate.
-  service_->ResetCredentialsInMemory();
-  success_tracker_.Reset();
-  EXPECT_FALSE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  service()->ResetCredentialsInMemory();
+  success_tracker()->Reset();
+  EXPECT_FALSE(service()->HasTokenForService(GaiaConstants::kSyncService));
 
-  service_->LoadTokensFromDB();
-  WaitForDBLoadCompletion();
+  service()->LoadTokensFromDB();
+  base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(1U, success_tracker_.size());
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_EQ(1U, success_tracker()->size());
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
 }
 
 TEST_F(TokenServiceTest, MultipleLoadResetIntegration) {
   // Should result in DB write.
-  service_->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
-  service_->ResetCredentialsInMemory();
-  success_tracker_.Reset();
-  EXPECT_FALSE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  service()->OnIssueAuthTokenSuccess(GaiaConstants::kSyncService, "token");
+  service()->ResetCredentialsInMemory();
+  success_tracker()->Reset();
+  EXPECT_FALSE(service()->HasTokenForService(GaiaConstants::kSyncService));
 
-  EXPECT_FALSE(service_->TokensLoadedFromDB());
-  service_->LoadTokensFromDB();
-  WaitForDBLoadCompletion();
-  EXPECT_TRUE(service_->TokensLoadedFromDB());
+  EXPECT_FALSE(service()->TokensLoadedFromDB());
+  service()->LoadTokensFromDB();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(service()->TokensLoadedFromDB());
 
-  service_->LoadTokensFromDB();  // Should do nothing.
-  WaitForDBLoadCompletion();
-  EXPECT_TRUE(service_->TokensLoadedFromDB());
+  service()->LoadTokensFromDB();  // Should do nothing.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(service()->TokensLoadedFromDB());
 
-  EXPECT_EQ(1U, success_tracker_.size());
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_EQ(1U, success_tracker()->size());
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
 
   // Reset it one more time so there's no surprises.
-  service_->ResetCredentialsInMemory();
-  EXPECT_FALSE(service_->TokensLoadedFromDB());
-  success_tracker_.Reset();
+  service()->ResetCredentialsInMemory();
+  EXPECT_FALSE(service()->TokensLoadedFromDB());
+  success_tracker()->Reset();
 
-  service_->LoadTokensFromDB();
-  WaitForDBLoadCompletion();
-  EXPECT_TRUE(service_->TokensLoadedFromDB());
+  service()->LoadTokensFromDB();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(service()->TokensLoadedFromDB());
 
-  EXPECT_EQ(1U, success_tracker_.size());
-  EXPECT_TRUE(service_->HasTokenForService(GaiaConstants::kSyncService));
+  EXPECT_EQ(1U, success_tracker()->size());
+  EXPECT_TRUE(service()->HasTokenForService(GaiaConstants::kSyncService));
 }
 
 #ifndef NDEBUG
@@ -415,14 +391,14 @@
     CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kSetToken, "my_service:my_value");
     TokenServiceTestHarness::SetUp();
-    service_->UpdateCredentials(credentials_);
+    UpdateCredentialsOnService();
 
     *CommandLine::ForCurrentProcess() = original_cl;
   }
 };
 
 TEST_F(TokenServiceCommandLineTest, TestValueOverride) {
-  EXPECT_TRUE(service_->HasTokenForService("my_service"));
-  EXPECT_EQ("my_value", service_->GetTokenForService("my_service"));
+  EXPECT_TRUE(service()->HasTokenForService("my_service"));
+  EXPECT_EQ("my_value", service()->GetTokenForService("my_service"));
 }
 #endif   // ifndef NDEBUG
diff --git a/chrome/browser/signin/token_service_unittest.h b/chrome/browser/signin/token_service_unittest.h
index a333d7c..34aa043 100644
--- a/chrome/browser/signin/token_service_unittest.h
+++ b/chrome/browser/signin/token_service_unittest.h
@@ -13,7 +13,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_notification_tracker.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -56,19 +56,24 @@
 };
 
 class TokenServiceTestHarness : public testing::Test {
- public:
+ protected:
   TokenServiceTestHarness();
   virtual ~TokenServiceTestHarness();
 
   virtual void SetUp() OVERRIDE;
-
   virtual void TearDown() OVERRIDE;
 
-  void WaitForDBLoadCompletion();
+  void UpdateCredentialsOnService();
+  TestingProfile* profile() const { return profile_.get(); }
+  TokenService* service() const { return service_; }
+  const GaiaAuthConsumer::ClientLoginResult& credentials() const {
+    return credentials_;
+  }
+  TokenAvailableTracker* success_tracker() { return &success_tracker_; }
+  TokenFailedTracker* failure_tracker() { return &failure_tracker_; }
 
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;  // Mostly so DCHECKS pass.
-  content::TestBrowserThread db_thread_;  // WDS on here
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
 
   TokenService* service_;
   TokenAvailableTracker success_tracker_;
diff --git a/chrome/browser/signin/ubertoken_fetcher_unittest.cc b/chrome/browser/signin/ubertoken_fetcher_unittest.cc
index eddb39a..ec752c7 100644
--- a/chrome/browser/signin/ubertoken_fetcher_unittest.cc
+++ b/chrome/browser/signin/ubertoken_fetcher_unittest.cc
@@ -11,8 +11,6 @@
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 class MockUbertokenConsumer : public UbertokenConsumer {
  public:
   MockUbertokenConsumer()
@@ -43,8 +41,8 @@
  public:
   virtual void SetUp() OVERRIDE {
     TokenServiceTestHarness::SetUp();
-    service_->UpdateCredentials(credentials_);
-    fetcher_.reset(new UbertokenFetcher(profile_.get(), &consumer_));
+    UpdateCredentialsOnService();
+    fetcher_.reset(new UbertokenFetcher(profile(), &consumer_));
   }
 
   virtual void TearDown() OVERRIDE {
@@ -61,10 +59,10 @@
   fetcher_->StartFetchingToken();
   TokenService::TokenAvailableDetails
       details(GaiaConstants::kGaiaOAuth2LoginRefreshToken, "refreshToken");
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                 "refreshToken");
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
   fetcher_->Observe(chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                    content::Source<TokenService>(service_),
+                    content::Source<TokenService>(service()),
                     content::Details<const TokenService::TokenAvailableDetails>(
                         &details));
   fetcher_->OnRefreshTokenResponse("accessToken", 3600);
@@ -75,8 +73,8 @@
 }
 
 TEST_F(UbertokenFetcherTest, TestSuccessWithRefreshToken) {
-  service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
-                                 "refreshToken");
+  service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+                                   "refreshToken");
   fetcher_->StartFetchingToken();
   fetcher_->OnRefreshTokenResponse("accessToken", 3600);
   fetcher_->OnUberAuthTokenSuccess("uberToken");
@@ -93,7 +91,7 @@
       details(GaiaConstants::kGaiaOAuth2LoginRefreshToken, error);
   fetcher_->Observe(
       chrome::NOTIFICATION_TOKEN_REQUEST_FAILED,
-      content::Source<TokenService>(service_),
+      content::Source<TokenService>(service()),
       content::Details<const TokenService::TokenRequestFailedDetails>(
           &details));
   EXPECT_EQ(1, consumer_.nb_error_);
diff --git a/chrome/browser/speech/speech_recognition_bubble_controller_unittest.cc b/chrome/browser/speech/speech_recognition_bubble_controller_unittest.cc
index c428e1d..f1380c9 100644
--- a/chrome/browser/speech/speech_recognition_bubble_controller_unittest.cc
+++ b/chrome/browser/speech/speech_recognition_bubble_controller_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/speech/speech_recognition_bubble_controller.h"
 #include "chrome/browser/ui/browser.h"
@@ -79,7 +80,6 @@
  public:
   SpeechRecognitionBubbleControllerTest()
       : BrowserWithTestWindowTest(),
-        io_thread_(BrowserThread::IO),  // constructs a new thread and loop
         cancel_clicked_(false),
         try_again_clicked_(false),
         focus_changed_(false),
@@ -103,14 +103,12 @@
     } else if (button == SpeechRecognitionBubble::BUTTON_TRY_AGAIN) {
       try_again_clicked_ = true;
     }
-    message_loop()->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   virtual void InfoBubbleFocusChanged(int session_id) OVERRIDE {
     VLOG(1) << "Received InfoBubbleFocusChanged";
     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
     focus_changed_ = true;
-    message_loop()->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   // testing::Test methods.
@@ -118,12 +116,10 @@
     BrowserWithTestWindowTest::SetUp();
     SpeechRecognitionBubble::set_factory(
         &SpeechRecognitionBubbleControllerTest::CreateBubble);
-    io_thread_.Start();
   }
 
   virtual void TearDown() {
     SpeechRecognitionBubble::set_factory(NULL);
-    io_thread_.Stop();
     BrowserWithTestWindowTest::TearDown();
   }
 
@@ -157,9 +153,6 @@
   }
 
  protected:
-  // The main thread of the test is marked as the IO thread and we create a new
-  // one for the UI thread.
-  content::TestBrowserThread io_thread_;
   bool cancel_clicked_;
   bool try_again_clicked_;
   bool focus_changed_;
@@ -184,7 +177,7 @@
       MockSpeechRecognitionBubble::BUBBLE_TEST_FOCUS_CHANGED);
 
   controller_->CreateBubble(kBubbleSessionId, 1, 1, gfx::Rect(1, 1));
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(focus_changed_);
   EXPECT_FALSE(cancel_clicked_);
   EXPECT_FALSE(try_again_clicked_);
@@ -198,7 +191,7 @@
       MockSpeechRecognitionBubble::BUBBLE_TEST_CLICK_CANCEL);
 
   controller_->CreateBubble(kBubbleSessionId, 1, 1, gfx::Rect(1, 1));
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(cancel_clicked_);
   EXPECT_FALSE(try_again_clicked_);
   EXPECT_FALSE(focus_changed_);
@@ -212,7 +205,7 @@
       MockSpeechRecognitionBubble::BUBBLE_TEST_CLICK_TRY_AGAIN);
 
   controller_->CreateBubble(kBubbleSessionId, 1, 1, gfx::Rect(1, 1));
-  base::MessageLoop::current()->Run();
+  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(cancel_clicked_);
   EXPECT_TRUE(try_again_clicked_);
   EXPECT_FALSE(focus_changed_);
diff --git a/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc b/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
index c18ce33..e20932d 100644
--- a/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
+++ b/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
@@ -5,8 +5,6 @@
 #include <vector>
 
 #include "base/file_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/histogram.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/strings/string_number_conversions.h"
@@ -17,7 +15,8 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/spellcheck_common.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/url_request/test_url_fetcher_factory.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_data.h"
 #include "sync/api/sync_error_factory.h"
@@ -29,7 +28,6 @@
 using base::HistogramBase;
 using base::HistogramSamples;
 using base::StatisticsRecorder;
-using content::BrowserThread;
 using chrome::spellcheck_common::WordList;
 using chrome::spellcheck_common::WordSet;
 
@@ -60,24 +58,14 @@
 
 class SpellcheckCustomDictionaryTest : public testing::Test {
  protected:
-  SpellcheckCustomDictionaryTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_),
-        profile_(new TestingProfile) {
-  }
-
   virtual void SetUp() OVERRIDE {
     // Use SetTestingFactoryAndUse to force creation and initialization.
     SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-        profile_.get(), &BuildSpellcheckService);
+        &profile_, &BuildSpellcheckService);
 
     StatisticsRecorder::Initialize();
   }
 
-  virtual void TearDown() OVERRIDE {
-    base::MessageLoop::current()->RunUntilIdle();
-  }
-
   // A wrapper around SpellcheckCustomDictionary::LoadDictionaryFile private
   // function to avoid a large number of FRIEND_TEST declarations in
   // SpellcheckCustomDictionary.
@@ -112,11 +100,10 @@
     return dictionary.Apply(change);
   }
 
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
-  scoped_ptr<TestingProfile> profile_;
+  TestingProfile profile_;
+  net::TestURLFetcherFactory fetcher_factory_;
 };
 
 // A wrapper around SpellcheckCustomDictionary that does not own the wrapped
@@ -187,7 +174,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, SaveAndLoad) {
   base::FilePath path =
-      profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
+      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
   WordList loaded_custom_words = LoadDictionaryFile(path);
 
   // The custom word list should be empty now.
@@ -217,7 +204,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, MultiProfile) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -251,7 +238,7 @@
 // Legacy empty dictionary should be converted to new format empty dictionary.
 TEST_F(SpellcheckCustomDictionaryTest, LegacyEmptyDictionaryShouldBeConverted) {
   base::FilePath path =
-      profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
+      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
 
   std::string content;
   file_util::WriteFile(path, content.c_str(), content.length());
@@ -264,7 +251,7 @@
 TEST_F(SpellcheckCustomDictionaryTest,
        LegacyDictionaryWithTwoWordsShouldBeConverted) {
   base::FilePath path =
-      profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
+      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
 
   std::string content = "foo\nbar\nfoo\n";
   file_util::WriteFile(path, content.c_str(), content.length());
@@ -280,7 +267,7 @@
 TEST_F(SpellcheckCustomDictionaryTest,
        IllegalWordsShouldBeRemovedFromDictionary) {
   base::FilePath path =
-      profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
+      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
 
   std::string content = "foo\n foo bar \n\n \nbar\n"
       "01234567890123456789012345678901234567890123456789"
@@ -299,7 +286,7 @@
 // previous version should be reloaded.
 TEST_F(SpellcheckCustomDictionaryTest, CorruptedWriteShouldBeRecovered) {
   base::FilePath path =
-      profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
+      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
 
   std::string content = "foo\nbar";
   file_util::WriteFile(path, content.c_str(), content.length());
@@ -324,7 +311,7 @@
        GetAllSyncDataAccuratelyReflectsDictionaryState) {
   SpellcheckCustomDictionary* dictionary =
       SpellcheckServiceFactory::GetForProfile(
-          profile_.get())->GetCustomDictionary();
+          &profile_)->GetCustomDictionary();
 
   syncer::SyncDataList data = dictionary->GetAllSyncData(syncer::DICTIONARY);
   EXPECT_TRUE(data.empty());
@@ -354,7 +341,7 @@
 TEST_F(SpellcheckCustomDictionaryTest, GetAllSyncDataHasLimit) {
   SpellcheckCustomDictionary* dictionary =
       SpellcheckServiceFactory::GetForProfile(
-          profile_.get())->GetCustomDictionary();
+          &profile_)->GetCustomDictionary();
 
   SpellcheckCustomDictionary::Change change;
   for (size_t i = 0;
@@ -389,7 +376,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, ProcessSyncChanges) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* dictionary =
       spellcheck_service->GetCustomDictionary();
 
@@ -460,7 +447,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, MergeDataAndStartSyncing) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -506,7 +493,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigBeforeSyncing) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -549,7 +536,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -601,7 +588,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, ServerTooBig) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -652,7 +639,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -698,7 +685,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -749,7 +736,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -787,7 +774,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -834,7 +821,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -881,7 +868,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionaryLoadNotification) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
 
@@ -902,7 +889,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionaryAddWordNotification) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
 
@@ -922,7 +909,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionaryRemoveWordNotification) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
 
@@ -945,7 +932,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncNotification) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   TestingProfile profile2;
@@ -1006,7 +993,7 @@
   // Upload the maximum number of words to the sync server.
   {
     SpellcheckService* spellcheck_service =
-        SpellcheckServiceFactory::GetForProfile(profile_.get());
+        SpellcheckServiceFactory::GetForProfile(&profile_);
     SpellcheckCustomDictionary* custom_dictionary =
         spellcheck_service->GetCustomDictionary();
 
@@ -1092,7 +1079,7 @@
 
   // Load the dictionary which should be empty.
   base::FilePath path =
-      profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
+      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
   WordList loaded_custom_words = LoadDictionaryFile(path);
   EXPECT_EQ(0u, loaded_custom_words.size());
 
@@ -1125,7 +1112,7 @@
 
 TEST_F(SpellcheckCustomDictionaryTest, HasWord) {
   SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile_.get());
+      SpellcheckServiceFactory::GetForProfile(&profile_);
   SpellcheckCustomDictionary* custom_dictionary =
       spellcheck_service->GetCustomDictionary();
   OnLoaded(*custom_dictionary, WordList());
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc b/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
index d0fb26f..8504256 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
@@ -9,7 +9,7 @@
 #include "chrome/common/spellcheck_marker.h"
 #include "chrome/common/spellcheck_messages.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "ipc/ipc_message.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -17,7 +17,6 @@
  public:
   TestingSpellCheckMessageFilter()
       : SpellCheckMessageFilter(0),
-        ui_thread_(content::BrowserThread::UI, &message_loop_),
         spellcheck_(new SpellcheckService(&profile_)) {}
 
   virtual bool Send(IPC::Message* message) OVERRIDE {
@@ -46,8 +45,7 @@
  private:
   virtual ~TestingSpellCheckMessageFilter() {}
 
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   scoped_ptr<SpellcheckService> spellcheck_;
 
diff --git a/chrome/browser/spellchecker/spellcheck_service_unittest.cc b/chrome/browser/spellchecker/spellcheck_service_unittest.cc
index 1f68810..c481af2 100644
--- a/chrome/browser/spellchecker/spellcheck_service_unittest.cc
+++ b/chrome/browser/spellchecker/spellcheck_service_unittest.cc
@@ -11,11 +11,10 @@
 #include "chrome/browser/spellchecker/spellcheck_service.h"
 #include "chrome/common/spellcheck_common.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
 using chrome::spellcheck_common::WordList;
 
 static BrowserContextKeyedService* BuildSpellcheckService(
@@ -25,27 +24,15 @@
 
 class SpellcheckServiceTest : public testing::Test {
  protected:
-  SpellcheckServiceTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_),
-        profile_(new TestingProfile()) {
-  }
-
   virtual void SetUp() OVERRIDE {
     // Use SetTestingFactoryAndUse to force creation and initialization.
     SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-        profile_.get(), &BuildSpellcheckService);
+        &profile_, &BuildSpellcheckService);
   }
 
-  virtual void TearDown() OVERRIDE {
-    base::MessageLoop::current()->RunUntilIdle();
-  }
-
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
-
-  scoped_ptr<TestingProfile> profile_;
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
 };
 
 TEST_F(SpellcheckServiceTest, GetSpellCheckLanguages1) {
diff --git a/chrome/browser/spellchecker/spelling_service_client_unittest.cc b/chrome/browser/spellchecker/spelling_service_client_unittest.cc
index c40bc55..b3ac8d2 100644
--- a/chrome/browser/spellchecker/spelling_service_client_unittest.cc
+++ b/chrome/browser/spellchecker/spelling_service_client_unittest.cc
@@ -16,6 +16,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/spellcheck_result.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -191,12 +192,6 @@
 // monitor the class calls the callback with expected results.
 class SpellingServiceClientTest : public testing::Test {
  public:
-  SpellingServiceClientTest() {}
-  virtual ~SpellingServiceClientTest() {}
-
-  virtual void SetUp() OVERRIDE {
-  }
-
   void OnTextCheckComplete(int tag,
                            bool success,
                            const string16& text,
@@ -205,6 +200,7 @@
   }
 
  protected:
+  content::TestBrowserThreadBundle thread_bundle_;
   TestingSpellingServiceClient client_;
   TestingProfile profile_;
 };
diff --git a/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc b/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc
index 1a19918..7a74069 100644
--- a/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc
+++ b/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc
@@ -204,6 +204,7 @@
 
     // Linux storage monitor must be destroyed on the UI thread, so do it here.
     test::TestStorageMonitor::RemoveSingleton();
+    base::RunLoop().RunUntilIdle();
   }
 
   // Append mtab entries from the |data| array of size |data_size| to the mtab
diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.cc b/chrome/browser/sync/abstract_profile_sync_service_test.cc
index 1c4a995..8de5c6b 100644
--- a/chrome/browser/sync/abstract_profile_sync_service_test.cc
+++ b/chrome/browser/sync/abstract_profile_sync_service_test.cc
@@ -7,13 +7,14 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
+#include "base/run_loop.h"
 #include "chrome/browser/sync/test_profile_sync_service.h"
+#include "content/public/test/test_utils.h"
 #include "sync/internal_api/public/test/test_user_share.h"
 #include "sync/internal_api/public/write_transaction.h"
 #include "sync/protocol/sync.pb.h"
 #include "sync/util/cryptographer.h"
 
-using content::BrowserThread;
 using syncer::ModelType;
 using syncer::UserShare;
 
@@ -41,10 +42,9 @@
 }
 
 AbstractProfileSyncServiceTest::AbstractProfileSyncServiceTest()
-    : ui_thread_(BrowserThread::UI, &ui_loop_),
-      db_thread_(BrowserThread::DB),
-      file_thread_(BrowserThread::FILE),
-      io_thread_(BrowserThread::IO),
+    : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
+                     content::TestBrowserThreadBundle::REAL_FILE_THREAD |
+                     content::TestBrowserThreadBundle::REAL_IO_THREAD),
       token_service_(NULL),
       sync_service_(NULL) {
 }
@@ -52,19 +52,14 @@
 AbstractProfileSyncServiceTest::~AbstractProfileSyncServiceTest() {}
 
 void AbstractProfileSyncServiceTest::SetUp() {
-  db_thread_.Start();
-  file_thread_.Start();
-  io_thread_.StartIOThread();
 }
 
 void AbstractProfileSyncServiceTest::TearDown() {
   // Pump messages posted by the sync core thread (which may end up
   // posting on the IO thread).
-  ui_loop_.RunUntilIdle();
-  io_thread_.Stop();
-  file_thread_.Stop();
-  db_thread_.Stop();
-  ui_loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
+  base::RunLoop().RunUntilIdle();
 }
 
 bool AbstractProfileSyncServiceTest::CreateRoot(ModelType model_type) {
diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.h b/chrome/browser/sync/abstract_profile_sync_service_test.h
index c3538a2..1ccc810 100644
--- a/chrome/browser/sync/abstract_profile_sync_service_test.h
+++ b/chrome/browser/sync/abstract_profile_sync_service_test.h
@@ -13,7 +13,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/change_record.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -52,11 +52,7 @@
       content::BrowserContext* profile);
 
  protected:
-  base::MessageLoopForUI ui_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread file_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   TokenService* token_service_;
   TestProfileSyncService* sync_service_;
 };
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
index 2660d57..696f5f1 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/sync/glue/autofill_data_type_controller.h"
@@ -24,7 +23,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "sync/api/sync_error.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -153,10 +152,9 @@
 class SyncAutofillDataTypeControllerTest : public testing::Test {
  public:
   SyncAutofillDataTypeControllerTest()
-      : weak_ptr_factory_(this),
-        ui_thread_(BrowserThread::UI, &message_loop_),
-        db_thread_(BrowserThread::DB),
-        last_start_result_(DataTypeController::OK) {}
+      : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD),
+        last_start_result_(DataTypeController::OK),
+        weak_ptr_factory_(this) {}
 
   virtual ~SyncAutofillDataTypeControllerTest() {}
 
@@ -174,8 +172,6 @@
         new AutofillDataTypeController(&profile_sync_factory_,
                                        &profile_,
                                        &service_);
-
-    db_thread_.Start();
   }
 
   // Passed to AutofillDTC::Start().
@@ -204,10 +200,7 @@
   }
 
  protected:
-  base::WeakPtrFactory<SyncAutofillDataTypeControllerTest> weak_ptr_factory_;
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   scoped_refptr<NiceMock<SharedChangeProcessorMock> > change_processor_;
   ProfileSyncComponentsFactoryMock profile_sync_factory_;
@@ -218,6 +211,7 @@
   // Stores arguments of most recent call of OnStartFinished().
   DataTypeController::StartResult last_start_result_;
   syncer::SyncError last_start_error_;
+  base::WeakPtrFactory<SyncAutofillDataTypeControllerTest> weak_ptr_factory_;
 };
 
 // Load the WDS's database, then start the Autofill DTC.  It should
diff --git a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
index ec8ba1f..3f95b14 100644
--- a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
@@ -6,6 +6,7 @@
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
 #include "base/tracked_objects.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -143,7 +144,7 @@
   EXPECT_EQ(DataTypeController::MODEL_LOADED, search_engine_dtc_->state());
 
   // Wait until WebDB is loaded before we shut it down.
-  test_util_.BlockTillServiceProcessesRequests();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(SyncSearchEngineDataTypeControllerTest, StartFirstRun) {
@@ -222,7 +223,7 @@
   Start();
   // This should cause search_engine_dtc_->Stop() to be called.
   search_engine_dtc_->OnSingleDatatypeUnrecoverableError(FROM_HERE, "Test");
-  test_util_.PumpLoop();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
   EXPECT_FALSE(syncable_service_.syncing());
 }
diff --git a/chrome/browser/sync/glue/sync_backend_host_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
index 5c2f62e..90eadee 100644
--- a/chrome/browser/sync/glue/sync_backend_host_unittest.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
@@ -20,7 +20,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "google/cacheinvalidation/include/types.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "sync/internal_api/public/base/model_type.h"
@@ -135,16 +136,13 @@
 class SyncBackendHostTest : public testing::Test {
  protected:
   SyncBackendHostTest()
-      : ui_thread_(BrowserThread::UI, &ui_loop_),
-        io_thread_(BrowserThread::IO),
+      : thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD),
         fake_manager_(NULL) {}
 
   virtual ~SyncBackendHostTest() {}
 
   virtual void SetUp() OVERRIDE {
-    io_thread_.StartIOThread();
     profile_.reset(new TestingProfile());
-    profile_->CreateRequestContext();
     sync_prefs_.reset(new SyncPrefs(profile_->GetPrefs()));
     backend_.reset(new SyncBackendHost(
         profile_->GetDebugName(),
@@ -178,10 +176,10 @@
     profile_.reset();
     // Pump messages posted by the sync thread (which may end up
     // posting on the IO thread).
-    ui_loop_.RunUntilIdle();
-    io_thread_.Stop();
+    base::RunLoop().RunUntilIdle();
+    content::RunAllPendingInMessageLoop(BrowserThread::IO);
     // Pump any messages posted by the IO thread.
-    ui_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   // Synchronously initializes the backend.
@@ -196,9 +194,11 @@
                          &fake_manager_factory_,
                          &handler_,
                          NULL);
-    ui_loop_.PostDelayedTask(FROM_HERE,
-        ui_loop_.QuitClosure(), TestTimeouts::action_timeout());
-    ui_loop_.Run();
+    base::RunLoop run_loop;
+    BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+                                   run_loop.QuitClosure(),
+                                   TestTimeouts::action_timeout());
+    run_loop.Run();
     // |fake_manager_factory_|'s fake_manager() is set on the sync
     // thread, but we can rely on the message loop barriers to
     // guarantee that we see the updated value.
@@ -226,9 +226,11 @@
                    base::Unretained(this)),
         base::Bind(&SyncBackendHostTest::OnDownloadRetry,
                    base::Unretained(this)));
-    ui_loop_.PostDelayedTask(FROM_HERE,
-        ui_loop_.QuitClosure(), TestTimeouts::action_timeout());
-    ui_loop_.Run();
+    base::RunLoop run_loop;
+    BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+                                   run_loop.QuitClosure(),
+                                   TestTimeouts::action_timeout());
+    run_loop.Run();
   }
 
   void IssueRefreshRequest(syncer::ModelTypeSet types) {
@@ -250,9 +252,7 @@
     NOTIMPLEMENTED();
   }
 
-  base::MessageLoop ui_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   StrictMock<MockSyncFrontend> mock_frontend_;
   syncer::SyncCredentials credentials_;
   syncer::TestUnrecoverableErrorHandler handler_;
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 9f18db2..72b6a0e 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -504,7 +504,6 @@
   virtual void SetUp() OVERRIDE {
     AbstractProfileSyncServiceTest::SetUp();
     profile_.reset(new ProfileMock());
-    profile_->CreateRequestContext();
     web_database_.reset(new WebDatabaseFake(&autofill_table_));
     MockWebDataServiceWrapper* wrapper =
         static_cast<MockWebDataServiceWrapper*>(
@@ -542,7 +541,6 @@
     web_data_service_->ShutdownOnUIThread();
     web_data_service_->ShutdownSyncableService();
     web_data_service_ = NULL;
-    profile_->ResetRequestContext();
     // To prevent a leak, fully release TestURLRequestContext to ensure its
     // destruction on the IO message loop.
     profile_.reset();
diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc
index b9a3fac..17b9523 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -154,8 +154,7 @@
 
   virtual void SetUp() {
     AbstractProfileSyncServiceTest::SetUp();
-    profile_.reset(new ProfileMock);
-    profile_->CreateRequestContext();
+    profile_.reset(new ProfileMock());
     invalidation::InvalidationServiceFactory::GetInstance()->
         SetBuildOnlyFakeInvalidatorsForTest(true);
     password_store_ = static_cast<MockPasswordStore*>(
@@ -168,7 +167,6 @@
       password_store_->ShutdownOnUIThread();
       ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
           profile_.get(), NULL);
-      profile_->ResetRequestContext();
       profile_.reset();
       AbstractProfileSyncServiceTest::TearDown();
   }
diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
index 076a7fb..4d57c21 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -124,7 +124,6 @@
   virtual void SetUp() {
     AbstractProfileSyncServiceTest::SetUp();
     profile_.reset(new TestingProfile());
-    profile_->CreateRequestContext();
     invalidation::InvalidationServiceFactory::GetInstance()->
         SetBuildOnlyFakeInvalidatorsForTest(true);
     prefs_ = profile_->GetTestingPrefService();
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index 6643286..aec8539 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/guid.h"
 #include "base/location.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -48,6 +48,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_thread.h"
 #include "google_apis/gaia/gaia_constants.h"
+#include "net/url_request/test_url_fetcher_factory.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/change_record.h"
 #include "sync/internal_api/public/read_node.h"
@@ -202,8 +203,7 @@
       public content::NotificationObserver {
  public:
   ProfileSyncServiceSessionTest()
-      : io_thread_(BrowserThread::IO),
-        window_bounds_(0, 1, 2, 3),
+      : window_bounds_(0, 1, 2, 3),
         notified_of_update_(false),
         notified_of_refresh_(false) {}
   ProfileSyncService* sync_service() { return sync_service_.get(); }
@@ -222,8 +222,6 @@
   virtual void SetUp() {
     // BrowserWithTestWindowTest implementation.
     BrowserWithTestWindowTest::SetUp();
-    io_thread_.StartIOThread();
-    profile()->CreateRequestContext();
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
         content::NotificationService::AllSources());
@@ -250,7 +248,6 @@
   virtual void TearDown() {
     sync_service_->Shutdown();
     sync_service_.reset();
-    profile()->ResetRequestContext();
 
     // We need to destroy the profile before shutting down the threads, because
     // some of the ref counted objects in the profile depend on their
@@ -260,9 +257,7 @@
 
     // Pump messages posted by the sync core thread (which may end up
     // posting on the IO thread).
-    base::MessageLoop::current()->RunUntilIdle();
-    io_thread_.Stop();
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     BrowserWithTestWindowTest::TearDown();
   }
 
@@ -312,7 +307,6 @@
     return true;
   }
 
-  content::TestBrowserThread io_thread_;
   // Path used in testing.
   base::ScopedTempDir temp_dir_;
   SessionModelAssociator* model_associator_;
@@ -323,6 +317,7 @@
   bool notified_of_update_;
   bool notified_of_refresh_;
   content::NotificationRegistrar registrar_;
+  net::TestURLFetcherFactory fetcher_factory_;
 };
 
 class CreateRootHelper {
@@ -1222,7 +1217,7 @@
   // Update associator.
   model_associator_->AssociateForeignSpecifics(meta, base::Time());
   model_associator_->AssociateForeignSpecifics(tab, base::Time());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(model_associator_->GetSyncedFaviconForPageURL(url, &favicon));
 
   // Now add a favicon.
@@ -1230,7 +1225,7 @@
   tab.mutable_tab()->set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON);
   tab.mutable_tab()->set_favicon("data");
   model_associator_->AssociateForeignSpecifics(tab, base::Time());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(model_associator_->GetSyncedFaviconForPageURL(url, &favicon));
   ASSERT_TRUE(CompareMemoryToString("data", favicon));
 
@@ -1241,7 +1236,7 @@
   tab.mutable_tab()->clear_favicon_type();
   tab.mutable_tab()->clear_favicon();
   model_associator_->AssociateForeignSpecifics(tab, base::Time());
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(model_associator_->GetSyncedFaviconForPageURL(url, &favicon));
 }
 
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index 85b5c88..f1bfd96 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
@@ -27,7 +28,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -71,10 +73,9 @@
 class ProfileSyncServiceStartupTest : public testing::Test {
  public:
   ProfileSyncServiceStartupTest()
-      : ui_thread_(BrowserThread::UI, &ui_loop_),
-        db_thread_(BrowserThread::DB),
-        file_thread_(BrowserThread::FILE),
-        io_thread_(BrowserThread::IO),
+      : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
+                       content::TestBrowserThreadBundle::REAL_FILE_THREAD |
+                       content::TestBrowserThreadBundle::REAL_IO_THREAD),
         profile_(new TestingProfile),
         sync_(NULL) {}
 
@@ -82,9 +83,6 @@
   }
 
   virtual void SetUp() {
-    file_thread_.Start();
-    io_thread_.StartIOThread();
-    profile_->CreateRequestContext();
 #if defined(OS_CHROMEOS)
     SigninManagerFactory::GetInstance()->SetTestingFactory(
         profile_.get(), FakeSigninManagerBase::Build);
@@ -104,10 +102,9 @@
 
     // Pump messages posted by the sync core thread (which may end up
     // posting on the IO thread).
-    ui_loop_.RunUntilIdle();
-    io_thread_.Stop();
-    file_thread_.Stop();
-    ui_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
+    content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
+    base::RunLoop().RunUntilIdle();
   }
 
   static BrowserContextKeyedService* BuildService(
@@ -139,11 +136,7 @@
     return data_type_manager;
   }
 
-  base::MessageLoop ui_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread file_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
   TestProfileSyncService* sync_;
   ProfileSyncServiceObserverMock observer_;
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index e933442..2738c10 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -174,8 +174,7 @@
 
   virtual void SetUp() {
     AbstractProfileSyncServiceTest::SetUp();
-    profile_.reset(new ProfileMock);
-    profile_->CreateRequestContext();
+    profile_.reset(new ProfileMock());
     invalidation::InvalidationServiceFactory::GetInstance()->
         SetBuildOnlyFakeInvalidatorsForTest(true);
     history_backend_ = new HistoryBackendMock();
@@ -194,7 +193,6 @@
     ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
         profile_.get(), NULL);
     history_thread_.Stop();
-    profile_->ResetRequestContext();
     profile_.reset();
     AbstractProfileSyncServiceTest::TearDown();
   }
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index 6eb7521..9b22da9 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -6,7 +6,7 @@
 #include "base/compiler_specific.h"
 #include "base/file_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -21,7 +21,8 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "google/cacheinvalidation/include/types.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "sync/js/js_arg_list.h"
@@ -38,7 +39,6 @@
 
 namespace {
 
-using content::BrowserThread;
 using testing::_;
 using testing::AtLeast;
 using testing::AtMost;
@@ -49,18 +49,13 @@
 class ProfileSyncServiceTestHarness {
  public:
   ProfileSyncServiceTestHarness()
-      : ui_thread_(BrowserThread::UI, &ui_loop_),
-        db_thread_(BrowserThread::DB),
-        file_thread_(BrowserThread::FILE),
-        io_thread_(BrowserThread::IO) {}
-
-  ~ProfileSyncServiceTestHarness() {}
+      : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
+                       content::TestBrowserThreadBundle::REAL_FILE_THREAD |
+                       content::TestBrowserThreadBundle::REAL_IO_THREAD) {
+   }
 
   void SetUp() {
-    file_thread_.Start();
-    io_thread_.StartIOThread();
     profile.reset(new TestingProfile());
-    profile->CreateRequestContext();
     invalidation::InvalidationServiceFactory::GetInstance()->
         SetBuildOnlyFakeInvalidatorsForTest(true);
     ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
@@ -76,11 +71,9 @@
     profile.reset();
     // Pump messages posted by the sync thread (which may end up
     // posting on the IO thread).
-    ui_loop_.RunUntilIdle();
-    io_thread_.Stop();
-    file_thread_.Stop();
-    // Ensure that the sync objects destruct to avoid memory leaks.
-    ui_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
+    content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
+    base::RunLoop().RunUntilIdle();
   }
 
   // TODO(akalin): Refactor the StartSyncService*() functions below.
@@ -140,14 +133,7 @@
   scoped_ptr<TestingProfile> profile;
 
  private:
-  base::MessageLoop ui_loop_;
-  // Needed by |service|.
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  // Needed by DisableAndEnableSyncTemporarily test case.
-  content::TestBrowserThread file_thread_;
-  // Needed by |service| and |profile|'s request context.
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 class TestProfileSyncServiceObserver : public ProfileSyncServiceObserver {
diff --git a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc
index 403abd9..30c27ab 100644
--- a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc
@@ -43,13 +43,11 @@
 #define MAYBE_SingleClientEnabledEncryptionAndChanged DISABLED_SingleClientEnabledEncryptionAndChanged
 #define MAYBE_BothChanged DISABLED_BothChanged
 #define MAYBE_DeleteIdleSession DISABLED_DeleteIdleSession
-#define MAYBE_DeleteActiveSession DISABLED_DeleteActiveSession
 #else
 #define MAYBE_SingleClientChanged SingleClientChanged
 #define MAYBE_SingleClientEnabledEncryptionAndChanged SingleClientEnabledEncryptionAndChanged
 #define MAYBE_BothChanged BothChanged
 #define MAYBE_DeleteIdleSession DeleteIdleSession
-#define MAYBE_DeleteActiveSession DeleteActiveSession
 #endif
 
 
@@ -188,7 +186,9 @@
   ASSERT_FALSE(GetSessionData(1, &sessions1));
 }
 
-IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, MAYBE_DeleteActiveSession) {
+// Fails all release trybots. crbug.com/263369.
+IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest,
+                       DISABLED_DeleteActiveSession) {
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
 
   ASSERT_TRUE(CheckInitialState(0));
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util.cc b/chrome/browser/sync_file_system/drive_backend/api_util.cc
index 84cb34a..e1ddfb7 100644
--- a/chrome/browser/sync_file_system/drive_backend/api_util.cc
+++ b/chrome/browser/sync_file_system/drive_backend/api_util.cc
@@ -9,6 +9,7 @@
 #include <sstream>
 #include <string>
 
+#include "base/file_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
@@ -137,9 +138,24 @@
   return mime_type;
 }
 
+bool CreateTemporaryFile(const base::FilePath& dir_path,
+                         webkit_blob::ScopedFile* temp_file) {
+  base::FilePath temp_file_path;
+  const bool success = file_util::CreateDirectory(dir_path) &&
+      file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path);
+  if (!success)
+    return success;
+  *temp_file =
+      webkit_blob::ScopedFile(temp_file_path,
+                              webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
+                              base::MessageLoopProxy::current().get());
+  return success;
+}
+
 }  // namespace
 
-APIUtil::APIUtil(Profile* profile)
+APIUtil::APIUtil(Profile* profile,
+                 const base::FilePath& temp_dir_path)
     : wapi_url_generator_(
           GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
           GURL(google_apis::GDataWapiUrlGenerator::
@@ -148,7 +164,8 @@
           GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
           GURL(google_apis::DriveApiUrlGenerator::
                kBaseDownloadUrlForProduction)),
-      upload_next_key_(0) {
+      upload_next_key_(0),
+      temp_dir_path_(temp_dir_path) {
   if (IsDriveAPIDisabled()) {
     drive_service_.reset(new drive::GDataWapiService(
         profile->GetRequestContext(),
@@ -175,10 +192,12 @@
 
 scoped_ptr<APIUtil> APIUtil::CreateForTesting(
     Profile* profile,
+    const base::FilePath& temp_dir_path,
     scoped_ptr<drive::DriveServiceInterface> drive_service,
     scoped_ptr<drive::DriveUploaderInterface> drive_uploader) {
   return make_scoped_ptr(new APIUtil(
       profile,
+      temp_dir_path,
       GURL(kFakeServerBaseUrl),
       GURL(kFakeDownloadServerBaseUrl),
       drive_service.Pass(),
@@ -186,13 +205,15 @@
 }
 
 APIUtil::APIUtil(Profile* profile,
+                 const base::FilePath& temp_dir_path,
                  const GURL& base_url,
                  const GURL& base_download_url,
                  scoped_ptr<drive::DriveServiceInterface> drive_service,
                  scoped_ptr<drive::DriveUploaderInterface> drive_uploader)
     : wapi_url_generator_(base_url, base_download_url),
       drive_api_url_generator_(base_url, base_download_url),
-      upload_next_key_(0) {
+      upload_next_key_(0),
+      temp_dir_path_(temp_dir_path) {
   drive_service_ = drive_service.Pass();
   drive_service_->Initialize(profile);
   drive_service_->AddObserver(this);
@@ -484,20 +505,19 @@
 
 void APIUtil::DownloadFile(const std::string& resource_id,
                            const std::string& local_file_md5,
-                           const base::FilePath& local_file_path,
                            const DownloadFileCallback& callback) {
   DCHECK(CalledOnValidThread());
+  DCHECK(!temp_dir_path_.empty());
   DVLOG(2) << "Downloading file [" << resource_id << "]";
 
-  drive_service_->GetResourceEntry(
-      resource_id,
-      base::Bind(&APIUtil::DidGetResourceEntry,
-                 AsWeakPtr(),
-                 base::Bind(&APIUtil::DownloadFileInternal,
-                            AsWeakPtr(),
-                            local_file_md5,
-                            local_file_path,
-                            callback)));
+  scoped_ptr<webkit_blob::ScopedFile> temp_file(new webkit_blob::ScopedFile);
+  webkit_blob::ScopedFile* temp_file_ptr = temp_file.get();
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::FILE, FROM_HERE,
+      base::Bind(&CreateTemporaryFile, temp_dir_path_, temp_file_ptr),
+      base::Bind(&APIUtil::DidGetTemporaryFileForDownload,
+                 AsWeakPtr(), resource_id, local_file_md5,
+                 base::Passed(&temp_file), callback));
 }
 
 void APIUtil::UploadNewFile(const std::string& directory_resource_id,
@@ -699,9 +719,33 @@
   callback.Run(error, entry.Pass());
 }
 
+void APIUtil::DidGetTemporaryFileForDownload(
+    const std::string& resource_id,
+    const std::string& local_file_md5,
+    scoped_ptr<webkit_blob::ScopedFile> local_file,
+    const DownloadFileCallback& callback,
+    bool success) {
+  if (!success) {
+    DVLOG(2) << "Error in creating a temp file under "
+             << temp_dir_path_.value();
+    callback.Run(google_apis::GDATA_FILE_ERROR, std::string(), 0, base::Time(),
+                 local_file.Pass());
+    return;
+  }
+  drive_service_->GetResourceEntry(
+      resource_id,
+      base::Bind(&APIUtil::DidGetResourceEntry,
+                 AsWeakPtr(),
+                 base::Bind(&APIUtil::DownloadFileInternal,
+                            AsWeakPtr(),
+                            local_file_md5,
+                            base::Passed(&local_file),
+                            callback)));
+}
+
 void APIUtil::DownloadFileInternal(
     const std::string& local_file_md5,
-    const base::FilePath& local_file_path,
+    scoped_ptr<webkit_blob::ScopedFile> local_file,
     const DownloadFileCallback& callback,
     google_apis::GDataErrorCode error,
     scoped_ptr<google_apis::ResourceEntry> entry) {
@@ -709,7 +753,8 @@
 
   if (error != google_apis::HTTP_SUCCESS) {
     DVLOG(2) << "Error on getting resource entry for download";
-    callback.Run(error, std::string(), 0, base::Time());
+    callback.Run(error, std::string(), 0, base::Time(),
+                 local_file.Pass());
     return;
   }
   DCHECK(entry);
@@ -720,23 +765,27 @@
     callback.Run(google_apis::HTTP_NOT_MODIFIED,
                  local_file_md5,
                  entry->file_size(),
-                 entry->updated_time());
+                 entry->updated_time(),
+                 local_file.Pass());
     return;
   }
 
   DVLOG(2) << "Downloading file: " << entry->resource_id();
   const std::string& resource_id = entry->resource_id();
+  const base::FilePath& local_file_path = local_file->path();
   drive_service_->DownloadFile(local_file_path,
                                resource_id,
                                base::Bind(&APIUtil::DidDownloadFile,
                                           AsWeakPtr(),
                                           base::Passed(&entry),
+                                          base::Passed(&local_file),
                                           callback),
                                google_apis::GetContentCallback(),
                                google_apis::ProgressCallback());
 }
 
 void APIUtil::DidDownloadFile(scoped_ptr<google_apis::ResourceEntry> entry,
+                              scoped_ptr<webkit_blob::ScopedFile> local_file,
                               const DownloadFileCallback& callback,
                               google_apis::GDataErrorCode error,
                               const base::FilePath& downloaded_file_path) {
@@ -747,7 +796,8 @@
     DVLOG(2) << "Error on downloading file: " << error;
 
   callback.Run(
-      error, entry->file_md5(), entry->file_size(), entry->updated_time());
+      error, entry->file_md5(), entry->file_size(), entry->updated_time(),
+      local_file.Pass());
 }
 
 void APIUtil::DidUploadNewFile(const std::string& parent_resource_id,
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util.h b/chrome/browser/sync_file_system/drive_backend/api_util.h
index 8c17628..e976a15 100644
--- a/chrome/browser/sync_file_system/drive_backend/api_util.h
+++ b/chrome/browser/sync_file_system/drive_backend/api_util.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
 #include "chrome/browser/sync_file_system/drive_backend/api_util_interface.h"
 #include "net/base/network_change_notifier.h"
+#include "webkit/common/blob/scoped_file.h"
 
 class GURL;
 class Profile;
@@ -44,7 +45,7 @@
                               scoped_ptr<google_apis::ResourceEntry> entry)>
       EnsureUniquenessCallback;
 
-  explicit APIUtil(Profile* profile);
+  APIUtil(Profile* profile, const base::FilePath& temp_dir_path);
   virtual ~APIUtil();
 
   virtual void AddObserver(APIUtilObserver* observer) OVERRIDE;
@@ -52,6 +53,7 @@
 
   static scoped_ptr<APIUtil> CreateForTesting(
       Profile* profile,
+      const base::FilePath& temp_dir_path,
       scoped_ptr<drive::DriveServiceInterface> drive_service,
       scoped_ptr<drive::DriveUploaderInterface> drive_uploader);
 
@@ -74,7 +76,6 @@
                                const ResourceListCallback& callback) OVERRIDE;
   virtual void DownloadFile(const std::string& resource_id,
                             const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
                             const DownloadFileCallback& callback) OVERRIDE;
   virtual void UploadNewFile(const std::string& directory_resource_id,
                              const base::FilePath& local_file_path,
@@ -115,6 +116,7 @@
 
   // Constructor for test use.
   APIUtil(Profile* profile,
+          const base::FilePath& temp_dir_path,
           const GURL& base_url,
           const GURL& base_download_url,
           scoped_ptr<drive::DriveServiceInterface> drive_service,
@@ -169,13 +171,21 @@
                            google_apis::GDataErrorCode error,
                            scoped_ptr<google_apis::ResourceEntry> entry);
 
+  void DidGetTemporaryFileForDownload(
+      const std::string& resource_id,
+      const std::string& local_file_md5,
+      scoped_ptr<webkit_blob::ScopedFile> local_file,
+      const DownloadFileCallback& callback,
+      bool success);
+
   void DownloadFileInternal(const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
+                            scoped_ptr<webkit_blob::ScopedFile> local_file,
                             const DownloadFileCallback& callback,
                             google_apis::GDataErrorCode error,
                             scoped_ptr<google_apis::ResourceEntry> entry);
 
   void DidDownloadFile(scoped_ptr<google_apis::ResourceEntry> entry,
+                       scoped_ptr<webkit_blob::ScopedFile> local_file,
                        const DownloadFileCallback& callback,
                        google_apis::GDataErrorCode error,
                        const base::FilePath& downloaded_file_path);
@@ -243,6 +253,8 @@
   UploadCallbackMap upload_callback_map_;
   UploadKey upload_next_key_;
 
+  base::FilePath temp_dir_path_;
+
   std::string root_resource_id_;
 
   ObserverList<APIUtilObserver> observers_;
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util_interface.h b/chrome/browser/sync_file_system/drive_backend/api_util_interface.h
index 46867f2..e4a2ca7 100644
--- a/chrome/browser/sync_file_system/drive_backend/api_util_interface.h
+++ b/chrome/browser/sync_file_system/drive_backend/api_util_interface.h
@@ -22,6 +22,10 @@
 class DriveUploaderInterface;
 }
 
+namespace webkit_blob {
+class ScopedFile;
+}
+
 namespace sync_file_system {
 namespace drive_backend {
 
@@ -46,7 +50,8 @@
   typedef base::Callback<void(google_apis::GDataErrorCode error,
                               const std::string& file_md5,
                               int64 file_size,
-                              const base::Time& last_updated)>
+                              const base::Time& last_updated,
+                              scoped_ptr<webkit_blob::ScopedFile> downloaded)>
       DownloadFileCallback;
   typedef base::Callback<void(google_apis::GDataErrorCode error,
                               const std::string& resource_id,
@@ -130,7 +135,6 @@
   // empty.
   virtual void DownloadFile(const std::string& resource_id,
                             const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
                             const DownloadFileCallback& callback) = 0;
 
   // Uploads the new file |local_file_path| with specified |title| into the
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util_unittest.cc b/chrome/browser/sync_file_system/drive_backend/api_util_unittest.cc
index 1407ab9..3f03963 100644
--- a/chrome/browser/sync_file_system/drive_backend/api_util_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/api_util_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/sync_file_system/drive_backend/api_util.h"
 
+#include "base/file_util.h"
 #include "base/location.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
@@ -214,8 +215,10 @@
     fake_drive_helper_.reset(new FakeDriveServiceHelper(
         fake_drive_service_, fake_drive_uploader_));
 
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     api_util_ = APIUtil::CreateForTesting(
         &profile_,
+        temp_dir_.path(),
         scoped_ptr<DriveServiceInterface>(fake_drive_service_),
         scoped_ptr<DriveUploaderInterface>(fake_drive_uploader_));
 
@@ -324,6 +327,7 @@
  private:
   content::TestBrowserThreadBundle thread_bundle_;
 
+  base::ScopedTempDir temp_dir_;
   TestingProfile profile_;
   scoped_ptr<APIUtil> api_util_;
   FakeDriveServiceWrapper* fake_drive_service_;
@@ -363,8 +367,10 @@
                      GDataErrorCode error,
                      const std::string& file_md5,
                      int64 file_size,
-                     const base::Time& updated_time) {
+                     const base::Time& updated_time,
+                     scoped_ptr<webkit_blob::ScopedFile> file) {
   ASSERT_TRUE(output);
+  ASSERT_TRUE(base::PathExists(file->path()));
   output->error = error;
   output->file_md5 = file_md5;
 }
@@ -585,15 +591,10 @@
   scoped_ptr<ResourceEntry> file;
   SetUpFile(origin_root_id, kFileContent, kFileTitle, &file);
 
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath output_file_path = temp_dir.path().AppendASCII(file->title());
-
   Output output;
   api_util()->DownloadFile(
       file->resource_id(),
       "",  // local_file_md5
-      output_file_path,
       base::Bind(&DidDownloadFile, &output));
   base::MessageLoop::current()->RunUntilIdle();
 
@@ -610,17 +611,12 @@
   scoped_ptr<ResourceEntry> file;
   SetUpFile(origin_root_id, kFileContent, kFileTitle, &file);
 
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath output_file_path = temp_dir.path().AppendASCII(file->title());
-
   // Since local file's hash value is equal to remote file's one, it is expected
   // to cancel download the file and to return NOT_MODIFIED status code.
   Output output;
   api_util()->DownloadFile(
       file->resource_id(),
       file->file_md5(),
-      output_file_path,
       base::Bind(&DidDownloadFile, &output));
   base::MessageLoop::current()->RunUntilIdle();
 
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service.cc b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service.cc
index 4ff04d8..9e07bdd 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service.cc
@@ -58,20 +58,6 @@
       ? kSyncFileSystemDirDev : kSyncFileSystemDir;
 }
 
-bool CreateTemporaryFile(const base::FilePath& dir_path,
-                         webkit_blob::ScopedFile* temp_file) {
-  base::FilePath temp_file_path;
-  const bool success = file_util::CreateDirectory(dir_path) &&
-      file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path);
-  if (!success)
-    return success;
-  *temp_file =
-      webkit_blob::ScopedFile(temp_file_path,
-                              webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
-                              base::MessageLoopProxy::current().get());
-  return success;
-}
-
 void EmptyStatusCallback(SyncStatusCode status) {}
 
 }  // namespace
@@ -325,7 +311,7 @@
   temporary_file_dir_ =
       profile_->GetPath().Append(GetSyncFileSystemDir()).Append(kTempDirName);
 
-  api_util_.reset(new drive_backend::APIUtil(profile_));
+  api_util_.reset(new drive_backend::APIUtil(profile_, temporary_file_dir_));
   api_util_->AddObserver(this);
 
   metadata_store_.reset(new DriveMetadataStore(
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_fake_unittest.cc b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_fake_unittest.cc
index 2d1e8a2..a26c2af 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_fake_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_fake_unittest.cc
@@ -7,8 +7,8 @@
 #include <utility>
 
 #include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
 #include "chrome/browser/drive/drive_uploader.h"
 #include "chrome/browser/drive/fake_drive_service.h"
 #include "chrome/browser/extensions/test_extension_service.h"
@@ -28,7 +28,6 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_builder.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/common/id_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -207,6 +206,7 @@
 
     api_util_ = APIUtil::CreateForTesting(
         profile_.get(),
+        fake_drive_helper_->base_dir_path().AppendASCII("tmp"),
         scoped_ptr<DriveServiceInterface>(fake_drive_service_),
         scoped_ptr<DriveUploaderInterface>(drive_uploader)).Pass();
     metadata_store_.reset(new DriveMetadataStore(
@@ -215,7 +215,7 @@
 
     bool done = false;
     metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     EXPECT_TRUE(done);
 
     fake_drive_service_->LoadResourceListForWapi(
@@ -240,7 +240,7 @@
     sync_service_->AddFileStatusObserver(&mock_file_status_observer_);
     sync_service_->SetRemoteChangeProcessor(mock_remote_processor());
     sync_service_->SetSyncEnabled(enabled);
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   virtual void TearDown() OVERRIDE {
@@ -256,7 +256,7 @@
 
     extension_service_ = NULL;
     profile_.reset();
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   void SetSyncEnabled(bool enabled) {
@@ -283,7 +283,7 @@
   void UpdateRegisteredOrigins() {
     sync_service_->UpdateRegisteredOrigins();
     // Wait for completion of uninstalling origin.
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   void VerifySizeOfRegisteredOrigins(size_t b_size,
@@ -352,7 +352,7 @@
 
     sync_service_->ProcessRemoteChange(
         base::Bind(&DidProcessRemoteChange, &actual_status, &actual_url));
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
 
     EXPECT_EQ(expected_status, actual_status);
     EXPECT_EQ(expected_url, actual_url);
@@ -445,7 +445,7 @@
   sync_service()->RegisterOriginForTrackingChanges(
       ExtensionNameToGURL(kExtensionName1),
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(done);
 
   VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
@@ -473,7 +473,7 @@
   sync_service()->RegisterOriginForTrackingChanges(
       ExtensionNameToGURL(kExtensionName1),
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(done);
 
   // The origin should be registered as an incremental sync origin.
@@ -493,7 +493,7 @@
   sync_service()->RegisterOriginForTrackingChanges(
       ExtensionNameToGURL(kExtensionName1),
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(done);
 
   // We must not have started batch sync for the newly registered origin,
@@ -515,7 +515,7 @@
   sync_service()->UnregisterOriginForTrackingChanges(
       ExtensionNameToGURL(kExtensionName1),
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(done);
 
   VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_sync_unittest.cc b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_sync_unittest.cc
index 8d273d1..41e9037 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_sync_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_sync_unittest.cc
@@ -118,6 +118,7 @@
 
     scoped_ptr<APIUtil> api_util(APIUtil::CreateForTesting(
         &profile_,
+        fake_drive_helper_->base_dir_path().AppendASCII("tmp"),
         scoped_ptr<drive::DriveServiceInterface>(fake_drive_service_),
         scoped_ptr<drive::DriveUploaderInterface>(drive_uploader_)));
 
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_unittest.cc
index 1b53de2..c107bdd 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_file_sync_service_unittest.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/sync_file_system/drive_backend/drive_file_sync_service.h"
 
-#include "base/message_loop/message_loop.h"
+#include "base/bind.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
 #include "chrome/browser/sync_file_system/drive_backend/drive_metadata_store.h"
 #include "chrome/browser/sync_file_system/drive_backend/fake_api_util.h"
 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
@@ -60,7 +60,7 @@
         base_dir_, base::MessageLoopProxy::current().get());
     bool done = false;
     metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     metadata_store_->SetSyncRootDirectory(kSyncRootResourceId);
     EXPECT_TRUE(done);
 
@@ -69,14 +69,14 @@
         base_dir_,
         scoped_ptr<APIUtilInterface>(fake_api_util_),
         scoped_ptr<DriveMetadataStore>(metadata_store_)).Pass();
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   virtual void TearDown() OVERRIDE {
     metadata_store_ = NULL;
     fake_api_util_ = NULL;
     sync_service_.reset();
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
 
     base_dir_ = base::FilePath();
     RevokeSyncableFileSystem();
@@ -172,7 +172,7 @@
   sync_service()->UninstallOrigin(
       origin_gurl,
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(done);
 
   // Assert the App's origin folder was marked as deleted.
@@ -194,7 +194,7 @@
   sync_service()->UninstallOrigin(
       origin_gurl,
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(done);
 
   // Assert the App's origin folder does not exist.
@@ -215,7 +215,7 @@
   // Pending origins that are disabled are dropped and do not go to disabled.
   sync_service()->DisableOriginForTrackingChanges(origin,
                                                   base::Bind(&ExpectOkStatus));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 0u));
 }
 
@@ -229,7 +229,7 @@
 
   sync_service()->DisableOriginForTrackingChanges(origin,
                                                   base::Bind(&ExpectOkStatus));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 1u));
 }
 
@@ -246,7 +246,7 @@
   // origins > 0.
   sync_service()->EnableOriginForTrackingChanges(origin,
                                                  base::Bind(&ExpectOkStatus));
-  base::MessageLoop::current()->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(VerifyOriginStatusCount(0u, 1u, 0u));
 }
 
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_api_util.cc b/chrome/browser/sync_file_system/drive_backend/fake_api_util.cc
index c8e01a1..88ce414 100644
--- a/chrome/browser/sync_file_system/drive_backend/fake_api_util.cc
+++ b/chrome/browser/sync_file_system/drive_backend/fake_api_util.cc
@@ -10,6 +10,7 @@
 #include "base/location.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "chrome/browser/google_apis/drive_entry_kinds.h"
+#include "webkit/common/blob/scoped_file.h"
 
 namespace sync_file_system {
 namespace drive_backend {
@@ -145,7 +146,6 @@
 
 void FakeAPIUtil::DownloadFile(const std::string& resource_id,
                                const std::string& local_file_md5,
-                               const base::FilePath& local_file_path,
                                const DownloadFileCallback& callback) {
   RemoteResourceByResourceId::iterator found =
       remote_resources_.find(resource_id);
@@ -163,9 +163,12 @@
     error = google_apis::HTTP_SUCCESS;
   }
 
+  scoped_ptr<webkit_blob::ScopedFile> dummy_local_file(
+      new webkit_blob::ScopedFile);
   base::MessageLoopProxy::current()->PostTask(
       FROM_HERE,
-      base::Bind(callback, error, file_md5, file_size, updated_time));
+      base::Bind(callback, error, file_md5, file_size, updated_time,
+                 base::Passed(&dummy_local_file)));
 }
 
 void FakeAPIUtil::UploadNewFile(const std::string& directory_resource_id,
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_api_util.h b/chrome/browser/sync_file_system/drive_backend/fake_api_util.h
index 52c201e..3c5a552 100644
--- a/chrome/browser/sync_file_system/drive_backend/fake_api_util.h
+++ b/chrome/browser/sync_file_system/drive_backend/fake_api_util.h
@@ -79,7 +79,6 @@
                                const ResourceListCallback& callback) OVERRIDE;
   virtual void DownloadFile(const std::string& resource_id,
                             const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
                             const DownloadFileCallback& callback) OVERRIDE;
   virtual void UploadNewFile(const std::string& directory_resource_id,
                              const base::FilePath& local_file_path,
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_api_util_unittest.cc b/chrome/browser/sync_file_system/drive_backend/fake_api_util_unittest.cc
index 88a7ede..a0239cd 100644
--- a/chrome/browser/sync_file_system/drive_backend/fake_api_util_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/fake_api_util_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/common/blob/scoped_file.h"
 
 namespace sync_file_system {
 namespace drive_backend {
@@ -22,7 +23,8 @@
                      google_apis::GDataErrorCode error,
                      const std::string& file_md5,
                      int64 file_size,
-                     const base::Time& updated_time) {
+                     const base::Time& updated_time,
+                     scoped_ptr<webkit_blob::ScopedFile> downloaded_file) {
   *error_out = error;
   *file_md5_out = file_md5;
 }
@@ -55,7 +57,6 @@
   std::string kMD5_1("md5 1");
   std::string kMD5_2("md5 2");
   std::string kMD5_3("md5 3");
-  base::FilePath kTempFilePath(FILE_PATH_LITERAL("tmp_file"));
 
   api_util.PushRemoteChange(kParentResourceId,
                             kParentTitle,
@@ -97,7 +98,6 @@
   std::string md5;
   api_util.DownloadFile(kResourceId1,
                         kMD5_1,
-                        kTempFilePath,
                         base::Bind(DidDownloadFile, &error, &md5));
   message_loop.RunUntilIdle();
   EXPECT_EQ(google_apis::HTTP_NOT_FOUND, error);
diff --git a/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc
index fa1cbc9..2377974 100644
--- a/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc
+++ b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc
@@ -15,20 +15,6 @@
 
 namespace {
 
-bool CreateTemporaryFile(const base::FilePath& dir_path,
-                         webkit_blob::ScopedFile* temp_file) {
-  base::FilePath temp_file_path;
-  const bool success = file_util::CreateDirectory(dir_path) &&
-      file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path);
-  if (!success)
-    return success;
-  *temp_file =
-      webkit_blob::ScopedFile(temp_file_path,
-                              webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
-                              base::MessageLoopProxy::current().get());
-  return success;
-}
-
 void EmptyStatusCallback(sync_file_system::SyncStatusCode status) {}
 
 }  // namespace
@@ -201,25 +187,6 @@
 }
 
 void RemoteSyncDelegate::DownloadFile(const SyncStatusCallback& callback) {
-  content::BrowserThread::PostTaskAndReplyWithResult(
-      content::BrowserThread::FILE, FROM_HERE,
-      base::Bind(&CreateTemporaryFile,
-                 sync_service_->temporary_file_dir_,
-                 &temporary_file_),
-      base::Bind(&RemoteSyncDelegate::DidGetTemporaryFileForDownload,
-                 AsWeakPtr(), callback));
-}
-
-void RemoteSyncDelegate::DidGetTemporaryFileForDownload(
-    const SyncStatusCallback& callback,
-    bool success) {
-  if (!success) {
-    AbortSync(callback, SYNC_FILE_ERROR_FAILED);
-    return;
-  }
-
-  DCHECK(!temporary_file_.path().empty());
-
   // We should not use the md5 in metadata for FETCH type to avoid the download
   // finishes due to NOT_MODIFIED.
   std::string md5_checksum;
@@ -229,7 +196,6 @@
   api_util()->DownloadFile(
       remote_change_.resource_id,
       md5_checksum,
-      temporary_file_.path(),
       base::Bind(&RemoteSyncDelegate::DidDownloadFile,
                  AsWeakPtr(),
                  callback));
@@ -240,7 +206,8 @@
     google_apis::GDataErrorCode error,
     const std::string& md5_checksum,
     int64 file_size,
-    const base::Time& updated_time) {
+    const base::Time& updated_time,
+    scoped_ptr<webkit_blob::ScopedFile> downloaded_file) {
   if (error == google_apis::HTTP_NOT_MODIFIED) {
     sync_action_ = SYNC_ACTION_NONE;
     DidApplyRemoteChange(callback, SYNC_STATUS_OK);
@@ -253,6 +220,7 @@
     return;
   }
 
+  temporary_file_ = downloaded_file->Pass();
   drive_metadata_.set_md5_checksum(md5_checksum);
   remote_change_processor()->ApplyRemoteChange(
       remote_file_change(), temporary_file_.path(), url(),
diff --git a/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h
index 5d8ccda..ff48cea 100644
--- a/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h
+++ b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h
@@ -56,13 +56,12 @@
                             SyncStatusCode status);
   void DeleteMetadata(const SyncStatusCallback& callback);
   void DownloadFile(const SyncStatusCallback& callback);
-  void DidGetTemporaryFileForDownload(const SyncStatusCallback& callback,
-                                      bool success);
   void DidDownloadFile(const SyncStatusCallback& callback,
                        google_apis::GDataErrorCode error,
                        const std::string& md5_checksum,
                        int64 file_size,
-                       const base::Time& updated_time);
+                       const base::Time& updated_time,
+                       scoped_ptr<webkit_blob::ScopedFile> downloaded_file);
   void HandleConflict(const SyncStatusCallback& callback,
                       SyncFileType remote_file_type);
   void HandleLocalWin(const SyncStatusCallback& callback);
diff --git a/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc
index 59722dc..9f19923 100644
--- a/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc
@@ -14,6 +14,9 @@
 #include "chrome/browser/sync_file_system/mock_local_change_processor.h"
 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/browser/fileapi/file_system_context.h"
@@ -27,6 +30,7 @@
 #include "webkit/browser/fileapi/syncable/sync_status_code.h"
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
 
+using content::BrowserThread;
 using fileapi::FileSystemURL;
 using ::testing::_;
 using ::testing::AtLeast;
@@ -95,19 +99,18 @@
     : public testing::Test,
       public LocalFileSyncService::Observer {
  protected:
-  LocalFileSyncServiceTest() : num_changes_(0) {}
-
-  virtual ~LocalFileSyncServiceTest() {}
+  LocalFileSyncServiceTest()
+      : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD |
+                        content::TestBrowserThreadBundle::REAL_IO_THREAD),
+        num_changes_(0) {}
 
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 
-    thread_helper_.SetUp();
-
     file_system_.reset(new CannedSyncableFileSystem(
         GURL(kOrigin),
-        thread_helper_.io_task_runner(),
-        thread_helper_.file_task_runner()));
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
 
     local_service_.reset(new LocalFileSyncService(&profile_));
 
@@ -132,8 +135,7 @@
     local_service_->Shutdown();
     file_system_->TearDown();
     RevokeSyncableFileSystem();
-
-    thread_helper_.TearDown();
+    content::RunAllPendingInMessageLoop(BrowserThread::FILE);
   }
 
   // LocalChangeObserver overrides.
@@ -173,11 +175,11 @@
     return file_system_->file_system_context()->change_tracker()->num_changes();
   }
 
+  content::TestBrowserThreadBundle thread_bundle_;
+
   ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
   TestingProfile profile_;
 
-  MultiThreadTestHelper thread_helper_;
-
   base::ScopedTempDir temp_dir_;
 
   scoped_ptr<CannedSyncableFileSystem> file_system_;
@@ -277,9 +279,10 @@
 
 TEST_F(LocalFileSyncServiceTest, MAYBE_LocalChangeObserverMultipleContexts) {
   const char kOrigin2[] = "http://foo";
-  CannedSyncableFileSystem file_system2(GURL(kOrigin2),
-                                        thread_helper_.io_task_runner(),
-                                        thread_helper_.file_task_runner());
+  CannedSyncableFileSystem file_system2(
+      GURL(kOrigin2),
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
   file_system2.SetUp();
 
   base::RunLoop run_loop;
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
index 6661bb1..7e3c543 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
@@ -15,6 +15,9 @@
 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/syncable/canned_syncable_file_system.h"
@@ -25,6 +28,7 @@
 #include "webkit/browser/fileapi/syncable/sync_status_code.h"
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
 
+using content::BrowserThread;
 using fileapi::FileSystemURL;
 using fileapi::FileSystemURLSet;
 using ::testing::AnyNumber;
@@ -63,11 +67,11 @@
 }
 
 // This is called on IO thread.
-void VerifyFileError(base::WaitableEvent* event,
+void VerifyFileError(base::RunLoop* run_loop,
                      base::PlatformFileError error) {
-  DCHECK(event);
+  DCHECK(run_loop);
   EXPECT_EQ(base::PLATFORM_FILE_OK, error);
-  event->Signal();
+  run_loop->Quit();
 }
 
 }  // namespace
@@ -112,16 +116,15 @@
 
 class SyncFileSystemServiceTest : public testing::Test {
  protected:
-  SyncFileSystemServiceTest() {}
-  virtual ~SyncFileSystemServiceTest() {}
+  SyncFileSystemServiceTest()
+      : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD |
+                       content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
 
   virtual void SetUp() OVERRIDE {
-    thread_helper_.SetUp();
-
     file_system_.reset(new CannedSyncableFileSystem(
         GURL(kOrigin),
-        thread_helper_.io_task_runner(),
-        thread_helper_.file_task_runner()));
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
 
     local_service_ = new LocalFileSyncService(&profile_);
     remote_service_ = new StrictMock<MockRemoteFileSyncService>;
@@ -150,10 +153,9 @@
 
   virtual void TearDown() OVERRIDE {
     sync_service_->Shutdown();
-
     file_system_->TearDown();
     RevokeSyncableFileSystem();
-    thread_helper_.TearDown();
+    content::RunAllPendingInMessageLoop(BrowserThread::FILE);
   }
 
   void InitializeApp() {
@@ -237,7 +239,7 @@
 
   ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
 
-  MultiThreadTestHelper thread_helper_;
+  content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   scoped_ptr<CannedSyncableFileSystem> file_system_;
 
@@ -392,17 +394,20 @@
   mock_remote_service()->NotifyRemoteChangeQueueUpdated(1);
 
   // Start a local operation on the same file (to make it BUSY).
-  base::WaitableEvent event(false, false);
-  thread_helper_.io_task_runner()->PostTask(
-      FROM_HERE, base::Bind(&CannedSyncableFileSystem::DoCreateFile,
-                            base::Unretained(file_system_.get()),
-                            kFile, base::Bind(&VerifyFileError, &event)));
+  base::RunLoop verify_file_error_run_loop;
+  BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&CannedSyncableFileSystem::DoCreateFile,
+                 base::Unretained(file_system_.get()),
+                 kFile, base::Bind(&VerifyFileError,
+                                   &verify_file_error_run_loop)));
 
   run_loop.Run();
 
   mock_remote_service()->NotifyRemoteChangeQueueUpdated(0);
 
-  event.Wait();
+  verify_file_error_run_loop.Run();
 }
 
 TEST_F(SyncFileSystemServiceTest, GetFileSyncStatus) {
diff --git a/chrome/browser/sync_file_system/sync_file_system_test_util.cc b/chrome/browser/sync_file_system/sync_file_system_test_util.cc
index 1f0c214..ccb5684 100644
--- a/chrome/browser/sync_file_system/sync_file_system_test_util.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_test_util.cc
@@ -9,12 +9,11 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
-#include "content/public/test/test_browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_utils.h"
 #include "webkit/browser/fileapi/syncable/sync_status_code.h"
 
 using content::BrowserThread;
-using content::TestBrowserThread;
 
 namespace sync_file_system {
 
@@ -35,30 +34,4 @@
 template base::Callback<void(SyncStatusCode)>
 AssignAndQuitCallback(base::RunLoop*, SyncStatusCode*);
 
-MultiThreadTestHelper::MultiThreadTestHelper()
-    : thread_bundle_(new content::TestBrowserThreadBundle(
-          content::TestBrowserThreadBundle::REAL_FILE_THREAD |
-          content::TestBrowserThreadBundle::REAL_IO_THREAD)) {
-}
-
-MultiThreadTestHelper::~MultiThreadTestHelper() {}
-
-void MultiThreadTestHelper::SetUp() {
-  ui_task_runner_ =
-      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
-  file_task_runner_ =
-      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE);
-  io_task_runner_ =
-      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
-}
-
-void MultiThreadTestHelper::TearDown() {
-  // Make sure we give some more time to finish tasks on the FILE thread
-  // before stopping IO/FILE threads.
-  base::RunLoop run_loop;
-  file_task_runner_->PostTaskAndReply(
-      FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure());
-  run_loop.Run();
-}
-
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/sync_file_system_test_util.h b/chrome/browser/sync_file_system/sync_file_system_test_util.h
index 85152d3..a7c33fa 100644
--- a/chrome/browser/sync_file_system/sync_file_system_test_util.h
+++ b/chrome/browser/sync_file_system/sync_file_system_test_util.h
@@ -5,19 +5,15 @@
 #ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_FILE_SYSTEM_TEST_UTIL_H_
 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_FILE_SYSTEM_TEST_UTIL_H_
 
+#include "base/callback_forward.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
 
 namespace base {
 class RunLoop;
 class SingleThreadTaskRunner;
 }
 
-namespace content {
-class TestBrowserThreadBundle;
-}
-
 namespace sync_file_system {
 
 template <typename R>
@@ -26,36 +22,6 @@
 template <typename R> base::Callback<void(R)>
 AssignAndQuitCallback(base::RunLoop* run_loop, R* result);
 
-// This sets up FILE, IO and UI browser threads for testing.
-// (UI thread is set to the current thread.)
-class MultiThreadTestHelper {
- public:
-  MultiThreadTestHelper();
-  ~MultiThreadTestHelper();
-
-  void SetUp();
-  void TearDown();
-
-  base::SingleThreadTaskRunner* ui_task_runner() {
-    return ui_task_runner_.get();
-  }
-
-  base::SingleThreadTaskRunner* file_task_runner() {
-    return file_task_runner_.get();
-  }
-
-  base::SingleThreadTaskRunner* io_task_runner() {
-    return io_task_runner_.get();
-  }
-
- private:
-  scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-};
-
 }  // namespace sync_file_system
 
 #endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_FILE_SYSTEM_TEST_UTIL_H_
diff --git a/chrome/browser/tab_contents/spelling_menu_observer_browsertest.cc b/chrome/browser/tab_contents/spelling_menu_observer_browsertest.cc
index 81dbb20..ae5c0a0 100644
--- a/chrome/browser/tab_contents/spelling_menu_observer_browsertest.cc
+++ b/chrome/browser/tab_contents/spelling_menu_observer_browsertest.cc
@@ -62,11 +62,6 @@
   virtual WebContents* GetWebContents() const OVERRIDE;
   virtual Profile* GetProfile() const OVERRIDE;
 
-  // Create a testing URL request context.
-  void CreateRequestContext() {
-    profile_->CreateRequestContext();
-  }
-
   // Attaches a RenderViewContextMenuObserver to be tested.
   void SetObserver(RenderViewContextMenuObserver* observer);
 
@@ -327,9 +322,6 @@
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   command_line->AppendSwitch(switches::kUseSpellingSuggestions);
 
-  // Make sure we can pretend to handle the JSON request.
-  menu()->CreateRequestContext();
-
   // Force a non-empty locale so SUGGEST is available.
   menu()->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "en");
   EXPECT_TRUE(SpellingServiceClient::IsAvailable(menu()->GetProfile(),
@@ -370,9 +362,6 @@
                        NoMoreSuggestionsNotDisplayed) {
   menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, true);
 
-  // Make sure we can pretend to handle the JSON request.
-  menu()->CreateRequestContext();
-
   // Force a non-empty locale so SPELLCHECK is available.
   menu()->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "en");
   EXPECT_TRUE(SpellingServiceClient::IsAvailable(menu()->GetProfile(),
@@ -478,7 +467,6 @@
   menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, true);
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   command_line->AppendSwitch(switches::kUseSpellingSuggestions);
-  menu()->CreateRequestContext();
   InitMenu("asdfkj", NULL);
 
   // Should have at least 2 entries. Separator, suggestion.
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index 8c5bae6..3dbbb7f 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -107,6 +107,7 @@
     case IDS_TASK_MANAGER_CPU_COLUMN:
     case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
     case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
+    case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN:
     case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
     case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
     case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
@@ -503,9 +504,7 @@
   if (!GetVideoMemory(index, &video_memory, &has_duplicates) || !video_memory)
     return ASCIIToUTF16("N/A");
   if (has_duplicates) {
-    return ASCIIToUTF16("(") +
-        GetMemCellText(video_memory) +
-        ASCIIToUTF16(")");
+    return GetMemCellText(video_memory) + ASCIIToUTF16("*");
   }
   return GetMemCellText(video_memory);
 }
diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc
index 057084e..70d9210 100644
--- a/chrome/browser/translate/translate_manager.cc
+++ b/chrome/browser/translate/translate_manager.cc
@@ -84,6 +84,10 @@
 }  // namespace
 
 TranslateManager::~TranslateManager() {
+  // CleanupPendingUrlFetcher should be called ahead of destructing.
+  DCHECK(language_list_.get() == NULL);
+  DCHECK(script_.get() == NULL);
+
   weak_method_factory_.InvalidateWeakPtrs();
 }
 
@@ -634,7 +638,7 @@
     NOTREACHED();
 }
 
-void TranslateManager::CleanupPendingUlrFetcher() {
+void TranslateManager::CleanupPendingUrlFetcher() {
   language_list_.reset();
   script_.reset();
 }
diff --git a/chrome/browser/translate/translate_manager.h b/chrome/browser/translate/translate_manager.h
index 8355ab1..da673f7 100644
--- a/chrome/browser/translate/translate_manager.h
+++ b/chrome/browser/translate/translate_manager.h
@@ -92,7 +92,7 @@
 
   // Allows caller to cleanup pending URLFetcher objects to make sure they
   // get released in the appropriate thread... Mainly for tests.
-  void CleanupPendingUlrFetcher();
+  void CleanupPendingUrlFetcher();
 
   // Translates the page contents from |source_lang| to |target_lang|.
   // The actual translation might be performed asynchronously if the translate
diff --git a/chrome/browser/ui/app_list/search/webstore_provider.cc b/chrome/browser/ui/app_list/search/webstore_provider.cc
index 0a0d14f..479ded0 100644
--- a/chrome/browser/ui/app_list/search/webstore_provider.cc
+++ b/chrome/browser/ui/app_list/search/webstore_provider.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/metrics/field_trial.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -26,6 +27,13 @@
 const char kKeyLocalizedName[] = "localized_name";
 const char kKeyIconUrl[] = "icon_url";
 
+// Returns true if the launcher should send queries to the web store server.
+bool UseWebstoreSearch() {
+  const char kFieldTrialName[] = "LauncherUseWebstoreSearch";
+  const char kEnable[] = "Enable";
+  return base::FieldTrialList::FindFullName(kFieldTrialName) == kEnable;
+}
+
 }  // namespace
 
 WebstoreProvider::WebstoreProvider(Profile* profile,
@@ -36,16 +44,18 @@
 WebstoreProvider::~WebstoreProvider() {}
 
 void WebstoreProvider::Start(const base::string16& query) {
-  if (!webstore_search_) {
-    webstore_search_.reset(new WebstoreSearchFetcher(
-        base::Bind(&WebstoreProvider::OnWebstoreSearchFetched,
-                   base::Unretained(this)),
-        profile_->GetRequestContext()));
-  }
-
   const std::string query_utf8 = UTF16ToUTF8(query);
-  webstore_search_->Start(query_utf8,
-                          g_browser_process->GetApplicationLocale());
+
+  if (UseWebstoreSearch()) {
+    if (!webstore_search_) {
+      webstore_search_.reset(new WebstoreSearchFetcher(
+          base::Bind(&WebstoreProvider::OnWebstoreSearchFetched,
+                     base::Unretained(this)),
+          profile_->GetRequestContext()));
+    }
+    webstore_search_->Start(query_utf8,
+                            g_browser_process->GetApplicationLocale());
+  }
 
   // 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.
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 2399091..b60133a 100644
--- a/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
+++ b/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
@@ -35,6 +35,11 @@
   virtual ~WebstoreProviderTest() {}
 
   // InProcessBrowserTest overrides:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
+                                    "LauncherUseWebstoreSearch/Enable/");
+  }
+
   virtual void SetUpOnMainThread() OVERRIDE {
     test_server_.reset(new EmbeddedTestServer(
         BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
diff --git a/chrome/browser/ui/ash/ime_controller_chromeos.cc b/chrome/browser/ui/ash/ime_controller_chromeos.cc
index 239b1d0..fca4702 100644
--- a/chrome/browser/ui/ash/ime_controller_chromeos.cc
+++ b/chrome/browser/ui/ash/ime_controller_chromeos.cc
@@ -13,10 +13,10 @@
   return manager->SwitchToNextInputMethod();
 }
 
-bool ImeController::HandlePreviousIme() {
+bool ImeController::HandlePreviousIme(const ui::Accelerator& accelerator) {
   chromeos::input_method::InputMethodManager* manager =
       chromeos::input_method::InputMethodManager::Get();
-  return manager->SwitchToPreviousInputMethod();
+  return manager->SwitchToPreviousInputMethod(accelerator);
 }
 
 bool ImeController::HandleSwitchIme(const ui::Accelerator& accelerator) {
diff --git a/chrome/browser/ui/ash/ime_controller_chromeos.h b/chrome/browser/ui/ash/ime_controller_chromeos.h
index e0f2e64..bdfa28e 100644
--- a/chrome/browser/ui/ash/ime_controller_chromeos.h
+++ b/chrome/browser/ui/ash/ime_controller_chromeos.h
@@ -18,7 +18,7 @@
 
   // Overridden from ash::ImeControlDelegate:
   virtual bool HandleNextIme() OVERRIDE;
-  virtual bool HandlePreviousIme() OVERRIDE;
+  virtual bool HandlePreviousIme(const ui::Accelerator& accelerator) OVERRIDE;
   virtual bool HandleSwitchIme(const ui::Accelerator& accelerator) OVERRIDE;
   virtual ui::Accelerator RemapAccelerator(
       const ui::Accelerator& accelerator) OVERRIDE;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc
index 5d73e33..f91430b 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_system.h"
@@ -23,7 +23,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_CHROMEOS)
@@ -38,9 +38,7 @@
 class ChromeLauncherControllerPerBrowserTest : public testing::Test {
  protected:
   ChromeLauncherControllerPerBrowserTest()
-      : ui_thread_(content::BrowserThread::UI, &loop_),
-        file_thread_(content::BrowserThread::FILE, &loop_),
-        profile_(new TestingProfile()),
+      : profile_(new TestingProfile()),
         extension_service_(NULL) {
     DictionaryValue manifest;
     manifest.SetString("name", "launcher controller test extension");
@@ -81,7 +79,7 @@
   virtual void TearDown() OVERRIDE {
     profile_.reset();
     // Execute any pending deletion tasks.
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
   }
 
   void InsertPrefValue(base::ListValue* pref_value,
@@ -145,9 +143,7 @@
   }
 
   // Needed for extension service & friends to work.
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
 #if defined OS_CHROMEOS
   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
index 8066568..dbcf723 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
 #include "ui/aura/root_window.h"
 
 class TestChromeLauncherControllerPerBrowser :
@@ -39,8 +38,7 @@
   }
 
   LauncherContextMenuTest()
-      : profile_(new TestingProfile()),
-        browser_thread_(content::BrowserThread::UI, message_loop()) {}
+      : profile_(new TestingProfile()) {}
 
   virtual void SetUp() OVERRIDE {
     ash::test::AshTestBase::SetUp();
@@ -66,7 +64,6 @@
 
  private:
   scoped_ptr<TestingProfile> profile_;
-  content::TestBrowserThread browser_thread_;
   ash::LauncherModel launcher_model_;
   scoped_ptr<ChromeLauncherController> controller_;
 
diff --git a/chrome/browser/ui/ash/screenshot_taker_unittest.cc b/chrome/browser/ui/ash/screenshot_taker_unittest.cc
index 6eac784..ed8ffd1 100644
--- a/chrome/browser/ui/ash/screenshot_taker_unittest.cc
+++ b/chrome/browser/ui/ash/screenshot_taker_unittest.cc
@@ -18,7 +18,6 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_utils.h"
 #include "ui/aura/root_window.h"
 #include "ui/message_center/message_center_switches.h"
@@ -30,8 +29,7 @@
                             public ScreenshotTakerObserver {
  public:
   ScreenshotTakerTest()
-      : ui_thread_(content::BrowserThread::UI, message_loop()),
-        running_(false),
+      : running_(false),
         screenshot_complete_(false),
         screenshot_result_(ScreenshotTakerObserver::SCREENSHOT_SUCCESS) {
   }
@@ -90,7 +88,6 @@
   }
 
   scoped_ptr<ScopedTestingLocalState> local_state_;
-  content::TestBrowserThread ui_thread_;
   bool running_;
   bool screenshot_complete_;
   ScreenshotTakerObserver::Result screenshot_result_;
diff --git a/chrome/browser/ui/ash/volume_controller_chromeos.cc b/chrome/browser/ui/ash/volume_controller_chromeos.cc
index db93e82..6779b95 100644
--- a/chrome/browser/ui/ash/volume_controller_chromeos.cc
+++ b/chrome/browser/ui/ash/volume_controller_chromeos.cc
@@ -86,7 +86,8 @@
 
     if (audio_handler->IsOutputMuted())
       audio_handler->SetOutputMute(false);
-    audio_handler->AdjustOutputVolumeByPercent(kStepPercentage);
+    else
+      audio_handler->AdjustOutputVolumeByPercent(kStepPercentage);
     return true;
   }
 
diff --git a/chrome/browser/ui/ash/window_positioner_unittest.cc b/chrome/browser/ui/ash/window_positioner_unittest.cc
index 157678f..3842e2a 100644
--- a/chrome/browser/ui/ash/window_positioner_unittest.cc
+++ b/chrome/browser/ui/ash/window_positioner_unittest.cc
@@ -16,7 +16,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/render_view_test.h"
-#include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/env.h"
 #include "ui/aura/root_window.h"
@@ -59,7 +58,6 @@
 class WindowPositionerTest : public AshTestBase {
  public:
   WindowPositionerTest();
-  virtual ~WindowPositionerTest();
 
   virtual void SetUp() OVERRIDE;
   virtual void TearDown() OVERRIDE;
@@ -80,8 +78,7 @@
   WindowPositioner* window_positioner_;
 
   // These two need to be deleted after everything else is gone.
-  scoped_ptr<content::TestBrowserThread> ui_thread_;
-  scoped_ptr<TestingProfile> profile_;
+  TestingProfile profile_;
 
   // These get created for each session.
   scoped_ptr<aura::Window> window_;
@@ -99,18 +96,6 @@
 WindowPositionerTest::WindowPositionerTest()
     : grid_size_(WindowPositioner::kMinimumWindowOffset),
       window_positioner_(NULL) {
-  // Create a message loop.
-  base::MessageLoopForUI* ui_loop = message_loop();
-  ui_thread_.reset(
-      new content::TestBrowserThread(content::BrowserThread::UI, ui_loop));
-
-  // Create a browser profile.
-  profile_.reset(new TestingProfile());
-}
-
-WindowPositionerTest::~WindowPositionerTest() {
-  profile_.reset(NULL);
-  ui_thread_.reset(NULL);
 }
 
 void WindowPositionerTest::SetUp() {
@@ -123,14 +108,14 @@
 
   // Create a browser for the window.
   browser_window_.reset(new TestBrowserWindowAura(window_.get()));
-  Browser::CreateParams window_params(profile_.get(),
+  Browser::CreateParams window_params(&profile_,
                                       chrome::HOST_DESKTOP_TYPE_ASH);
   window_params.window = browser_window_.get();
   window_owning_browser_.reset(new Browser(window_params));
 
   // Creating a browser for the popup.
   browser_popup_.reset(new TestBrowserWindowAura(popup_.get()));
-  Browser::CreateParams popup_params(Browser::TYPE_POPUP, profile_.get(),
+  Browser::CreateParams popup_params(Browser::TYPE_POPUP, &profile_,
                                      chrome::HOST_DESKTOP_TYPE_ASH);
   popup_params.window = browser_popup_.get();
   popup_owning_browser_.reset(new Browser(popup_params));
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index 142e7d0..a647868 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -320,7 +320,6 @@
   // testing::Test implementation:
   virtual void SetUp() OVERRIDE {
     ChromeRenderViewHostTestHarness::SetUp();
-    profile()->CreateRequestContext();
 
     test_bubble_controller_ =
         new testing::NiceMock<TestAutofillCreditCardBubbleController>(
@@ -342,7 +341,6 @@
   void Reset() {
     if (controller_)
       controller_->ViewClosed();
-    profile()->CreateRequestContext();
 
     test_bubble_controller_ =
         new testing::NiceMock<TestAutofillCreditCardBubbleController>(
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
index ddf8415..c248a37 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/files/file_path.h"
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_result.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -30,6 +31,7 @@
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -231,16 +233,41 @@
 
   ui_test_utils::NavigateToURL(browser(), GetTestURL());
 
+  // Wait until the request actually has hit the popup blocker. The
+  // NavigateToURL call above returns as soon as the main tab stopped loading
+  // which can happen before the popup request was processed.
+  WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  PopupBlockerTabHelper* popup_blocker_helper =
+      PopupBlockerTabHelper::FromWebContents(web_contents);
+  if (!popup_blocker_helper->GetBlockedPopupsCount()) {
+    content::WindowedNotificationObserver observer(
+        chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
+        content::NotificationService::AllSources());
+    observer.Wait();
+  }
+
   // 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(GetTestURL(), web_contents->GetURL());
 
   // And no new RVH created.
   EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
+
+  content::WindowedNotificationObserver observer(
+      chrome::NOTIFICATION_TAB_ADDED,
+      content::NotificationService::AllSources());
+
+  // 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());
+
+  observer.Wait();
 }
 
 IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest,
@@ -280,4 +307,92 @@
   observer.Wait();
 }
 
+IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest, WindowFeatures) {
+  GURL url(ui_test_utils::GetTestUrl(
+      base::FilePath(kTestDir),
+      base::FilePath(FILE_PATH_LITERAL("popup-window-open.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());
+  IDMap<chrome::NavigateParams, IDMapOwnPointer>::const_iterator iter(
+      &popup_blocker_helper->GetBlockedPopupRequests());
+  ASSERT_FALSE(iter.IsAtEnd());
+  popup_blocker_helper->ShowBlockedPopup(iter.GetCurrentKey());
+
+  observer.Wait();
+  Browser* new_browser = browser_observer.WaitForSingleNewBrowser();
+
+  // Check that the new popup has (roughly) the requested size.
+  web_contents = new_browser->tab_strip_model()->GetActiveWebContents();
+  gfx::Size window_size = web_contents->GetView()->GetContainerSize();
+  EXPECT_TRUE(349 <= window_size.width() && window_size.width() <= 351);
+  EXPECT_TRUE(249 <= window_size.height() && window_size.height() <= 251);
+}
+
+IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest, CorrectReferrer) {
+  GURL url(ui_test_utils::GetTestUrl(
+      base::FilePath(kTestDir),
+      base::FilePath(FILE_PATH_LITERAL("popup-referrer.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());
+  IDMap<chrome::NavigateParams, IDMapOwnPointer>::const_iterator iter(
+      &popup_blocker_helper->GetBlockedPopupRequests());
+  ASSERT_FALSE(iter.IsAtEnd());
+  popup_blocker_helper->ShowBlockedPopup(iter.GetCurrentKey());
+
+  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());
+}
+
 }  // namespace
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index bd0799f..852fd4d 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -179,6 +179,7 @@
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/url_request/url_request_context.h"
+#include "third_party/WebKit/public/web/WebWindowFeatures.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/gfx/point.h"
@@ -216,6 +217,7 @@
 using extensions::Extension;
 using ui::WebDialogDelegate;
 using web_modal::WebContentsModalDialogManager;
+using WebKit::WebWindowFeatures;
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -1481,8 +1483,11 @@
     WindowContainerType window_container_type,
     const string16& frame_name,
     const GURL& target_url,
+    const content::Referrer& referrer,
     WindowOpenDisposition disposition,
-    bool user_gesture) {
+    const WebWindowFeatures& features,
+    bool user_gesture,
+    bool opener_suppressed) {
   if (window_container_type == WINDOW_CONTAINER_TYPE_BACKGROUND) {
     // If a BackgroundContents is created, suppress the normal WebContents.
     return !MaybeCreateBackgroundContents(
@@ -1505,12 +1510,29 @@
           switches::kDisablePopupBlocking)) {
     chrome::NavigateParams nav_params(
         this, target_url, content::PAGE_TRANSITION_LINK);
-    // TODO(jochen): route missing information to here:
-    //   referrer, extra_headers, override_encoding
-    nav_params.source_contents = web_contents;
-    nav_params.tabstrip_add_types = TabStripModel::ADD_NONE;
+    // TODO(jochen): route window features here.
+    nav_params.referrer = referrer;
+    if (!opener_suppressed)
+      nav_params.source_contents = web_contents;
+    nav_params.is_renderer_initiated = true;
+    nav_params.tabstrip_add_types = TabStripModel::ADD_ACTIVE;
     nav_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
     nav_params.user_gesture = user_gesture;
+    web_contents->GetView()->GetContainerBounds(&nav_params.window_bounds);
+    if (features.xSet)
+      nav_params.window_bounds.set_x(features.x);
+    if (features.ySet)
+      nav_params.window_bounds.set_y(features.y);
+    if (features.widthSet)
+      nav_params.window_bounds.set_width(features.width);
+    if (features.heightSet)
+      nav_params.window_bounds.set_height(features.height);
+
+    // Compare RenderViewImpl::show().
+    if (!user_gesture && disposition != NEW_BACKGROUND_TAB)
+      nav_params.disposition = NEW_POPUP;
+    else
+      nav_params.disposition = disposition;
 
     return !popup_blocker_helper->MaybeBlockPopup(nav_params);
   }
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 61be1dd..a26587d 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -566,8 +566,11 @@
       WindowContainerType window_container_type,
       const string16& frame_name,
       const GURL& target_url,
+      const content::Referrer& referrer,
       WindowOpenDisposition disposition,
-      bool user_action) OVERRIDE;
+      const WebKit::WebWindowFeatures& features,
+      bool user_action,
+      bool opener_suppressed) OVERRIDE;
   virtual void WebContentsCreated(content::WebContents* source_contents,
                                   int64 source_frame_id,
                                   const string16& frame_name,
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm b/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm
index 8f4f659..58c279f 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm
@@ -58,7 +58,6 @@
   virtual void SetUp() OVERRIDE {
     ChromeRenderViewHostTestHarness::SetUp();
     CocoaTest::BootstrapCocoa();
-    profile()->CreateRequestContext();
     Browser::CreateParams native_params(profile(), chrome::GetActiveDesktop());
     browser_.reset(
         chrome::CreateBrowserWithTestWindowForParams(&native_params));
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc
index 904c791..33bcea7 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc
@@ -15,11 +15,19 @@
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::kAboutBlankURL;
-using content::PAGE_TRANSITION_TYPED;
 
-// Interactive test fixture testing Fullscreen Controller through its states. --
-// See documentation at the top of fullscreen_controller_state_unittest.cc.
+// FullscreenControllerStateInteractiveTest ------------------------------------
+
+// Interactive test fixture testing Fullscreen Controller through its states.
+//
+// Used to verify that the FullscreenControllerTestWindow models the behavior
+// of actual windows accurately. The interactive tests are too flaky to run
+// on infrastructure, and so those tests are disabled. Run them with:
+//     interactive_ui_tests
+//         --gtest_filter="FullscreenControllerStateInteractiveTest.*"
+//         --gtest_also_run_disabled_tests
+//
+// More context atop fullscreen_controller_state_test.h.
 class FullscreenControllerStateInteractiveTest
     : public InProcessBrowserTest,
       public FullscreenControllerStateTest {
@@ -32,9 +40,8 @@
   return InProcessBrowserTest::browser();
 }
 
-// Tests -----------------------------------------------------------------------
 
-// Soak tests:
+// Soak tests ------------------------------------------------------------------
 
 // Tests all states with all permutations of multiple events to detect lingering
 // state issues that would bleed over to other states.
@@ -47,13 +54,14 @@
 IN_PROC_BROWSER_TEST_F(FullscreenControllerStateInteractiveTest,
                        DISABLED_TransitionsForEachState) {
   // A tab is needed for tab fullscreen.
-  AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
+  AddTabAtIndex(0, GURL(content::kAboutBlankURL),
+                content::PAGE_TRANSITION_TYPED);
   TestTransitionsForEachState();
   // Progress of test can be examined via LOG(INFO) << GetAndClearDebugLog();
 }
 
 
-// Individual tests for each pair of state and event:
+// Individual tests for each pair of state and event ---------------------------
 
 // An "empty" test is included as part of each "TEST_EVENT" because it makes
 // running the entire test suite less flaky on MacOS. All of the tests pass
@@ -64,164 +72,25 @@
     } \
     IN_PROC_BROWSER_TEST_F(FullscreenControllerStateInteractiveTest, \
                            DISABLED_##state##__##event) { \
-      AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED); \
+      AddTabAtIndex(0, GURL(content::kAboutBlankURL), \
+                    content::PAGE_TRANSITION_TYPED); \
       ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event)) \
           << GetAndClearDebugLog(); \
     }
     // Progress of tests can be examined by inserting the following line:
     // LOG(INFO) << GetAndClearDebugLog(); }
 
-TEST_EVENT(STATE_NORMAL, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_NORMAL, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_NORMAL, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_NORMAL, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_NORMAL, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_NORMAL, BUBBLE_ALLOW);
-TEST_EVENT(STATE_NORMAL, BUBBLE_DENY);
-TEST_EVENT(STATE_NORMAL, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, WINDOW_CHANGE);
-
-#if defined(OS_WIN)
-TEST_EVENT(STATE_METRO_SNAP, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_METRO_SNAP, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_FALSE);
-TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_FALSE);
-TEST_EVENT(STATE_METRO_SNAP, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_METRO_SNAP, BUBBLE_ALLOW);
-TEST_EVENT(STATE_METRO_SNAP, BUBBLE_DENY);
-TEST_EVENT(STATE_METRO_SNAP, WINDOW_CHANGE);
-#endif
-
-TEST_EVENT(STATE_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_FULLSCREEN, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TAB_FULLSCREEN, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TAB_FULLSCREEN, BUBBLE_DENY);
-TEST_EVENT(STATE_TAB_FULLSCREEN, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, BUBBLE_DENY);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_NORMAL, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_NORMAL, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_NORMAL, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_NORMAL, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_NORMAL, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_NORMAL, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, WINDOW_CHANGE);
+#include "chrome/browser/ui/fullscreen/fullscreen_controller_state_tests.h"
 
 
-// Specific one-off tests for known issues:
+// Specific one-off tests for known issues -------------------------------------
 
 // Used manually to determine what happens on a platform.
 IN_PROC_BROWSER_TEST_F(FullscreenControllerStateInteractiveTest,
                        DISABLED_ManualTest) {
   // A tab is needed for tab fullscreen.
-  AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
+  AddTabAtIndex(0, GURL(content::kAboutBlankURL),
+                content::PAGE_TRANSITION_TYPED);
   ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN)) << GetAndClearDebugLog();
   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
@@ -229,8 +98,8 @@
   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
 
   // Wait, allowing human operator to observe the result.
-  scoped_refptr<content::MessageLoopRunner> message_loop;
-  message_loop = new content::MessageLoopRunner();
+  scoped_refptr<content::MessageLoopRunner> message_loop
+      = new content::MessageLoopRunner();
   message_loop->Run();
 }
 
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc
index bbc4c23..cafbcd5 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc
@@ -198,22 +198,23 @@
       STATE_TAB_FULLSCREEN,                   // Event WINDOW_CHANGE
     },
   };
-  CHECK_EQ(sizeof(transition_table_data), sizeof(transition_table_));
+  COMPILE_ASSERT(sizeof(transition_table_data) == sizeof(transition_table_),
+                 transition_table_incorrect_size);
   memcpy(transition_table_, transition_table_data,
          sizeof(transition_table_data));
 
   // Verify that transition_table_ has been completely defined.
-  for (int source = 0; source < NUM_STATES; source++) {
-    for (int event = 0; event < NUM_EVENTS; event++) {
-      CHECK_NE(STATE_INVALID, transition_table_[source][event]);
-      CHECK_LE(0, transition_table_[source][event]);
-      CHECK_GT(NUM_STATES, transition_table_[source][event]);
+  for (int source = 0; source < NUM_STATES; ++source) {
+    for (int event = 0; event < NUM_EVENTS; ++event) {
+      EXPECT_NE(transition_table_[source][event], STATE_INVALID);
+      EXPECT_GE(transition_table_[source][event], 0);
+      EXPECT_LT(transition_table_[source][event], NUM_STATES);
     }
   }
 
   // Copy transition_table_ data into state_transitions_ table.
-  for (int source = 0; source < NUM_STATES; source++) {
-    for (int event = 0; event < NUM_EVENTS; event++) {
+  for (int source = 0; source < NUM_STATES; ++source) {
+    for (int event = 0; event < NUM_EVENTS; ++event) {
       if (ShouldSkipStateAndEventPair(static_cast<State>(source),
                                       static_cast<Event>(event)))
         continue;
@@ -231,30 +232,18 @@
 // static
 const char* FullscreenControllerStateTest::GetStateString(State state) {
   switch (state) {
-    case STATE_NORMAL:
-      return "STATE_NORMAL";
-    case STATE_BROWSER_FULLSCREEN_NO_CHROME:
-      return "STATE_BROWSER_FULLSCREEN_NO_CHROME";
-    case STATE_BROWSER_FULLSCREEN_WITH_CHROME:
-      return "STATE_BROWSER_FULLSCREEN_WITH_CHROME";
-    case STATE_METRO_SNAP:
-      return "STATE_METRO_SNAP";
-    case STATE_TAB_FULLSCREEN:
-      return "STATE_TAB_FULLSCREEN";
-    case STATE_TAB_BROWSER_FULLSCREEN:
-      return "STATE_TAB_BROWSER_FULLSCREEN";
-    case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
-      return "STATE_TAB_BROWSER_FULLSCREEN_CHROME";
-    case STATE_TO_NORMAL:
-      return "STATE_TO_NORMAL";
-    case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
-      return "STATE_TO_BROWSER_FULLSCREEN_NO_CHROME";
-    case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME:
-      return "STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME";
-    case STATE_TO_TAB_FULLSCREEN:
-      return "STATE_TO_TAB_FULLSCREEN";
-    case STATE_INVALID:
-      return "STATE_INVALID";
+    ENUM_TO_STRING(STATE_NORMAL);
+    ENUM_TO_STRING(STATE_BROWSER_FULLSCREEN_NO_CHROME);
+    ENUM_TO_STRING(STATE_BROWSER_FULLSCREEN_WITH_CHROME);
+    ENUM_TO_STRING(STATE_METRO_SNAP);
+    ENUM_TO_STRING(STATE_TAB_FULLSCREEN);
+    ENUM_TO_STRING(STATE_TAB_BROWSER_FULLSCREEN);
+    ENUM_TO_STRING(STATE_TAB_BROWSER_FULLSCREEN_CHROME);
+    ENUM_TO_STRING(STATE_TO_NORMAL);
+    ENUM_TO_STRING(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME);
+    ENUM_TO_STRING(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME);
+    ENUM_TO_STRING(STATE_TO_TAB_FULLSCREEN);
+    ENUM_TO_STRING(STATE_INVALID);
     default:
       NOTREACHED() << "No string for state " << state;
       return "State-Unknown";
@@ -264,28 +253,17 @@
 // static
 const char* FullscreenControllerStateTest::GetEventString(Event event) {
   switch (event) {
-    case TOGGLE_FULLSCREEN:
-      return "TOGGLE_FULLSCREEN";
-    case TOGGLE_FULLSCREEN_CHROME:
-      return "TOGGLE_FULLSCREEN_CHROME";
-    case TAB_FULLSCREEN_TRUE:
-      return "TAB_FULLSCREEN_TRUE";
-    case TAB_FULLSCREEN_FALSE:
-      return "TAB_FULLSCREEN_FALSE";
-    case METRO_SNAP_TRUE:
-      return "METRO_SNAP_TRUE";
-    case METRO_SNAP_FALSE:
-      return "METRO_SNAP_FALSE";
-    case BUBBLE_EXIT_LINK:
-      return "BUBBLE_EXIT_LINK";
-    case BUBBLE_ALLOW:
-      return "BUBBLE_ALLOW";
-    case BUBBLE_DENY:
-      return "BUBBLE_DENY";
-    case WINDOW_CHANGE:
-      return "WINDOW_CHANGE";
-    case EVENT_INVALID:
-      return "EVENT_INVALID";
+    ENUM_TO_STRING(TOGGLE_FULLSCREEN);
+    ENUM_TO_STRING(TOGGLE_FULLSCREEN_CHROME);
+    ENUM_TO_STRING(TAB_FULLSCREEN_TRUE);
+    ENUM_TO_STRING(TAB_FULLSCREEN_FALSE);
+    ENUM_TO_STRING(METRO_SNAP_TRUE);
+    ENUM_TO_STRING(METRO_SNAP_FALSE);
+    ENUM_TO_STRING(BUBBLE_EXIT_LINK);
+    ENUM_TO_STRING(BUBBLE_ALLOW);
+    ENUM_TO_STRING(BUBBLE_DENY);
+    ENUM_TO_STRING(WINDOW_CHANGE);
+    ENUM_TO_STRING(EVENT_INVALID);
     default:
       NOTREACHED() << "No string for event " << event;
       return "Event-Unknown";
@@ -293,7 +271,7 @@
 }
 
 // static
-bool FullscreenControllerStateTest::IsReentrant() {
+bool FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant() {
 #if defined(TOOLKIT_VIEWS)
   return true;
 #else
@@ -312,11 +290,13 @@
     case STATE_TAB_BROWSER_FULLSCREEN:
     case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
       return true;
+
     case STATE_TO_NORMAL:
     case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
     case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME:
     case STATE_TO_TAB_FULLSCREEN:
       return false;
+
     default:
       NOTREACHED();
       return false;
@@ -378,13 +358,13 @@
 
   // When simulating reentrant window change calls, expect the next state
   // automatically.
-  if (IsReentrant())
+  if (IsWindowFullscreenStateChangedReentrant())
     next_state = transition_table_[next_state][WINDOW_CHANGE];
 
   debugging_log_ << "  InvokeEvent(" << std::left
-      << std::setw(MAX_EVENT_NAME_LENGTH) << GetEventString(event)
+      << std::setw(kMaxStateNameLength) << GetEventString(event)
       << ") to "
-      << std::setw(MAX_STATE_NAME_LENGTH) << GetStateString(next_state);
+      << std::setw(kMaxStateNameLength) << GetStateString(next_state);
 
   state_ = next_state;
 
@@ -392,6 +372,7 @@
     case TOGGLE_FULLSCREEN:
       GetFullscreenController()->ToggleFullscreenMode();
       break;
+
     case TOGGLE_FULLSCREEN_CHROME:
 #if defined(OS_MACOSX)
       if (chrome::mac::SupportsSystemFullscreen()) {
@@ -401,14 +382,17 @@
 #endif
       NOTREACHED() << GetAndClearDebugLog();
       break;
+
     case TAB_FULLSCREEN_TRUE:
       GetFullscreenController()->ToggleFullscreenModeForTab(
            GetBrowser()->tab_strip_model()->GetActiveWebContents(), true);
       break;
+
     case TAB_FULLSCREEN_FALSE:
       GetFullscreenController()->ToggleFullscreenModeForTab(
            GetBrowser()->tab_strip_model()->GetActiveWebContents(), false);
       break;
+
     case METRO_SNAP_TRUE:
 #if defined(OS_WIN)
       GetFullscreenController()->SetMetroSnapMode(true);
@@ -416,6 +400,7 @@
       NOTREACHED() << GetAndClearDebugLog();
 #endif
       break;
+
     case METRO_SNAP_FALSE:
 #if defined(OS_WIN)
       GetFullscreenController()->SetMetroSnapMode(false);
@@ -423,18 +408,23 @@
       NOTREACHED() << GetAndClearDebugLog();
 #endif
       break;
+
     case BUBBLE_EXIT_LINK:
       GetFullscreenController()->ExitTabOrBrowserFullscreenToPreviousState();
       break;
+
     case BUBBLE_ALLOW:
       GetFullscreenController()->OnAcceptFullscreenPermission();
       break;
+
     case BUBBLE_DENY:
       GetFullscreenController()->OnDenyFullscreenPermission();
       break;
+
     case WINDOW_CHANGE:
       ChangeWindowFullscreenState();
       break;
+
     default:
       NOTREACHED() << "InvokeEvent needs a handler for event "
           << GetEventString(event) << GetAndClearDebugLog();
@@ -455,152 +445,86 @@
 void FullscreenControllerStateTest::VerifyWindowState() {
   switch (state_) {
     case STATE_NORMAL:
-#if defined(OS_MACOSX)
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-#endif
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
+                                    FULLSCREEN_WITHOUT_CHROME_FALSE,
+                                    FULLSCREEN_FOR_BROWSER_FALSE,
+                                    FULLSCREEN_FOR_TAB_FALSE,
+                                    IN_METRO_SNAP_FALSE);
       break;
     case STATE_BROWSER_FULLSCREEN_NO_CHROME:
-#if defined(OS_MACOSX)
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-#endif
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
+                                    FULLSCREEN_WITHOUT_CHROME_TRUE,
+                                    FULLSCREEN_FOR_BROWSER_TRUE,
+                                    FULLSCREEN_FOR_TAB_FALSE,
+                                    IN_METRO_SNAP_FALSE);
       break;
     case STATE_BROWSER_FULLSCREEN_WITH_CHROME:
-#if defined(OS_MACOSX)
-      EXPECT_TRUE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-#endif
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_TRUE,
+                                    FULLSCREEN_WITHOUT_CHROME_FALSE,
+                                    FULLSCREEN_FOR_BROWSER_TRUE,
+                                    FULLSCREEN_FOR_TAB_FALSE,
+                                    IN_METRO_SNAP_FALSE);
       break;
     case STATE_METRO_SNAP:
-#if defined(OS_WIN)
-      // http://crbug.com/169138
-      // No expectation for IsFullscreenWithChrome() or
-      // IsFullscreenWithoutChrome()
-
-      // TODO(scheib) IsFullscreenForBrowser and IsFullscreenForTabOrPending
-      // are returning true and false in interactive tests with real window.
-      // With only a single Metro Snap state in this test framework it isn't
-      // fair to try to have an expectation anyway.
-      //
-      // No expectation for IsFullscreenForBrowser.
-      // No expectation for IsFullscreenForTabOrPending.
-      EXPECT_TRUE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
-#else
-      NOTREACHED() << GetAndClearDebugLog();
-#endif
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_NO_EXPECTATION,
+                                    FULLSCREEN_WITHOUT_CHROME_NO_EXPECTATION,
+                                    FULLSCREEN_FOR_BROWSER_NO_EXPECTATION,
+                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
+                                    IN_METRO_SNAP_TRUE);
       break;
     case STATE_TAB_FULLSCREEN:
-#if defined(OS_MACOSX)
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-#endif
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
+                                    FULLSCREEN_WITHOUT_CHROME_TRUE,
+                                    FULLSCREEN_FOR_BROWSER_FALSE,
+                                    FULLSCREEN_FOR_TAB_TRUE,
+                                    IN_METRO_SNAP_FALSE);
       break;
     case STATE_TAB_BROWSER_FULLSCREEN:
-#if defined(OS_MACOSX)
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-#endif
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
+                                    FULLSCREEN_WITHOUT_CHROME_TRUE,
+                                    FULLSCREEN_FOR_BROWSER_TRUE,
+                                    FULLSCREEN_FOR_TAB_TRUE,
+                                    IN_METRO_SNAP_FALSE);
       break;
     case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
-#if defined(OS_MACOSX)
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-#endif
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
+                                    FULLSCREEN_WITHOUT_CHROME_TRUE,
+                                    FULLSCREEN_FOR_BROWSER_TRUE,
+                                    FULLSCREEN_FOR_TAB_TRUE,
+                                    IN_METRO_SNAP_FALSE);
       break;
     case STATE_TO_NORMAL:
-#if defined(OS_MACOSX)
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-#endif
-      // No expectation for IsFullscreenForBrowser.
-      // No expectation for IsFullscreenForTabOrPending.
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
+                                    FULLSCREEN_WITHOUT_CHROME_FALSE,
+                                    FULLSCREEN_FOR_BROWSER_NO_EXPECTATION,
+                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
+                                    IN_METRO_SNAP_FALSE);
       break;
+
     case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
+                                    FULLSCREEN_WITHOUT_CHROME_TRUE,
 #if defined(OS_MACOSX)
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
+                                    FULLSCREEN_FOR_BROWSER_TRUE,
 #else
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
+                                    FULLSCREEN_FOR_BROWSER_FALSE,
 #endif
-      // No expectation for IsFullscreenForTabOrPending.
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
+                                    IN_METRO_SNAP_FALSE);
       break;
+
     case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME:
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_TRUE,
+                                    FULLSCREEN_WITHOUT_CHROME_FALSE,
 #if defined(OS_MACOSX)
-      EXPECT_TRUE(GetBrowser()->window()->IsFullscreenWithChrome())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetBrowser()->window()->IsFullscreenWithoutChrome())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
+                                    FULLSCREEN_FOR_BROWSER_TRUE,
 #else
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
+                                    FULLSCREEN_FOR_BROWSER_FALSE,
 #endif
-      // No expectation for IsFullscreenForTabOrPending.
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
+                                    IN_METRO_SNAP_FALSE);
       break;
+
     case STATE_TO_TAB_FULLSCREEN:
 #if defined(OS_MACOSX)
       // TODO(scheib) InPresentationMode returns false when invoking events:
@@ -612,13 +536,13 @@
       // EXPECT_TRUE(GetBrowser()->window()->InPresentationMode())
       //     << GetAndClearDebugLog();
 #endif
-      EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
-          << GetAndClearDebugLog();
-      EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending())
-          << GetAndClearDebugLog();
-      EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
-          << GetAndClearDebugLog();
+      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_NO_EXPECTATION,
+                                    FULLSCREEN_WITHOUT_CHROME_NO_EXPECTATION,
+                                    FULLSCREEN_FOR_BROWSER_FALSE,
+                                    FULLSCREEN_FOR_TAB_TRUE,
+                                    IN_METRO_SNAP_FALSE);
       break;
+
     default:
       NOTREACHED() << GetAndClearDebugLog();
   }
@@ -638,8 +562,8 @@
 }
 
 void FullscreenControllerStateTest::TestTransitionsForEachState() {
-  for (int source_int = 0; source_int < NUM_STATES; source_int++) {
-    for (int event1_int = 0; event1_int < NUM_EVENTS; event1_int++) {
+  for (int source_int = 0; source_int < NUM_STATES; ++source_int) {
+    for (int event1_int = 0; event1_int < NUM_EVENTS; ++event1_int) {
       State state = static_cast<State>(source_int);
       Event event1 = static_cast<Event>(event1_int);
 
@@ -647,8 +571,8 @@
       if (ShouldSkipTest(state, event1))
         continue;
 
-      for (int event2_int = 0; event2_int < NUM_EVENTS; event2_int++) {
-        for (int event3_int = 0; event3_int < NUM_EVENTS; event3_int++) {
+      for (int event2_int = 0; event2_int < NUM_EVENTS; ++event2_int) {
+        for (int event3_int = 0; event3_int < NUM_EVENTS; ++event3_int) {
           Event event2 = static_cast<Event>(event2_int);
           Event event3 = static_cast<Event>(event3_int);
 
@@ -673,8 +597,10 @@
 
 FullscreenControllerStateTest::StateTransitionInfo
     FullscreenControllerStateTest::NextTransitionInShortestPath(
-        State source, State destination, int search_limit) {
-  if (search_limit == 0)
+    State source,
+    State destination,
+    int search_limit) {
+  if (search_limit <= 0)
     return StateTransitionInfo();  // Return a default (invalid) state.
 
   if (state_transitions_[source][destination].state == STATE_INVALID) {
@@ -682,7 +608,7 @@
     StateTransitionInfo result;
 
     // Consider all states reachable via each event from the source state.
-    for (int event_int = 0; event_int < NUM_EVENTS; event_int++) {
+    for (int event_int = 0; event_int < NUM_EVENTS; ++event_int) {
       Event event = static_cast<Event>(event_int);
       State next_state_candidate = transition_table_[source][event];
 
@@ -771,7 +697,8 @@
   // will be unable to remain in, as they will progress due to the
   // reentrant window change call. Skip states that will be instantly
   // exited by the reentrant call.
-  if (IsReentrant() && (transition_table_[state][WINDOW_CHANGE] != state)) {
+  if (IsWindowFullscreenStateChangedReentrant() &&
+      (transition_table_[state][WINDOW_CHANGE] != state)) {
     debugging_log_ << "\nSkipping reentrant test for transitory source state "
         << GetStateString(state) << ".\n";
     return true;
@@ -797,9 +724,11 @@
 
   debugging_log_ << "\nTest transition from state "
       << GetStateString(state)
-      << (IsReentrant() ? " with reentrant calls.\n" : ".\n");
+      << (IsWindowFullscreenStateChangedReentrant() ?
+          " with reentrant calls.\n" : ".\n");
 
-  debugging_log_ << "First,                               from"
+  // Spaced out text to line up with columns printed in InvokeEvent().
+  debugging_log_ << "First,                                               from "
       << GetStateString(state_) << "\n";
   ASSERT_NO_FATAL_FAILURE(TransitionToState(state))
       << GetAndClearDebugLog();
@@ -808,6 +737,36 @@
   ASSERT_TRUE(InvokeEvent(event)) << GetAndClearDebugLog();
 }
 
+void FullscreenControllerStateTest::VerifyWindowStateExpectations(
+    FullscreenWithChromeExpectation fullscreen_with_chrome,
+    FullscreenWithoutChromeExpectation fullscreen_without_chrome,
+    FullscreenForBrowserExpectation fullscreen_for_browser,
+    FullscreenForTabExpectation fullscreen_for_tab,
+    InMetroSnapExpectation in_metro_snap) {
+#if defined(OS_MACOSX)
+  if (fullscreen_with_chrome != FULLSCREEN_WITH_CHROME_NO_EXPECTATION) {
+    EXPECT_EQ(GetBrowser()->window()->IsFullscreenWithChrome(),
+              !!fullscreen_with_chrome) << GetAndClearDebugLog();
+  }
+  if (fullscreen_without_chrome != FULLSCREEN_WITHOUT_CHROME_NO_EXPECTATION) {
+    EXPECT_EQ(GetBrowser()->window()->IsFullscreenWithoutChrome(),
+              !!fullscreen_without_chrome) << GetAndClearDebugLog();
+  }
+#endif
+  if (fullscreen_for_browser != FULLSCREEN_FOR_BROWSER_NO_EXPECTATION) {
+    EXPECT_EQ(GetFullscreenController()->IsFullscreenForBrowser(),
+              !!fullscreen_for_browser) << GetAndClearDebugLog();
+  }
+  if (fullscreen_for_tab != FULLSCREEN_FOR_TAB_NO_EXPECTATION) {
+    EXPECT_EQ(GetFullscreenController()->IsFullscreenForTabOrPending(),
+              !!fullscreen_for_tab) << GetAndClearDebugLog();
+  }
+  if (in_metro_snap != IN_METRO_SNAP_NO_EXPECTATION) {
+    EXPECT_EQ(GetFullscreenController()->IsInMetroSnapMode(),
+              !!in_metro_snap) << GetAndClearDebugLog();
+  }
+}
+
 FullscreenController* FullscreenControllerStateTest::GetFullscreenController() {
     return GetBrowser()->fullscreen_controller();
 }
@@ -817,13 +776,13 @@
   output << "transition_table_[NUM_STATES = " << NUM_STATES
       << "][NUM_EVENTS = " << NUM_EVENTS
       << "] =\n";
-  for (int state_int = 0; state_int < NUM_STATES; state_int++) {
+  for (int state_int = 0; state_int < NUM_STATES; ++state_int) {
     State state = static_cast<State>(state_int);
     output << "    { // " << GetStateString(state) << ":\n";
-    for (int event_int = 0; event_int < NUM_EVENTS; event_int++) {
+    for (int event_int = 0; event_int < NUM_EVENTS; ++event_int) {
       Event event = static_cast<Event>(event_int);
       output << "      "
-          << std::left << std::setw(MAX_STATE_NAME_LENGTH+1)
+          << std::left << std::setw(kMaxStateNameLength+1)
           << std::string(GetStateString(transition_table_[state][event])) + ","
           << "// Event "
           << GetEventString(event) << "\n";
@@ -838,16 +797,16 @@
   std::ostringstream output;
   output << "state_transitions_[NUM_STATES = " << NUM_STATES
       << "][NUM_STATES = " << NUM_STATES << "] =\n";
-  for (int state1_int = 0; state1_int < NUM_STATES; state1_int++) {
+  for (int state1_int = 0; state1_int < NUM_STATES; ++state1_int) {
     State state1 = static_cast<State>(state1_int);
     output << "{ // " << GetStateString(state1) << ":\n";
-    for (int state2_int = 0; state2_int < NUM_STATES; state2_int++) {
+    for (int state2_int = 0; state2_int < NUM_STATES; ++state2_int) {
       State state2 = static_cast<State>(state2_int);
-      const StateTransitionInfo &info = state_transitions_[state1][state2];
+      const StateTransitionInfo& info = state_transitions_[state1][state2];
       output << "  { "
-        << std::left << std::setw(MAX_EVENT_NAME_LENGTH+1)
+        << std::left << std::setw(kMaxStateNameLength+1)
         << std::string(GetEventString(info.event)) + ","
-        << std::left << std::setw(MAX_STATE_NAME_LENGTH+1)
+        << std::left << std::setw(kMaxStateNameLength+1)
         << std::string(GetStateString(info.state)) + ","
         << std::right << std::setw(2)
         << info.distance
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h
index de3e264..1417ed1 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h
@@ -16,9 +16,38 @@
 class FullscreenController;
 class FullscreenNotificationObserver;
 
-// Test fixture testing Fullscreen Controller through its states. --------------
+// Utility definition for mapping enum values to strings in switch statements.
+#define ENUM_TO_STRING(enum) case enum: return #enum
+
+// Test fixture used to test Fullscreen Controller through exhaustive sequences
+// of events in unit and interactive tests.
+//
+// Because operating system window managers are too unreliable (they result in
+// flakiness at around 1 out of 1000 runs) this fixture is designed to be run
+// on testing infrastructure in unit tests mocking out the platforms' behavior.
+// To verify that behavior interactive tests exist but are left disabled and
+// only run manually when verifying the consistency of the
+// FullscreenControllerTestWindow.
 class FullscreenControllerStateTest {
  public:
+  // Events names for FullscreenController methods.
+  enum Event {
+    TOGGLE_FULLSCREEN,         // ToggleFullscreenMode()
+    TOGGLE_FULLSCREEN_CHROME,  // ToggleFullscreenWithChrome()
+    TAB_FULLSCREEN_TRUE,       // ToggleFullscreenModeForTab(, true)
+    TAB_FULLSCREEN_FALSE,      // ToggleFullscreenModeForTab(, false)
+    METRO_SNAP_TRUE,           // SetMetroSnapMode(true)
+    METRO_SNAP_FALSE,          // SetMetroSnapMode(false)
+    BUBBLE_EXIT_LINK,          // ExitTabOrBrowserFullscreenToPreviousState()
+    BUBBLE_ALLOW,              // OnAcceptFullscreenPermission()
+    BUBBLE_DENY,               // OnDenyFullscreenPermission()
+    WINDOW_CHANGE,             // ChangeWindowFullscreenState()
+    NUM_EVENTS,
+    EVENT_INVALID,
+  };
+
+  // Conceptual states of the Fullscreen Controller, these do not correspond
+  // to particular implemenation details.
   enum State {
     // The window is not in fullscreen.
     STATE_NORMAL,
@@ -46,33 +75,8 @@
     STATE_INVALID,
   };
 
-  enum Event {
-    // FullscreenController::ToggleFullscreenMode()
-    TOGGLE_FULLSCREEN,
-    // FullscreenController::ToggleFullscreenWithChrome()
-    TOGGLE_FULLSCREEN_CHROME,
-    // FullscreenController::ToggleFullscreenModeForTab(, true)
-    TAB_FULLSCREEN_TRUE,
-    // FullscreenController::ToggleFullscreenModeForTab(, false)
-    TAB_FULLSCREEN_FALSE,
-    // FullscreenController::SetMetroSnapMode(true)
-    METRO_SNAP_TRUE,
-    // FullscreenController::SetMetroSnapMode(flase)
-    METRO_SNAP_FALSE,
-    // FullscreenController::ExitTabOrBrowserFullscreenToPreviousState
-    BUBBLE_EXIT_LINK,
-    // FullscreenController::OnAcceptFullscreenPermission
-    BUBBLE_ALLOW,
-    // FullscreenController::OnDenyFullscreenPermission
-    BUBBLE_DENY,
-    // FullscreenController::ChangeWindowFullscreenState()
-    WINDOW_CHANGE,
-    NUM_EVENTS,
-    EVENT_INVALID,
-  };
-
-  static const int MAX_STATE_NAME_LENGTH = 39;
-  static const int MAX_EVENT_NAME_LENGTH = 24;
+  static const int kMaxStateNameLength = 39;
+  static const int kMaxEventNameLength = 24;
 
   FullscreenControllerStateTest();
   virtual ~FullscreenControllerStateTest();
@@ -80,9 +84,10 @@
   static const char* GetStateString(State state);
   static const char* GetEventString(Event event);
 
-  // Returns true if WindowFullscreenStateChanged() is called synchronously as a
-  // result of calling BrowserWindow's fullscreen related modifiers.
-  static bool IsReentrant();
+  // Returns true if FullscreenController::WindowFullscreenStateChanged()
+  // will be called and re-enter FullscreenController before
+  // FullscreenController methods complete.
+  static bool IsWindowFullscreenStateChangedReentrant();
 
   // Returns true if |state| can be persistent. This is true for all of the
   // states without "_TO_" in their name.
@@ -90,12 +95,18 @@
 
   // Causes Fullscreen Controller to transition to an arbitrary state.
   void TransitionToState(State state);
+
   // Makes one state change to approach |destination_state| via shortest path.
   // Returns true if a state change is made.
   // Repeated calls are needed to reach the destination.
   bool TransitionAStepTowardState(State destination_state);
 
+  // Calls FullscreenController::ChangeWindowFullscreenState if needed because
+  // a mock BrowserWindow is being used.
   virtual void ChangeWindowFullscreenState() {}
+
+  // Returns a description of the window's state, may return NULL.
+  // FullscreenControllerStateTest owns the returned pointer.
   virtual const char* GetWindowStateString();
 
   // Causes the |event| to occur and return true on success.
@@ -124,6 +135,21 @@
   std::string GetStateTransitionsAsString() const;
 
  protected:
+  // Set of enumerations (created with a helper macro) for _FALSE, _TRUE, and
+  // _NO_EXPECTATION values to be passed to VerifyWindowStateExpectations().
+  #define EXPECTATION_ENUM(enum_name, enum_prefix) \
+      enum enum_name { \
+        enum_prefix##_FALSE, \
+        enum_prefix##_TRUE, \
+        enum_prefix##_NO_EXPECTATION \
+      }
+  EXPECTATION_ENUM(FullscreenWithChromeExpectation, FULLSCREEN_WITH_CHROME);
+  EXPECTATION_ENUM(FullscreenWithoutChromeExpectation,
+                   FULLSCREEN_WITHOUT_CHROME);
+  EXPECTATION_ENUM(FullscreenForBrowserExpectation, FULLSCREEN_FOR_BROWSER);
+  EXPECTATION_ENUM(FullscreenForTabExpectation, FULLSCREEN_FOR_TAB);
+  EXPECTATION_ENUM(InMetroSnapExpectation, IN_METRO_SNAP);
+
   // Generated information about the transitions between states.
   struct StateTransitionInfo {
     StateTransitionInfo()
@@ -140,6 +166,8 @@
                                                    State destination,
                                                    int search_limit);
 
+  // Returns a detailed log of what FullscreenControllerStateTest has done
+  // up to this point, to be reported when tests fail.
   std::string GetAndClearDebugLog();
 
   // Returns true if the |state| & |event| pair should be skipped.
@@ -151,9 +179,23 @@
   // Runs one test of transitioning to a state and invoking an event.
   virtual void TestStateAndEvent(State state, Event event);
 
+  // Checks that window state matches the expected controller state.
+  virtual void VerifyWindowStateExpectations(
+      FullscreenWithChromeExpectation fullscreen_with_chrome,
+      FullscreenWithoutChromeExpectation fullscreen_without_chrome,
+      FullscreenForBrowserExpectation fullscreen_for_browser,
+      FullscreenForTabExpectation fullscreen_for_tab,
+      InMetroSnapExpectation in_metro_snap);
+
+
   virtual Browser* GetBrowser() = 0;
   FullscreenController* GetFullscreenController();
 
+  // The state the FullscreenController is expected to be in.
+  State state() const { return state_; }
+
+ private:
+  // The state the FullscreenController is expected to be in.
   State state_;
 
   // The state when the previous NOTIFICATION_FULLSCREEN_CHANGED notification
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_tests.h b/chrome/browser/ui/fullscreen/fullscreen_controller_state_tests.h
new file mode 100644
index 0000000..ed8931d
--- /dev/null
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_tests.h
@@ -0,0 +1,47 @@
+// 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_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TESTS_H_
+#define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TESTS_H_
+
+// Macros used to create individual tests for all state and event pairs.
+// To be included in the middle of a test .cc file just after a definition for
+// TEST_EVENT in order to instantiate all the necessary actual tests.  See
+// fullscreen_controller_state_interactive_browsertest.cc and
+// fullscreen_controller_state_unittest.cc.
+
+#define TEST_ALL_EVENTS_NON_METRO(state) \
+    TEST_EVENT(state, TOGGLE_FULLSCREEN) \
+    TEST_EVENT(state, TOGGLE_FULLSCREEN_CHROME) \
+    TEST_EVENT(state, TAB_FULLSCREEN_TRUE) \
+    TEST_EVENT(state, TAB_FULLSCREEN_FALSE) \
+    TEST_EVENT(state, BUBBLE_EXIT_LINK) \
+    TEST_EVENT(state, BUBBLE_ALLOW) \
+    TEST_EVENT(state, BUBBLE_DENY) \
+    TEST_EVENT(state, WINDOW_CHANGE)
+
+#if defined(OS_WIN)
+#define TEST_ALL_EVENTS(state) \
+    TEST_ALL_EVENTS_NON_METRO(state) \
+    TEST_EVENT(state, METRO_SNAP_TRUE) \
+    TEST_EVENT(state, METRO_SNAP_FALSE)
+#else
+#define TEST_ALL_EVENTS(state) TEST_ALL_EVENTS_NON_METRO(state)
+#endif
+
+TEST_ALL_EVENTS(STATE_NORMAL);
+TEST_ALL_EVENTS(STATE_BROWSER_FULLSCREEN_NO_CHROME);
+TEST_ALL_EVENTS(STATE_BROWSER_FULLSCREEN_WITH_CHROME);
+#if defined(OS_WIN)
+TEST_ALL_EVENTS(STATE_METRO_SNAP);
+#endif
+TEST_ALL_EVENTS(STATE_TAB_FULLSCREEN);
+TEST_ALL_EVENTS(STATE_TAB_BROWSER_FULLSCREEN);
+TEST_ALL_EVENTS(STATE_TAB_BROWSER_FULLSCREEN_CHROME);
+TEST_ALL_EVENTS(STATE_TO_NORMAL);
+TEST_ALL_EVENTS(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME);
+TEST_ALL_EVENTS(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME);
+TEST_ALL_EVENTS(STATE_TO_TAB_FULLSCREEN);
+
+#endif  // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TESTS_H_
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
index 885bb76..0f2d94d 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
@@ -16,16 +16,12 @@
 // The FullscreenControllerStateUnitTest unit test suite exhastively tests
 // the FullscreenController through all permutations of events. The behavior
 // of the BrowserWindow is mocked via FullscreenControllerTestWindow.
-//
-// FullscreenControllerStateInteractiveTest is an interactive test suite
-// used to verify that the FullscreenControllerTestWindow models the behavior
-// of actual windows accurately. The interactive tests are too flaky to run
-// on infrastructure, and so those tests are disabled. Run them with:
-//     interactive_ui_tests
-//         --gtest_filter="FullscreenControllerStateInteractiveTest.*"
-//         --gtest_also_run_disabled_tests
 
-// A BrowserWindow used for testing FullscreenController. ----------------------
+
+// FullscreenControllerTestWindow ----------------------------------------------
+
+// A BrowserWindow used for testing FullscreenController. The behavior of this
+// mock is verfied manually by running FullscreenControllerStateInteractiveTest.
 class FullscreenControllerTestWindow : public TestBrowserWindow {
  public:
   // Simulate the window state with an enumeration.
@@ -113,13 +109,10 @@
 
 #if defined(OS_WIN)
 void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable) {
-  if (enable != IsInMetroSnapMode()) {
-    if (enable)
-      state_ = METRO_SNAP;
-    else
-      state_ = NORMAL;
-  }
-  if (FullscreenControllerStateTest::IsReentrant())
+  if (enable != IsInMetroSnapMode())
+    state_ = enable ? METRO_SNAP : NORMAL;
+
+  if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
     ChangeWindowFullscreenState();
 }
 
@@ -146,16 +139,11 @@
 const char* FullscreenControllerTestWindow::GetWindowStateString(
     WindowState state) {
   switch (state) {
-    case NORMAL:
-      return "NORMAL";
-    case FULLSCREEN:
-      return "FULLSCREEN";
-    case METRO_SNAP:
-      return "METRO_SNAP";
-    case TO_FULLSCREEN:
-      return "TO_FULLSCREEN";
-    case TO_NORMAL:
-      return "TO_NORMAL";
+    ENUM_TO_STRING(NORMAL);
+    ENUM_TO_STRING(FULLSCREEN);
+    ENUM_TO_STRING(METRO_SNAP);
+    ENUM_TO_STRING(TO_FULLSCREEN);
+    ENUM_TO_STRING(TO_NORMAL);
     default:
       NOTREACHED() << "No string for state " << state;
       return "WindowState-Unknown";
@@ -163,25 +151,14 @@
 }
 
 void FullscreenControllerTestWindow::ChangeWindowFullscreenState() {
-  // Several states result in "no operation" intentionally. The tests
+  // Most states result in "no operation" intentionally. The tests
   // assume that all possible states and event pairs can be tested, even
   // though window managers will not generate all of these.
-  switch (state_) {
-    case NORMAL:
-      break;
-    case FULLSCREEN:
-      break;
-    case METRO_SNAP:
-      break;
-    case TO_FULLSCREEN:
+  if (state_ == TO_FULLSCREEN)
       state_ = FULLSCREEN;
-      break;
-    case TO_NORMAL:
+  else if (state_ == TO_NORMAL)
       state_ = NORMAL;
-      break;
-    default:
-      NOTREACHED();
-  }
+
   // Emit a change event from every state to ensure the Fullscreen Controller
   // handles it in all circumstances.
   browser_->WindowFullscreenStateChanged();
@@ -213,7 +190,7 @@
   if (!fullscreen_changed && !mac_with_chrome_mode_changed)
     return false;
 
-  if (FullscreenControllerStateTest::IsReentrant())
+  if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
     return true;
 
   // BrowserWindowCocoa::EnterFullscreen() and
@@ -224,7 +201,11 @@
       mac_with_chrome_mode_changed;
 }
 
-// Unit test fixture testing Fullscreen Controller through its states. ---------
+
+// FullscreenControllerStateUnitTest -------------------------------------------
+
+// Unit test fixture testing Fullscreen Controller through its states. Most of
+// the test logic comes from FullscreenControllerStateTest.
 class FullscreenControllerStateUnitTest : public BrowserWithTestWindowTest,
                                           public FullscreenControllerStateTest {
  public:
@@ -267,53 +248,40 @@
 }
 
 void FullscreenControllerStateUnitTest::VerifyWindowState() {
-  switch (state_) {
+  switch (state()) {
     case STATE_NORMAL:
       EXPECT_EQ(FullscreenControllerTestWindow::NORMAL,
                 window_->state()) << GetAndClearDebugLog();
       break;
+
     case STATE_BROWSER_FULLSCREEN_NO_CHROME:
-      EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
-                window_->state()) << GetAndClearDebugLog();
-      break;
     case STATE_BROWSER_FULLSCREEN_WITH_CHROME:
+    case STATE_TAB_FULLSCREEN:
+    case STATE_TAB_BROWSER_FULLSCREEN:
+    case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
       EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
                 window_->state()) << GetAndClearDebugLog();
       break;
+
 #if defined(OS_WIN)
     case STATE_METRO_SNAP:
       EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
                 window_->state()) << GetAndClearDebugLog();
       break;
 #endif
-    case STATE_TAB_FULLSCREEN:
-      EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
-                window_->state()) << GetAndClearDebugLog();
-      break;
-    case STATE_TAB_BROWSER_FULLSCREEN:
-      EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
-                window_->state()) << GetAndClearDebugLog();
-      break;
-    case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
-      EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
-                window_->state()) << GetAndClearDebugLog();
-      break;
+
     case STATE_TO_NORMAL:
       EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
                 window_->state()) << GetAndClearDebugLog();
       break;
+
     case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
-      EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
-                window_->state()) << GetAndClearDebugLog();
-      break;
     case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME:
-      EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
-                window_->state()) << GetAndClearDebugLog();
-      break;
     case STATE_TO_TAB_FULLSCREEN:
       EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
                 window_->state()) << GetAndClearDebugLog();
       break;
+
     default:
       NOTREACHED() << GetAndClearDebugLog();
   }
@@ -344,18 +312,8 @@
   return BrowserWithTestWindowTest::browser();
 }
 
-// Tests -----------------------------------------------------------------------
 
-#define TEST_EVENT(state, event) \
-    TEST_F(FullscreenControllerStateUnitTest, state##__##event) { \
-      AddTab(browser(), GURL(content::kAboutBlankURL)); \
-      ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event)) \
-          << GetAndClearDebugLog(); \
-    }
-    // Progress of tests can be examined by inserting the following line:
-    // LOG(INFO) << GetAndClearDebugLog(); }
-
-// Soak tests:
+// Soak tests ------------------------------------------------------------------
 
 // Tests all states with all permutations of multiple events to detect lingering
 // state issues that would bleed over to other states.
@@ -373,159 +331,29 @@
 }
 
 
-// Individual tests for each pair of state and event:
+// Individual tests for each pair of state and event ---------------------------
 
-TEST_EVENT(STATE_NORMAL, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_NORMAL, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_NORMAL, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_NORMAL, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_NORMAL, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_NORMAL, BUBBLE_ALLOW);
-TEST_EVENT(STATE_NORMAL, BUBBLE_DENY);
-TEST_EVENT(STATE_NORMAL, WINDOW_CHANGE);
+#define TEST_EVENT(state, event) \
+    TEST_F(FullscreenControllerStateUnitTest, state##__##event) { \
+      AddTab(browser(), GURL(content::kAboutBlankURL)); \
+      ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event)) \
+          << GetAndClearDebugLog(); \
+    }
+    // Progress of tests can be examined by inserting the following line:
+    // LOG(INFO) << GetAndClearDebugLog(); }
 
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_WITH_CHROME, WINDOW_CHANGE);
-
-#if defined(OS_WIN)
-TEST_EVENT(STATE_METRO_SNAP, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_METRO_SNAP, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_FALSE);
-TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_FALSE);
-TEST_EVENT(STATE_METRO_SNAP, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_METRO_SNAP, BUBBLE_ALLOW);
-TEST_EVENT(STATE_METRO_SNAP, BUBBLE_DENY);
-TEST_EVENT(STATE_METRO_SNAP, WINDOW_CHANGE);
-#endif
-
-TEST_EVENT(STATE_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_FULLSCREEN, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TAB_FULLSCREEN, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TAB_FULLSCREEN, BUBBLE_DENY);
-TEST_EVENT(STATE_TAB_FULLSCREEN, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, BUBBLE_DENY);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_NORMAL, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_NORMAL, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_NORMAL, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_NORMAL, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_NORMAL, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_NORMAL, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TOGGLE_FULLSCREEN_CHROME);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, BUBBLE_EXIT_LINK);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, BUBBLE_ALLOW);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, BUBBLE_DENY);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, WINDOW_CHANGE);
+#include "chrome/browser/ui/fullscreen/fullscreen_controller_state_tests.h"
 
 
-// Specific one-off tests for known issues:
+// Specific one-off tests for known issues -------------------------------------
 
 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
 // Browser fullscreen is broken currently http://crbug.com/154196
 TEST_F(FullscreenControllerStateUnitTest,
        DISABLED_ToggleTabWhenPendingBrowser) {
-#if !defined(OS_WIN)  // Only possible without reentrancy
+  // Only possible without reentrancy.
+  if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
+    return;
   AddTab(browser(), GURL(content::kAboutBlankURL));
   ASSERT_NO_FATAL_FAILURE(
       TransitionToState(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME))
@@ -534,13 +362,14 @@
   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
-#endif
 }
 
 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
 // Browser fullscreen is broken currently http://crbug.com/154196
 TEST_F(FullscreenControllerStateUnitTest, DISABLED_ToggleTabWhenPendingTab) {
-#if !defined(OS_WIN)  // Only possible without reentrancy
+  // Only possible without reentrancy.
+  if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
+    return;
   AddTab(browser(), GURL(content::kAboutBlankURL));
   ASSERT_NO_FATAL_FAILURE(
       TransitionToState(STATE_TO_TAB_FULLSCREEN))
@@ -549,7 +378,6 @@
   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
-#endif
 }
 
 // Debugging utility: Display the transition tables. Intentionally disabled
@@ -562,9 +390,9 @@
   output << GetStateTransitionsAsString();
 
   // Calculate all transition pairs.
-  for (int state1_int = 0; state1_int < NUM_STATES; state1_int++) {
+  for (int state1_int = 0; state1_int < NUM_STATES; ++state1_int) {
     State state1 = static_cast<State>(state1_int);
-    for (int state2_int = 0; state2_int < NUM_STATES; state2_int++) {
+    for (int state2_int = 0; state2_int < NUM_STATES; ++state2_int) {
       State state2 = static_cast<State>(state2_int);
       if (ShouldSkipStateAndEventPair(state1, EVENT_INVALID) ||
           ShouldSkipStateAndEventPair(state2, EVENT_INVALID))
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc
index faf842d..c520df9 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h"
 
 #include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -14,11 +14,9 @@
 #include "chrome/test/base/test_browser_window.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 // Dummy implementation that's good enough for the tests; we don't test
 // rendering here so all we need is a non-NULL object.
 class EmptyTabstripOriginProvider : public TabstripOriginProvider {
@@ -30,11 +28,6 @@
 
 class BookmarkBarGtkUnittest : public testing::Test {
  protected:
-  BookmarkBarGtkUnittest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_) {
-  }
-
   virtual void SetUp() OVERRIDE {
     profile_.reset(new TestingProfile());
     profile_->CreateBookmarkModel(true);
@@ -51,7 +44,7 @@
   }
 
   virtual void TearDown() OVERRIDE {
-    message_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
 
     bookmark_bar_.reset();
     origin_provider_.reset();
@@ -61,9 +54,7 @@
 
   BookmarkModel* model_;
 
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   scoped_ptr<TestingProfile> profile_;
   scoped_ptr<Browser> browser_;
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h b/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
index e91aa2d..b21495b 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
@@ -54,9 +54,7 @@
   // Notifies the SearchTabHelper, if one exists, of relevant changes to the
   // omnibox state.
   virtual void NotifySearchTabHelper(bool user_input_in_progress,
-                                     bool cancelling,
-                                     bool popup_is_open,
-                                     bool user_text_is_empty) = 0;
+                                     bool cancelling) = 0;
 
   // Performs prerendering for |match|.
   virtual void DoPrerender(const AutocompleteMatch& match) = 0;
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
index 7868c8c..e26f8d5 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
@@ -74,15 +74,12 @@
 
 void OmniboxCurrentPageDelegateImpl::NotifySearchTabHelper(
     bool user_input_in_progress,
-    bool cancelling,
-    bool popup_is_open,
-    bool user_text_is_empty) {
+    bool cancelling) {
   if (!controller_->GetWebContents())
     return;
   SearchTabHelper::FromWebContents(
       controller_->GetWebContents())->OmniboxEditModelChanged(
-          user_input_in_progress, cancelling, popup_is_open,
-          user_text_is_empty);
+          user_input_in_progress, cancelling);
 }
 
 void OmniboxCurrentPageDelegateImpl::DoPrerender(
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
index 9ef4581..5546ad0 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
@@ -30,9 +30,7 @@
       const AutocompleteMatch& match,
       WindowOpenDisposition disposition) OVERRIDE;
   virtual void NotifySearchTabHelper(bool user_input_in_progress,
-                                     bool cancelling,
-                                     bool popup_is_open,
-                                     bool user_text_is_empty) OVERRIDE;
+                                     bool cancelling) OVERRIDE;
   virtual void DoPrerender(const AutocompleteMatch& match) OVERRIDE;
 
  private:
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
index 7ade221..bdc292c 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -116,18 +116,18 @@
   if (search_term_replacement_active) {
     if (transition == content::PAGE_TRANSITION_TYPED) {
       UMA_HISTOGRAM_PERCENTAGE(
-          "InstantExtended.PercentageMatchQuerytoURL", percent);
+          "InstantExtended.PercentageMatchV2_QuerytoURL", percent);
     } else {
       UMA_HISTOGRAM_PERCENTAGE(
-          "InstantExtended.PercentageMatchQuerytoQuery", percent);
+          "InstantExtended.PercentageMatchV2_QuerytoQuery", percent);
     }
   } else {
     if (transition == content::PAGE_TRANSITION_TYPED) {
       UMA_HISTOGRAM_PERCENTAGE(
-          "InstantExtended.PercentageMatchURLtoURL", percent);
+          "InstantExtended.PercentageMatchV2_URLtoURL", percent);
     } else {
       UMA_HISTOGRAM_PERCENTAGE(
-          "InstantExtended.PercentageMatchURLtoQuery", percent);
+          "InstantExtended.PercentageMatchV2_URLtoQuery", percent);
     }
   }
 }
@@ -435,8 +435,7 @@
   }
   controller_->OnInputInProgress(in_progress);
 
-  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_,
-                                   popup_model()->IsOpen(), user_text_.empty());
+  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_);
 }
 
 void OmniboxEditModel::Revert() {
@@ -765,8 +764,7 @@
 void OmniboxEditModel::AcceptTemporaryTextAsUserText() {
   InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
   has_temporary_text_ = false;
-  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_,
-                                   popup_model()->IsOpen(), user_text_.empty());
+  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_);
 }
 
 void OmniboxEditModel::ClearKeyword(const string16& visible_text) {
@@ -814,8 +812,7 @@
                                                 permanent_text_);
   }
 
-  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_,
-                                   popup_model()->IsOpen(), user_text_.empty());
+  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_);
 }
 
 void OmniboxEditModel::SetCaretVisibility(bool visible) {
@@ -836,8 +833,7 @@
 
   // TODO(jered): Rip this out along with StartZeroSuggest.
   autocomplete_controller()->StopZeroSuggest();
-  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_,
-                                   popup_model()->IsOpen(), user_text_.empty());
+  delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_);
 }
 
 void OmniboxEditModel::OnKillFocus() {
diff --git a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
index 7d2f2c8..686d654 100644
--- a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
+++ b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
@@ -579,48 +579,6 @@
   EXPECT_TRUE(favicon_tab_helper->ShouldDisplayFavicon());
 }
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, ProcessIsolation) {
-  // Prior to setup, Instant has an ntp with a failed "google.com" load in
-  // it, which is rendered in the dedicated Instant renderer process.
-  //
-  // TODO(sreeram): Fix this up when we stop doing crazy things on init.
-  InstantService* instant_service =
-        InstantServiceFactory::GetForProfile(browser()->profile());
-  ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
-#if !defined(OS_MACOSX)
-  // The failed "google.com" load is deleted, which sometimes leads to the
-  // process shutting down on Mac.
-  EXPECT_EQ(1, instant_service->GetInstantProcessCount());
-#endif
-
-  // Setup Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantNTPSupport();
-
-  // The registered Instant render process should still exist.
-  EXPECT_EQ(1, instant_service->GetInstantProcessCount());
-  // And the Instant ntp should live inside it.
-  content::WebContents* ntp_contents = instant()->ntp_->contents();
-  EXPECT_TRUE(instant_service->IsInstantProcess(
-      ntp_contents->GetRenderProcessHost()->GetID()));
-
-  // Navigating to the NTP should use the Instant render process.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(),
-      GURL(chrome::kChromeUINewTabURL),
-      CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_NONE);
-  content::WebContents* active_tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(instant_service->IsInstantProcess(
-      active_tab->GetRenderProcessHost()->GetID()));
-
-  // Navigating elsewhere should not use the Instant render process.
-  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL));
-  EXPECT_FALSE(instant_service->IsInstantProcess(
-      active_tab->GetRenderProcessHost()->GetID()));
-}
-
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_MostVisited) {
   content::WindowedNotificationObserver observer(
       chrome::NOTIFICATION_INSTANT_SENT_MOST_VISITED_ITEMS,
@@ -951,54 +909,6 @@
               old_render_view_id != new_render_view_id);
 }
 
-// Test that renderer initiated navigations to an Instant URL from an
-// Instant process end up in an Instant process.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       RendererInitiatedNavigationInInstantProcess) {
-  InstantService* instant_service =
-      InstantServiceFactory::GetForProfile(browser()->profile());
-  ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
-
-  // Setup Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantNTPSupport();
-
-  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  EXPECT_EQ(1, browser()->tab_strip_model()->count());
-
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(),
-      instant_url(),
-      CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  content::WebContents* contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(instant_service->IsInstantProcess(
-      contents->GetRenderProcessHost()->GetID()));
-
-  std::string instant_url_with_query = instant_url().spec() + "q=3";
-  std::string add_link_script = base::StringPrintf(
-      "var a = document.createElement('a');"
-      "a.id = 'toClick';"
-      "a.href = '%s';"
-      "document.body.appendChild(a);",
-      instant_url_with_query.c_str());
-  EXPECT_TRUE(content::ExecuteScript(contents, add_link_script));
-
-  content::WindowedNotificationObserver observer(
-        content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-        content::NotificationService::AllSources());
-  EXPECT_TRUE(content::ExecuteScript(
-      contents, "document.getElementById('toClick').click();"));
-  observer.Wait();
-
-  EXPECT_EQ(1, browser()->tab_strip_model()->count());
-  contents = browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(instant_service->IsInstantProcess(
-      contents->GetRenderProcessHost()->GetID()));
-  EXPECT_EQ(GURL(instant_url_with_query), contents->GetURL());
-}
-
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, AcceptingURLSearchDoesNotNavigate) {
   // Get a committed Instant tab, which will be in the Instant process and thus
   // support chrome::GetSearchTerms().
@@ -1805,3 +1715,94 @@
   // Make sure the URL remains the same.
   EXPECT_EQ(ntp_url, ntp_contents->GetURL());
 }
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, ProcessIsolation) {
+  // Prior to setup, Instant has an ntp with a failed "google.com" load in
+  // it, which is rendered in the dedicated Instant renderer process.
+  //
+  // TODO(sreeram): Fix this up when we stop doing crazy things on init.
+  InstantService* instant_service =
+        InstantServiceFactory::GetForProfile(browser()->profile());
+  ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
+#if !defined(OS_MACOSX)
+  // The failed "google.com" load is deleted, which sometimes leads to the
+  // process shutting down on Mac.
+  EXPECT_EQ(1, instant_service->GetInstantProcessCount());
+#endif
+
+  // Setup Instant.
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // The registered Instant render process should still exist.
+  EXPECT_EQ(1, instant_service->GetInstantProcessCount());
+  // And the Instant ntp should live inside it.
+  content::WebContents* ntp_contents =
+      instant_service->ntp_prerenderer()->ntp()->contents();
+  EXPECT_TRUE(instant_service->IsInstantProcess(
+      ntp_contents->GetRenderProcessHost()->GetID()));
+
+  // Navigating to the NTP should use the Instant render process.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      CURRENT_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(instant_service->IsInstantProcess(
+      active_tab->GetRenderProcessHost()->GetID()));
+
+  // Navigating elsewhere should not use the Instant render process.
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL));
+  EXPECT_FALSE(instant_service->IsInstantProcess(
+      active_tab->GetRenderProcessHost()->GetID()));
+}
+
+// Test that renderer initiated navigations to an Instant URL from an
+// Instant process end up in an Instant process.
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
+                       RendererInitiatedNavigationInInstantProcess) {
+  InstantService* instant_service =
+      InstantServiceFactory::GetForProfile(browser()->profile());
+  ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
+
+  // Setup Instant.
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      instant_url(),
+      CURRENT_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(instant_service->IsInstantProcess(
+      contents->GetRenderProcessHost()->GetID()));
+
+  std::string instant_url_with_query = instant_url().spec() + "q=3";
+  std::string add_link_script = base::StringPrintf(
+      "var a = document.createElement('a');"
+      "a.id = 'toClick';"
+      "a.href = '%s';"
+      "document.body.appendChild(a);",
+      instant_url_with_query.c_str());
+  EXPECT_TRUE(content::ExecuteScript(contents, add_link_script));
+
+  content::WindowedNotificationObserver observer(
+        content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+        content::NotificationService::AllSources());
+  EXPECT_TRUE(content::ExecuteScript(
+      contents, "document.getElementById('toClick').click();"));
+  observer.Wait();
+
+  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+  contents = browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(instant_service->IsInstantProcess(
+      contents->GetRenderProcessHost()->GetID()));
+  EXPECT_EQ(GURL(instant_url_with_query), contents->GetURL());
+}
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer.h b/chrome/browser/ui/search/instant_ntp_prerenderer.h
index cf0c0d3..19ac200 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer.h
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer.h
@@ -108,6 +108,7 @@
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedManualTest, MANUAL_ShowsGoogleNTP);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedManualTest,
                            MANUAL_SearchesFromFakebox);
+  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ProcessIsolation);
 
   // Overridden from net::NetworkChangeNotifier::NetworkChangeObserver:
   // If the network status changes, resets InstantNTP.
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc b/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc
index 374c8fd..0535657 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc
@@ -14,7 +14,7 @@
 #include "chrome/common/content_settings.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::HistogramBase;
@@ -136,11 +136,7 @@
 class InstantNTPPrerendererTest : public testing::Test {
  public:
   InstantNTPPrerendererTest()
-      : ui_thread_(content::BrowserThread::UI),
-        instant_ntp_prerenderer_(new TestableInstantNTPPrerenderer(&profile_)) {
-  }
-
-  virtual void SetUp() OVERRIDE {
+      : instant_ntp_prerenderer_(new TestableInstantNTPPrerenderer(&profile_)) {
     base::StatisticsRecorder::Initialize();
   }
 
@@ -153,7 +149,7 @@
   }
 
  private:
-  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestableInstantNTPPrerenderer> instant_ntp_prerenderer_;
   mutable TestingProfile profile_;
 };
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 8b6dee9..1a226db 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -49,8 +49,6 @@
     : WebContentsObserver(web_contents),
       is_search_enabled_(chrome::IsInstantExtendedAPIEnabled()),
       user_input_in_progress_(false),
-      popup_is_open_(false),
-      user_text_is_empty_(true),
       web_contents_(web_contents) {
   if (!is_search_enabled_)
     return;
@@ -73,15 +71,11 @@
 }
 
 void SearchTabHelper::OmniboxEditModelChanged(bool user_input_in_progress,
-                                              bool cancelling,
-                                              bool popup_is_open,
-                                              bool user_text_is_empty) {
+                                              bool cancelling) {
   if (!is_search_enabled_)
     return;
 
   user_input_in_progress_ = user_input_in_progress;
-  popup_is_open_ = popup_is_open;
-  user_text_is_empty_ = user_text_is_empty;
   if (!user_input_in_progress && !cancelling)
     return;
 
@@ -195,21 +189,7 @@
     origin = model_.mode().origin;
   if (user_input_in_progress_)
     type = SearchMode::MODE_SEARCH_SUGGESTIONS;
-
-  if (type == SearchMode::MODE_NTP && origin == SearchMode::ORIGIN_NTP &&
-      !popup_is_open_ && !user_text_is_empty_) {
-    // We're switching back (|popup_is_open_| is false) to an NTP (type and
-    // mode are |NTP|) with suggestions (|user_text_is_empty_| is false), don't
-    // modify visibility of top bars or voice search support.  This specific
-    // omnibox state is set when OmniboxEditModelChanged() is called from
-    // OmniboxEditModel::SetInputInProgress() which is called from
-    // OmniboxEditModel::Revert().
-    model_.SetState(SearchModel::State(SearchMode(type, origin),
-                                       model_.instant_support(),
-                                       model_.state().voice_search_supported));
-  } else {
-    model_.SetMode(SearchMode(type, origin));
-  }
+  model_.SetMode(SearchMode(type, origin));
 }
 
 void SearchTabHelper::DetermineIfPageSupportsInstant() {
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h
index ca05de1..8a3955f 100644
--- a/chrome/browser/ui/search/search_tab_helper.h
+++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -42,10 +42,7 @@
 
   // Invoked when the OmniboxEditModel changes state in some way that might
   // affect the search mode.
-  void OmniboxEditModelChanged(bool user_input_in_progress,
-                               bool cancelling,
-                               bool popup_is_open,
-                               bool user_text_is_empty);
+  void OmniboxEditModelChanged(bool user_input_in_progress, bool cancelling);
 
   // Invoked when the active navigation entry is updated in some way that might
   // affect the search mode. This is used by Instant when it "fixes up" the
@@ -111,8 +108,6 @@
 
   // Tracks the last value passed to OmniboxEditModelChanged().
   bool user_input_in_progress_;
-  bool popup_is_open_;
-  bool user_text_is_empty_;
 
   // Model object for UI that cares about search state.
   SearchModel model_;
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.cc b/chrome/browser/ui/sync/one_click_signin_helper.cc
index 0fd124a..4c001ee 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper.cc
@@ -476,7 +476,11 @@
 
   // content::WebContentsObserver:
   virtual void WebContentsDestroyed(content::WebContents* contents) OVERRIDE;
-  virtual void DidStopLoading(
+  virtual void DidCommitProvisionalLoadForFrame(
+      int64 frame_id,
+      bool is_main_frame,
+      const GURL& url,
+      content::PageTransition transition_type,
       content::RenderViewHost* render_view_host) OVERRIDE;
 
  private:
@@ -495,13 +499,26 @@
 CurrentHistoryCleaner::~CurrentHistoryCleaner() {
 }
 
-void CurrentHistoryCleaner::DidStopLoading(
+void CurrentHistoryCleaner::DidCommitProvisionalLoadForFrame(
+    int64 frame_id,
+    bool is_main_frame,
+    const GURL& url,
+    content::PageTransition transition_type,
     content::RenderViewHost* render_view_host) {
+  // Return early if this is not top-level navigation.
+  if (!is_main_frame)
+    return;
+
   content::NavigationController* nc = &web_contents()->GetController();
+
   // Have to wait until something else gets added to history before removal.
   if (history_index_to_remove_ < nc->GetLastCommittedEntryIndex()) {
-    nc->RemoveEntryAtIndex(history_index_to_remove_);
-    delete this;  // Success.
+    content::NavigationEntry* entry =
+        nc->GetEntryAtIndex(history_index_to_remove_);
+    if (SyncPromoUI::IsContinueUrlForWebBasedSigninFlow(entry->GetURL()) &&
+        nc->RemoveEntryAtIndex(history_index_to_remove_)) {
+      delete this;  // Success.
+    }
   }
 }
 
@@ -906,8 +923,10 @@
 void OneClickSigninHelper::RemoveSigninRedirectURLHistoryItem(
     content::WebContents* web_contents) {
   // Only actually remove the item if it's the blank.html continue url.
-  if (SyncPromoUI::IsContinueUrlForWebBasedSigninFlow(web_contents->GetURL()))
+  if (SyncPromoUI::IsContinueUrlForWebBasedSigninFlow(
+          web_contents->GetLastCommittedURL())) {
     new CurrentHistoryCleaner(web_contents);  // will self-destruct when done
+  }
 }
 
 void OneClickSigninHelper::ShowSigninErrorBubble(Browser* browser,
@@ -1041,7 +1060,7 @@
   // If the user left the sign in process, clear all members.
   // TODO(rogerta): might need to allow some youtube URLs.
   content::WebContents* contents = web_contents();
-  const GURL url = contents->GetURL();
+  const GURL url = contents->GetLastCommittedURL();
   Profile* profile =
       Profile::FromBrowserContext(contents->GetBrowserContext());
   VLOG(1) << "OneClickSigninHelper::DidStopLoading: url=" << url.spec();
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc
index d4c94a8..e0ff981 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
 
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/global_error/global_error.h"
@@ -13,6 +14,9 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/menu_model_test.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_io_thread_state.h"
+#include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -77,6 +81,27 @@
   virtual bool GetAcceleratorForCommandId(
       int command_id,
       ui::Accelerator* accelerator) OVERRIDE { return false; }
+
+ protected:
+  virtual void SetUp() OVERRIDE {
+    prefs_.reset(new TestingPrefServiceSimple());
+    chrome::RegisterLocalState(prefs_->registry());
+
+    TestingBrowserProcess::GetGlobal()->SetLocalState(prefs_.get());
+    testing_io_thread_state_.reset(new chrome::TestingIOThreadState());
+    BrowserWithTestWindowTest::SetUp();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    BrowserWithTestWindowTest::TearDown();
+    testing_io_thread_state_.reset();
+    TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
+    DestroyBrowserAndProfile();
+  }
+
+ private:
+  scoped_ptr<TestingPrefServiceSimple> prefs_;
+  scoped_ptr<chrome::TestingIOThreadState> testing_io_thread_state_;
 };
 
 // Copies parts of MenuModelTest::Delegate and combines them with the
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index 05b180e..c6e21b3 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -12,11 +12,13 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/avatar_menu_bubble_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/profile_chooser_view.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "content/public/test/test_utils.h"
@@ -101,7 +103,6 @@
             ProfileChooserView::IsShowing());
 }
 
-
 IN_PROC_BROWSER_TEST_P(AvatarMenuButtonTest, HideOnSecondClick) {
   if (!profiles::IsMultipleProfilesEnabled() ||
       UsingNewProfileChooser()) {
@@ -123,7 +124,6 @@
   EXPECT_FALSE(ProfileChooserView::IsShowing());
 }
 
-
 IN_PROC_BROWSER_TEST_P(AvatarMenuButtonTest, NewSignOut) {
   if (!profiles::IsMultipleProfilesEnabled() ||
       !UsingNewProfileChooser()) {
@@ -159,6 +159,34 @@
   EXPECT_TRUE(browser_list->empty());
 }
 
+IN_PROC_BROWSER_TEST_P(AvatarMenuButtonTest, LaunchUserManagerScreen) {
+  if (!profiles::IsMultipleProfilesEnabled() ||
+      !UsingNewProfileChooser()) {
+    return;
+  }
+
+  CreateTestingProfile();
+  StartAvatarMenu();
+
+  int starting_tab_count = browser()->tab_strip_model()->count();
+  BrowserList* browser_list =
+      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
+  EXPECT_EQ(1U, browser_list->size());
+
+  ui::MouseEvent mouse_ev(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0);
+  ProfileChooserView::profile_bubble_->ButtonPressed(
+      static_cast<views::Button*>(
+          ProfileChooserView::profile_bubble_->users_button_view_),
+      mouse_ev);
+
+  // The user manager screen should go into a new, active tab.
+  int final_tab_count = browser()->tab_strip_model()->count();
+  EXPECT_EQ(1U, browser_list->size());
+  EXPECT_EQ(starting_tab_count + 1, final_tab_count);
+
+  GURL tab_url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
+  EXPECT_EQ(std::string(chrome::kChromeUIUserChooserURL), tab_url.spec());
+}
 
 INSTANTIATE_TEST_CASE_P(Old, AvatarMenuButtonTest, testing::Values(false));
 INSTANTIATE_TEST_CASE_P(New, AvatarMenuButtonTest, testing::Values(true));
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
index c1f7053..bb5f2de 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -113,8 +113,7 @@
  public:
   BookmarkBarViewEventTestBase()
       : ViewEventTestBase(),
-        model_(NULL),
-        file_thread_(BrowserThread::FILE, base::MessageLoop::current()) {}
+        model_(NULL) {}
 
   virtual void SetUp() OVERRIDE {
     views::MenuController::TurnOffContextMenuSelectionHoldForTest();
@@ -243,7 +242,6 @@
   scoped_ptr<TestingProfile> profile_;
   scoped_ptr<Browser> browser_;
   scoped_ptr<ScopedTestingLocalState> local_state_;
-  content::TestBrowserThread file_thread_;
   ChromeViewsDelegate views_delegate_;
 };
 
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 11561a0..1294d04 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -1085,13 +1085,24 @@
   AddChildView(discard_button_);
 
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  // The dangerous download label text and icon are different under
-  // different cases.
-  if (mode_ == MALICIOUS_MODE) {
-    warning_icon_ = rb.GetImageSkiaNamed(IDR_SAFEBROWSING_WARNING);
-  } else {
-    // The download file has dangerous file type (e.g.: an executable).
-    warning_icon_ = rb.GetImageSkiaNamed(IDR_WARNING);
+  switch (download()->GetDangerType()) {
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
+    case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
+      warning_icon_ = rb.GetImageSkiaNamed(IDR_SAFEBROWSING_WARNING);
+      break;
+
+    case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
+    case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
+    case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
+    case content::DOWNLOAD_DANGER_TYPE_MAX:
+      NOTREACHED();
+      // fallthrough
+
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+      warning_icon_ = rb.GetImageSkiaNamed(IDR_WARNING);
   }
   string16 dangerous_label = model_.GetWarningText(font_, kTextWidth);
   dangerous_download_label_ = new views::Label(dangerous_label);
diff --git a/chrome/browser/ui/views/frame/browser_view_unittest.cc b/chrome/browser/ui/views/frame/browser_view_unittest.cc
index 8bb3377..d3ad284 100644
--- a/chrome/browser/ui/views/frame/browser_view_unittest.cc
+++ b/chrome/browser/ui/views/frame/browser_view_unittest.cc
@@ -9,6 +9,7 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
+#include "chrome/browser/predictors/predictor_database.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -23,6 +24,8 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_io_thread_state.h"
+#include "content/public/test/test_utils.h"
 #include "grit/theme_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/controls/single_split_view.h"
@@ -80,6 +83,8 @@
  private:
   BrowserView* browser_view_;  // Not owned.
   scoped_ptr<ScopedTestingLocalState> local_state_;
+  scoped_ptr<predictors::PredictorDatabase> predictor_db_;
+  scoped_ptr<chrome::TestingIOThreadState> testing_io_thread_state_;
   DISALLOW_COPY_AND_ASSIGN(BrowserViewTest);
 };
 
@@ -101,7 +106,10 @@
   // the Profile.
   browser_view_->GetWidget()->CloseNow();
   browser_view_ = NULL;
+  content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
   BrowserWithTestWindowTest::TearDown();
+  testing_io_thread_state_.reset();
+  predictor_db_.reset();
 #if defined(OS_CHROMEOS)
   chromeos::input_method::Shutdown();
 #endif
@@ -134,7 +142,9 @@
   chromeos::input_method::InitializeForTesting(
       new chromeos::input_method::MockInputMethodManager);
 #endif
+  testing_io_thread_state_.reset(new chrome::TestingIOThreadState());
   BrowserWithTestWindowTest::SetUp();
+  predictor_db_.reset(new predictors::PredictorDatabase(GetProfile()));
   browser_view_ = static_cast<BrowserView*>(browser()->window());
 }
 
@@ -289,7 +299,6 @@
 
   BrowserViewIncognitoSwitcherTest()
       : browser_view_(NULL) {}
-  virtual ~BrowserViewIncognitoSwitcherTest() {}
 
   virtual void SetUp() OVERRIDE {
     Init();
diff --git a/chrome/browser/ui/views/profile_chooser_view.cc b/chrome/browser/ui/views/profile_chooser_view.cc
index 280853f..f432e77 100644
--- a/chrome/browser/ui/views/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profile_chooser_view.cc
@@ -10,6 +10,8 @@
 #include "chrome/browser/profiles/avatar_menu_model.h"
 #include "chrome/browser/profiles/profile_info_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/singleton_tabs.h"
+#include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -67,6 +69,7 @@
       browser_(browser),
       current_profile_view_(NULL),
       guest_button_view_(NULL),
+      users_button_view_(NULL),
       other_profiles_view_(NULL),
       signout_current_profile_view_(NULL) {
   avatar_menu_model_.reset(new AvatarMenuModel(
@@ -113,11 +116,12 @@
 
   if (sender == guest_button_view_) {
     avatar_menu_model_->SwitchToGuestProfileWindow(browser_);
-    return;
+  } else if (sender == users_button_view_) {
+    chrome::ShowSingletonTab(browser_, GURL(chrome::kChromeUIUserChooserURL));
+  } else {
+    DCHECK_EQ(sender, signout_current_profile_view_);
+    avatar_menu_model_->BeginSignOut();
   }
-
-  DCHECK_EQ(sender, signout_current_profile_view_);
-  avatar_menu_model_->BeginSignOut();
 }
 
 void ProfileChooserView::OnAvatarMenuModelChanged(
@@ -126,6 +130,7 @@
   // will actually delete them.
   current_profile_view_ = NULL;
   guest_button_view_ = NULL;
+  users_button_view_ = NULL;
   open_other_profile_indexes_map_.clear();
   other_profiles_view_ = NULL;
   signout_current_profile_view_ = NULL;
@@ -293,22 +298,19 @@
 }
 
 views::View* ProfileChooserView::CreateOptionsView() {
-  views::View* view = new views::View();
-
-  views::LabelButton* users_button = new views::LabelButton(
+  users_button_view_ = new views::LabelButton(
       this,
       l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_USERS_BUTTON));
-  users_button->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-  users_button->set_tag(IDS_PROFILES_PROFILE_USERS_BUTTON);
-  views::LabelButton* guest_button = new views::LabelButton(
+  users_button_view_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+  users_button_view_->set_tag(IDS_PROFILES_PROFILE_USERS_BUTTON);
+
+ guest_button_view_ = new views::LabelButton(
       this,
       l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_GUEST_BUTTON));
-  guest_button->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-  guest_button->set_tag(IDS_PROFILES_PROFILE_GUEST_BUTTON);
+  guest_button_view_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+  guest_button_view_->set_tag(IDS_PROFILES_PROFILE_GUEST_BUTTON);
 
-  DCHECK(!guest_button_view_);
-  guest_button_view_ = guest_button;
-
+  views::View* view = new views::View();
   views::GridLayout* layout = new views::GridLayout(view);
   view->SetLayoutManager(layout);
 
@@ -323,11 +325,11 @@
 
   const int kButtonHeight = 40;
   layout->StartRow(0, 0);
-  layout->AddView(users_button, 1, 1,
+  layout->AddView(users_button_view_, 1, 1,
                   views::GridLayout::FILL, views::GridLayout::FILL,
                   0, kButtonHeight);
   layout->AddView(new views::Separator(views::Separator::VERTICAL));
-  layout->AddView(guest_button, 1, 1,
+  layout->AddView(guest_button_view_, 1, 1,
                   views::GridLayout::FILL, views::GridLayout::FILL,
                   0, kButtonHeight);
 
diff --git a/chrome/browser/ui/views/profile_chooser_view.h b/chrome/browser/ui/views/profile_chooser_view.h
index e2de425..54dcb43 100644
--- a/chrome/browser/ui/views/profile_chooser_view.h
+++ b/chrome/browser/ui/views/profile_chooser_view.h
@@ -16,6 +16,10 @@
 class Image;
 }
 
+namespace views {
+class LabelButton;
+}
+
 class AvatarMenuModel;
 class Browser;
 class ProfileItemView;
@@ -42,6 +46,7 @@
  private:
   friend class AvatarMenuButtonTest;
   FRIEND_TEST_ALL_PREFIXES(AvatarMenuButtonTest, NewSignOut);
+  FRIEND_TEST_ALL_PREFIXES(AvatarMenuButtonTest, LaunchUserManagerScreen);
 
   typedef std::vector<size_t> Indexes;
   typedef std::map<views::View*, int> ViewIndexes;
@@ -77,7 +82,8 @@
   scoped_ptr<AvatarMenuModel> avatar_menu_model_;
   Browser* browser_;
   views::View* current_profile_view_;
-  views::View* guest_button_view_;
+  views::LabelButton* guest_button_view_;
+  views::LabelButton* users_button_view_;
   ViewIndexes open_other_profile_indexes_map_;
   views::View* other_profiles_view_;
   views::View* signout_current_profile_view_;
diff --git a/chrome/browser/ui/views/toolbar_view.cc b/chrome/browser/ui/views/toolbar_view.cc
index 98f7381..9fee7cf 100644
--- a/chrome/browser/ui/views/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar_view.cc
@@ -626,8 +626,8 @@
 
 bool ToolbarView::AcceleratorPressed(const ui::Accelerator& accelerator) {
   const views::View* focused_view = focus_manager()->GetFocusedView();
-  if (focused_view == location_bar_)
-    return false;  // Let location bar handle all accelerator events.
+  if (focused_view && (focused_view->id() == VIEW_ID_OMNIBOX))
+    return false;  // Let the omnibox handle all accelerator events.
   return AccessiblePaneView::AcceleratorPressed(accelerator);
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index adfeb11..83257da 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -5,11 +5,13 @@
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 
 #include "base/callback.h"
+#include "base/chromeos/chromeos_version.h"
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/histogram.h"
+#include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
@@ -20,6 +22,7 @@
 #include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
 #include "chrome/browser/chromeos/login/hwid_checker.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
@@ -32,6 +35,7 @@
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
@@ -103,6 +107,12 @@
   io_thread->ClearHostCache();
 }
 
+static bool Contains(const std::vector<std::string>& container,
+                     const std::string& value) {
+  return std::find(container.begin(), container.end(), value) !=
+         container.end();
+}
+
 }  // namespace
 
 namespace chromeos {
@@ -312,6 +322,59 @@
   }
 }
 
+static bool SetUserInputMethodImpl(
+    const std::string& username,
+    chromeos::input_method::InputMethodManager* manager) {
+  PrefService* const local_state = g_browser_process->local_state();
+
+  const base::DictionaryValue* users_lru_input_methods =
+      local_state->GetDictionary(prefs::kUsersLRUInputMethod);
+
+  if (users_lru_input_methods == NULL) {
+    DLOG(WARNING) << "SetUserInputMethod('" << username
+                  << "'): no kUsersLRUInputMethod";
+    return false;
+  }
+
+  std::string input_method;
+
+  if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
+                                                              &input_method)) {
+    DLOG(INFO) << "SetUserInputMethod('" << username
+               << "'): no input method for this user";
+    return false;
+  }
+
+  if (input_method.empty())
+    return false;
+
+  if (!manager->IsFullLatinKeyboard(input_method)) {
+    LOG(WARNING) << "SetUserInputMethod('" << username
+                 << "'): stored user LRU input method '" << input_method
+                 << "' is no longer Full Latin Keyboard Language"
+                 << " (entry dropped). Use hardware default instead.";
+
+    DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
+
+    base::DictionaryValue* const users_lru_input_methods = updater.Get();
+    if (users_lru_input_methods != NULL) {
+      users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
+    }
+    return false;
+  }
+
+  if (!Contains(manager->GetActiveInputMethodIds(), input_method)) {
+    if (!manager->EnableInputMethod(input_method)) {
+      DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
+                  << "'): user input method '" << input_method
+                  << "' is not enabled and enabling failed (ignored!).";
+    }
+  }
+  manager->ChangeInputMethod(input_method);
+
+  return true;
+}
+
 }  // namespace
 
 // SigninScreenHandler implementation ------------------------------------------
@@ -814,6 +877,10 @@
               &SigninScreenHandler::HandleUpdateOfflineLogin);
 }
 
+void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
+}
+
 void SigninScreenHandler::HandleGetUsers() {
   SendUserList(false);
 }
@@ -970,6 +1037,35 @@
   ShowSigninScreenIfReady();
 }
 
+void SigninScreenHandler::SetUserInputMethodHWDefault() {
+  chromeos::input_method::InputMethodManager* manager =
+      chromeos::input_method::InputMethodManager::Get();
+  manager->ChangeInputMethod(
+      manager->GetInputMethodUtil()->GetHardwareInputMethodId());
+}
+
+// Update keyboard layout to least recently used by the user.
+void SigninScreenHandler::SetUserInputMethod(const std::string& username) {
+  chromeos::input_method::InputMethodManager* const manager =
+      chromeos::input_method::InputMethodManager::Get();
+
+  const chromeos::input_method::InputMethodUtil& ime_util =
+      *manager->GetInputMethodUtil();
+
+  const bool succeed = SetUserInputMethodImpl(username, manager);
+
+  // This is also a case when LRU layout is set only for a few local users,
+  // thus others need to be switched to default locale.
+  // Otherwise they will end up using another user's locale to log in.
+  if (!succeed) {
+    DLOG(INFO) << "SetUserInputMethod('" << username
+               << "'): failed to set user layout. Switching to default '"
+               << ime_util.GetHardwareInputMethodId() << "'";
+
+    SetUserInputMethodHWDefault();
+  }
+}
+
 void SigninScreenHandler::ShowSigninScreenIfReady() {
   if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
     return;
@@ -991,6 +1087,10 @@
   else
     delegate_->LoadWallpaper(email_);
 
+  // Set Least Recently Used input method for the user.
+  if (!email_.empty())
+    SetUserInputMethod(email_);
+
   LoadAuthExtension(!gaia_silent_load_, false, false);
   UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
 
@@ -1210,6 +1310,7 @@
         &SigninScreenHandler::ShowSigninScreenIfReady,
         weak_factory_.GetWeakPtr()));
   }
+  SetUserInputMethodHWDefault();
 }
 
 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
@@ -1451,7 +1552,7 @@
     // There might be multiple messages from OOBE UI so send notifications after
     // the first one only.
     content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
+        chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
         content::NotificationService::AllSources(),
         content::NotificationService::NoDetails());
     TRACE_EVENT_ASYNC_END0(
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index aea2d03..5768ab2 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -193,6 +193,9 @@
   virtual void UpdateState(NetworkStateInformer::State state,
                            ErrorScreenActor::ErrorReason reason) OVERRIDE;
 
+  // Required Local State preferences.
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
  private:
   enum UIState {
     UI_STATE_UNKNOWN = 0,
@@ -379,6 +382,12 @@
   // Attempts login for test.
   void SubmitLoginFormForTest();
 
+  // Update current input method (namely keyboard layout) to LRU by this user.
+  void SetUserInputMethod(const std::string& username);
+
+  // Update current input method to HW default.
+  void SetUserInputMethodHWDefault();
+
   // Current UI state of the signin screen.
   UIState ui_state_;
 
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc
index 293cae7..b885b01 100644
--- a/chrome/browser/ui/webui/crashes_ui.cc
+++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -19,7 +19,6 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -105,8 +104,7 @@
 }
 
 void CrashesDOMHandler::RegisterMessages() {
-  upload_list_->LoadUploadListAsynchronously(
-      content::BrowserThread::GetBlockingPool());
+  upload_list_->LoadUploadListAsynchronously();
 
   web_ui()->RegisterMessageCallback("requestCrashList",
       base::Bind(&CrashesDOMHandler::HandleRequestCrashes,
diff --git a/chrome/browser/ui/webui/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads_dom_handler.cc
index 124b278..72245e1 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/downloads_dom_handler.cc
@@ -99,6 +99,8 @@
       return "UNCOMMON_CONTENT";
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
       return "DANGEROUS_HOST";
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+      return "POTENTIALLY_UNWANTED";
     default:
       // Don't return a danger type string if it is NOT_DANGEROUS or
       // MAYBE_DANGEROUS_CONTENT.
@@ -161,7 +163,9 @@
                download_item->GetDangerType() ==
                    content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT ||
                download_item->GetDangerType() ==
-                   content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST);
+                   content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
+               download_item->GetDangerType() ==
+                   content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED);
         const char* danger_type_value =
             GetDangerTypeString(download_item->GetDangerType());
         file_value->SetString("danger_type", danger_type_value);
diff --git a/chrome/browser/ui/webui/downloads_ui.cc b/chrome/browser/ui/webui/downloads_ui.cc
index 2eec32b..b90b28c 100644
--- a/chrome/browser/ui/webui/downloads_ui.cc
+++ b/chrome/browser/ui/webui/downloads_ui.cc
@@ -59,6 +59,8 @@
                              IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT);
   source->AddLocalizedString("danger_uncommon_desc",
                              IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT);
+  source->AddLocalizedString("danger_potentially_unwanted_desc",
+                             IDS_PROMPT_POTENTIALLY_UNWANTED_DOWNLOAD);
   source->AddLocalizedString("danger_save", IDS_CONFIRM_DOWNLOAD);
   source->AddLocalizedString("danger_discard", IDS_DISCARD_DOWNLOAD);
 
diff --git a/chrome/browser/ui/webui/favicon_source.cc b/chrome/browser/ui/webui/favicon_source.cc
index 3c322bc..eb284e6 100644
--- a/chrome/browser/ui/webui/favicon_source.cc
+++ b/chrome/browser/ui/webui/favicon_source.cc
@@ -11,8 +11,6 @@
 #include "chrome/browser/history/top_sites.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_io_context.h"
-#include "chrome/browser/search/instant_service.h"
-#include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/common/favicon/favicon_url_parser.h"
 #include "chrome/common/url_constants.h"
 #include "grit/locale_settings.h"
diff --git a/chrome/browser/ui/webui/flash_ui.cc b/chrome/browser/ui/webui/flash_ui.cc
index 050b033..52b70e3 100644
--- a/chrome/browser/ui/webui/flash_ui.cc
+++ b/chrome/browser/ui/webui/flash_ui.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/ui/webui/crashes_ui.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/url_constants.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/browser/gpu_data_manager_observer.h"
 #include "content/public/browser/plugin_service.h"
@@ -143,8 +142,7 @@
       has_plugin_info_(false) {
   // Request Crash data asynchronously.
   upload_list_ = CrashUploadList::Create(this);
-  upload_list_->LoadUploadListAsynchronously(
-      content::BrowserThread::GetBlockingPool());
+  upload_list_->LoadUploadListAsynchronously();
 
   // Watch for changes in GPUInfo.
   GpuDataManager::GetInstance()->AddObserver(this);
diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc
index b98f865..f078123 100644
--- a/chrome/browser/ui/webui/inspect_ui.cc
+++ b/chrome/browser/ui/webui/inspect_ui.cc
@@ -63,6 +63,7 @@
 static const char kDataFile[] = "targets-data.json";
 static const char kAdbPages[] = "adb-pages";
 
+static const char kAppTargetType[] = "app";
 static const char kExtensionTargetType[]  = "extension";
 static const char kPageTargetType[]  = "page";
 static const char kWorkerTargetType[]  = "worker";
@@ -138,7 +139,12 @@
       const extensions::Extension* extension = extension_service->
           extensions()->GetByID(url.host());
       if (extension) {
-        target_type = kExtensionTargetType;
+        if (extension->is_hosted_app()
+            || extension->is_legacy_packaged_app()
+            || extension->is_platform_app())
+          target_type = kAppTargetType;
+        else
+          target_type = kExtensionTargetType;
         title = extension->name();
       }
     }
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
index 6d4505a..54de606 100644
--- a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
+++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -19,7 +19,6 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -113,8 +112,7 @@
 }
 
 void WebRtcLogsDOMHandler::RegisterMessages() {
-  upload_list_->LoadUploadListAsynchronously(
-      content::BrowserThread::GetBlockingPool());
+  upload_list_->LoadUploadListAsynchronously();
 
   web_ui()->RegisterMessageCallback("requestWebRtcLogsList",
       base::Bind(&WebRtcLogsDOMHandler::HandleRequestWebRtcLogs,
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index b6e69f3..3fa9351 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -375,7 +375,7 @@
   if (!app_page_names || !app_page_names->GetSize()) {
     ListPrefUpdate update(prefs, prefs::kNtpAppPageNames);
     ListValue* list = update.Get();
-    list->Set(0, Value::CreateStringValue(
+    list->Set(0, new base::StringValue(
         l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME)));
     dictionary->Set("appPageNames",
                     static_cast<ListValue*>(list->DeepCopy()));
@@ -652,7 +652,7 @@
   PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
   ListPrefUpdate update(prefs, prefs::kNtpAppPageNames);
   ListValue* list = update.Get();
-  list->Set(static_cast<size_t>(page_index), Value::CreateStringValue(name));
+  list->Set(static_cast<size_t>(page_index), new base::StringValue(name));
 }
 
 void AppLauncherHandler::HandleGenerateAppForLink(const ListValue* args) {
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
index 0d4836a..dfe5ed9 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui.cc
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
@@ -106,6 +106,7 @@
     web_ui->AddMessageHandler(new MostVisitedHandler());
     web_ui->AddMessageHandler(new RecentlyClosedTabsHandler());
 #if !defined(OS_ANDROID)
+    web_ui->AddMessageHandler(new FaviconWebUIHandler());
     web_ui->AddMessageHandler(new MetricsHandler());
     web_ui->AddMessageHandler(new NewTabPageHandler());
     if (NewTabUI::IsDiscoveryInNTPEnabled())
@@ -121,14 +122,13 @@
         web_ui->AddMessageHandler(new AppLauncherHandler(service));
     }
 #endif
-
-    web_ui->AddMessageHandler(new FaviconWebUIHandler());
   }
 
 #if defined(OS_ANDROID)
   // These handlers are specific to the Android NTP page.
   web_ui->AddMessageHandler(new BookmarksHandler());
   web_ui->AddMessageHandler(new ContextMenuHandler());
+  web_ui->AddMessageHandler(new FaviconWebUIHandler());
   web_ui->AddMessageHandler(new NavigationHandler());
   web_ui->AddMessageHandler(new NewTabPageReadyHandler());
   if (!GetProfile()->IsOffTheRecord())
diff --git a/chrome/browser/ui/webui/ntp/thumbnail_source.cc b/chrome/browser/ui/webui/ntp/thumbnail_source.cc
index 5895f9c..324c694 100644
--- a/chrome/browser/ui/webui/ntp/thumbnail_source.cc
+++ b/chrome/browser/ui/webui/ntp/thumbnail_source.cc
@@ -9,8 +9,6 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_io_context.h"
-#include "chrome/browser/search/instant_service.h"
-#include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/thumbnails/thumbnail_service.h"
 #include "chrome/browser/thumbnails/thumbnail_service_factory.h"
 #include "chrome/common/url_constants.h"
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index 5152da9..800b984 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -360,6 +360,8 @@
       IDS_OPTIONS_SETTINGS_ACCESSIBILITY_SCREEN_MAGNIFIER_PARTIAL },
     { "accessibilityLargeCursor",
       IDS_OPTIONS_SETTINGS_ACCESSIBILITY_LARGE_CURSOR_DESCRIPTION },
+    { "accessibilityStickyKeys",
+      IDS_OPTIONS_SETTINGS_ACCESSIBILITY_STICKY_KEYS_DESCRIPTION },
     { "accessibilitySpokenFeedback",
       IDS_OPTIONS_SETTINGS_ACCESSIBILITY_SPOKEN_FEEDBACK_DESCRIPTION },
     { "accessibilityTitle",
@@ -500,6 +502,10 @@
   magnifier_list->Append(option_partial.release());
 
   values->Set("magnifierList", magnifier_list.release());
+
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  values->SetBoolean("enableStickyKeys",
+                     command_line.HasSwitch(switches::kEnableStickyKeys));
 #endif
 
 #if defined(OS_MACOSX)
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 39b6d61..c8b991d 100644
--- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
@@ -33,6 +33,8 @@
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/cros/network_property_ui_data.h"
 #include "chrome/browser/chromeos/enrollment_dialog_view.h"
+#include "chrome/browser/chromeos/login/user.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/mobile_config.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
 #include "chrome/browser/chromeos/options/network_connect.h"
@@ -51,6 +53,7 @@
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/favorite_state.h"
+#include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_device_handler.h"
@@ -282,8 +285,10 @@
 const base::DictionaryValue* FindPolicyForActiveUser(
     const NetworkState* network,
     onc::ONCSource* onc_source) {
-  *onc_source = network->onc_source();
-  return NetworkLibrary::Get()->FindOncForNetwork(network->guid());
+  const User* user = UserManager::Get()->GetActiveUser();
+  std::string username_hash = user ? user->username_hash() : std::string();
+  return NetworkHandler::Get()->managed_network_configuration_handler()
+      ->FindPolicyByGUID(username_hash, network->guid(), onc_source);
 }
 
 std::string ActivationStateString(const std::string& activation_state) {
diff --git a/chrome/browser/ui/webui/sync_setup_handler.cc b/chrome/browser/ui/webui/sync_setup_handler.cc
index 491b60a..07fb346 100644
--- a/chrome/browser/ui/webui/sync_setup_handler.cc
+++ b/chrome/browser/ui/webui/sync_setup_handler.cc
@@ -735,7 +735,15 @@
     return;
   }
 
-  // Bring up the existing wizard, or just display it on this page.
+  // If a setup wizard is already present, but not on this page, close the
+  // blank setup overlay on this page. This can happen if the user navigates to
+  // chrome://settings/syncSetup in more than one tab. See crbug.com/261566.
+  // Note: The following block will transfer focus to the existing wizard.
+  if (IsExistingWizardPresent() && !IsActiveLogin())
+    CloseOverlay();
+
+  // If a setup wizard is present on this page or another, bring it to focus.
+  // Otherwise, display a new one on this page.
   if (!FocusExistingWizardIfPresent())
     OpenSyncSetup();
 }
@@ -880,10 +888,18 @@
   CloseOverlay();
 }
 
-bool SyncSetupHandler::FocusExistingWizardIfPresent() {
+bool SyncSetupHandler::IsExistingWizardPresent() {
   LoginUIService* service = GetLoginUIService();
-  if (!service->current_login_ui())
+  DCHECK(service);
+  return service->current_login_ui() != NULL;
+}
+
+bool SyncSetupHandler::FocusExistingWizardIfPresent() {
+  if (!IsExistingWizardPresent())
     return false;
+
+  LoginUIService* service = GetLoginUIService();
+  DCHECK(service);
   service->current_login_ui()->FocusUI();
   return true;
 }
diff --git a/chrome/browser/ui/webui/sync_setup_handler.h b/chrome/browser/ui/webui/sync_setup_handler.h
index 2f562ac..574bb28 100644
--- a/chrome/browser/ui/webui/sync_setup_handler.h
+++ b/chrome/browser/ui/webui/sync_setup_handler.h
@@ -141,6 +141,9 @@
   // Returns true if this object is the active login object.
   bool IsActiveLogin() const;
 
+  // If a wizard already exists, return true. Otherwise, return false.
+  bool IsExistingWizardPresent();
+
   // If a wizard already exists, focus it and return true.
   bool FocusExistingWizardIfPresent();
 
diff --git a/chrome/browser/ui/webui/uber/uber_ui.cc b/chrome/browser/ui/webui/uber/uber_ui.cc
index 2c68102..a55842d 100644
--- a/chrome/browser/ui/webui/uber/uber_ui.cc
+++ b/chrome/browser/ui/webui/uber/uber_ui.cc
@@ -210,14 +210,12 @@
     case chrome::NOTIFICATION_EXTENSION_LOADED:
     case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
       Profile* profile = Profile::FromWebUI(web_ui());
-      bool overridesHistory = HasExtensionType(profile,
-          chrome::kChromeUIHistoryHost);
-      scoped_ptr<Value> controlsValue(
-          Value::CreateStringValue(chrome::kChromeUIHistoryHost));
-      scoped_ptr<Value> overrideValue(
-          Value::CreateStringValue(overridesHistory ? "yes" : "no"));
+      bool overrides_history =
+          HasExtensionType(profile, chrome::kChromeUIHistoryHost);
       web_ui()->CallJavascriptFunction(
-          "uber_frame.setNavigationOverride", *controlsValue, *overrideValue);
+          "uber_frame.setNavigationOverride",
+          base::StringValue(chrome::kChromeUIHistoryHost),
+          base::StringValue(overrides_history ? "yes" : "no"));
       break;
     }
     default:
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
index 2790756..a66d5c9 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
@@ -76,32 +76,6 @@
   return location / grid_size * grid_size;
 }
 
-// A special test class for use with browser creation - it will create a
-// browser thread and deletes it after all other things have been destroyed.
-class WindowSizerTestWithBrowser : public WindowSizerTest {
- public:
-  WindowSizerTestWithBrowser();
-  virtual ~WindowSizerTestWithBrowser();
-
- private:
-  // Note: It is important to delete the thread after the browser instances got
-  // deleted. For this we transfer the thread here.
-  scoped_ptr<content::TestBrowserThread> ui_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(WindowSizerTestWithBrowser);
-};
-
-// The class function definitions from window_sizer_common_unittest.h
-WindowSizerTestWithBrowser::WindowSizerTestWithBrowser() {
-  // Set up a UI message thread.
-  base::MessageLoopForUI* ui_loop = message_loop();
-  ui_thread_.reset(
-      new content::TestBrowserThread(content::BrowserThread::UI, ui_loop));
-}
-
-WindowSizerTestWithBrowser::~WindowSizerTestWithBrowser() {
-}
-
 }  // namespace
 
 // Test that the window is sized appropriately for the first run experience
@@ -456,7 +430,7 @@
 }
 
 // Test the placement of newly created windows.
-TEST_F(WindowSizerTestWithBrowser, PlaceNewWindows) {
+TEST_F(WindowSizerTest, PlaceNewWindows) {
   // Create a dummy window.
   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
   window->SetBounds(gfx::Rect(16, 32, 640, 320));
@@ -576,7 +550,7 @@
 // Test the placement of newly created windows on an empty desktop.
 // This test supplements "PlaceNewWindows" by testing the creation of a newly
 // created browser window on an empty desktop.
-TEST_F(WindowSizerTestWithBrowser, PlaceNewBrowserWindowOnEmptyDesktop) {
+TEST_F(WindowSizerTest, PlaceNewBrowserWindowOnEmptyDesktop) {
   // Create a browser which we can use to pass into the GetWindowBounds
   // function.
   scoped_ptr<TestingProfile> profile(new TestingProfile());
@@ -652,7 +626,7 @@
 #endif
 
 // Test the placement of newly created windows on multiple dislays.
-TEST_F(WindowSizerTestWithBrowser, MAYBE_PlaceNewWindowsOnMultipleDisplays) {
+TEST_F(WindowSizerTest, MAYBE_PlaceNewWindowsOnMultipleDisplays) {
   UpdateDisplay("1600x1200,1600x1200");
   const gfx::Rect secondary(1600, 0, 1600, 1200);
 
@@ -741,7 +715,7 @@
 }
 
 // Test that the show state is properly returned for non default cases.
-TEST_F(WindowSizerTestWithBrowser, TestShowState) {
+TEST_F(WindowSizerTest, TestShowState) {
   // Creating a browser & window to play with.
   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
   window->SetBounds(gfx::Rect(16, 32, 640, 320));
@@ -846,7 +820,7 @@
 }
 
 // Test that the default show state override behavior is properly handled.
-TEST_F(WindowSizerTestWithBrowser, TestShowStateDefaults) {
+TEST_F(WindowSizerTest, TestShowStateDefaults) {
   // Creating a browser & window to play with.
   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
   window->SetBounds(gfx::Rect(16, 32, 640, 320));
diff --git a/chrome/browser/upload_list.cc b/chrome/browser/upload_list.cc
new file mode 100644
index 0000000..3f618aa
--- /dev/null
+++ b/chrome/browser/upload_list.cc
@@ -0,0 +1,95 @@
+// 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/upload_list.h"
+
+#include <algorithm>
+#include <iterator>
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+UploadList::UploadInfo::UploadInfo(const std::string& c, const base::Time& t)
+    : id(c), time(t) {}
+
+UploadList::UploadInfo::~UploadInfo() {}
+
+UploadList::UploadList(Delegate* delegate,
+                       const base::FilePath& upload_log_path)
+    : delegate_(delegate),
+      upload_log_path_(upload_log_path) {}
+
+UploadList::~UploadList() {}
+
+void UploadList::LoadUploadListAsynchronously() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  BrowserThread::PostBlockingPoolTask(
+      FROM_HERE,
+      base::Bind(&UploadList::LoadUploadListAndInformDelegateOfCompletion,
+                 this));
+}
+
+void UploadList::ClearDelegate() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  delegate_ = NULL;
+}
+
+void UploadList::LoadUploadListAndInformDelegateOfCompletion() {
+  LoadUploadList();
+  BrowserThread::PostTask(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&UploadList::InformDelegateOfCompletion, this));
+}
+
+void UploadList::LoadUploadList() {
+  if (base::PathExists(upload_log_path_)) {
+    std::string contents;
+    file_util::ReadFileToString(upload_log_path_, &contents);
+    std::vector<std::string> log_entries;
+    base::SplitStringAlongWhitespace(contents, &log_entries);
+    ParseLogEntries(log_entries);
+  }
+}
+
+void UploadList::AppendUploadInfo(const UploadInfo& info) {
+  uploads_.push_back(info);
+}
+
+void UploadList::ParseLogEntries(
+    const std::vector<std::string>& log_entries) {
+  std::vector<std::string>::const_reverse_iterator i;
+  for (i = log_entries.rbegin(); i != log_entries.rend(); ++i) {
+    std::vector<std::string> components;
+    base::SplitString(*i, ',', &components);
+    // Skip any blank (or corrupted) lines.
+    if (components.size() != 2)
+      continue;
+    double seconds_since_epoch;
+    if (!base::StringToDouble(components[0], &seconds_since_epoch))
+      continue;
+    UploadInfo info(components[1],
+                    base::Time::FromDoubleT(seconds_since_epoch));
+    uploads_.push_back(info);
+  }
+}
+
+void UploadList::InformDelegateOfCompletion() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (delegate_)
+    delegate_->OnUploadListAvailable();
+}
+
+void UploadList::GetUploads(unsigned int max_count,
+                            std::vector<UploadInfo>* uploads) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  std::copy(uploads_.begin(),
+            uploads_.begin() + std::min<size_t>(uploads_.size(), max_count),
+            std::back_inserter(*uploads));
+}
diff --git a/chrome/browser/upload_list.h b/chrome/browser/upload_list.h
new file mode 100644
index 0000000..23c4ff5
--- /dev/null
+++ b/chrome/browser/upload_list.h
@@ -0,0 +1,88 @@
+// 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_UPLOAD_LIST_H_
+#define CHROME_BROWSER_UPLOAD_LIST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+
+// Loads and parses an upload list text file of the format
+// time,id
+// time,id
+// etc.
+// where each line represents an upload and "time" is Unix time. Must be used
+// from the UI thread. The loading and parsing is done on a blocking pool task
+// runner.
+class UploadList : public base::RefCountedThreadSafe<UploadList> {
+ public:
+  struct UploadInfo {
+    UploadInfo(const std::string& c, const base::Time& t);
+    ~UploadInfo();
+
+    std::string id;
+    base::Time time;
+  };
+
+  class Delegate {
+   public:
+    // Invoked when the upload list has been loaded. Will be called on the
+    // UI thread.
+    virtual void OnUploadListAvailable() = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  // Creates a new upload list with the given callback delegate.
+  UploadList(Delegate* delegate, const base::FilePath& upload_log_path);
+
+  // Starts loading the upload list. OnUploadListAvailable will be called when
+  // loading is complete.
+  void LoadUploadListAsynchronously();
+
+  // Clears the delegate, so that any outstanding asynchronous load will not
+  // call the delegate on completion.
+  void ClearDelegate();
+
+  // Populates |uploads| with the |max_count| most recent uploads,
+  // in reverse chronological order.
+  // Must be called only after OnUploadListAvailable has been called.
+  void GetUploads(unsigned int max_count, std::vector<UploadInfo>* uploads);
+
+ protected:
+  virtual ~UploadList();
+
+  // Reads the upload log and stores the entries in |uploads_|.
+  virtual void LoadUploadList();
+
+  // Adds |info| to |uploads_|.
+  void AppendUploadInfo(const UploadInfo& info);
+
+ private:
+  friend class base::RefCountedThreadSafe<UploadList>;
+  FRIEND_TEST_ALL_PREFIXES(UploadListTest, ParseLogEntries);
+
+  // Manages the background thread work for LoadUploadListAsynchronously().
+  void LoadUploadListAndInformDelegateOfCompletion();
+
+  // Calls the delegate's callback method, if there is a delegate.
+  void InformDelegateOfCompletion();
+
+  // Parses upload log lines, converting them to UploadInfo entries.
+  void ParseLogEntries(const std::vector<std::string>& log_entries);
+
+  std::vector<UploadInfo> uploads_;
+  Delegate* delegate_;
+  const base::FilePath upload_log_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(UploadList);
+};
+
+#endif  // CHROME_BROWSER_UPLOAD_LIST_H_
diff --git a/chrome/browser/upload_list_unittest.cc b/chrome/browser/upload_list_unittest.cc
new file mode 100644
index 0000000..153f9db
--- /dev/null
+++ b/chrome/browser/upload_list_unittest.cc
@@ -0,0 +1,44 @@
+// 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 <string>
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "chrome/browser/upload_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Test that UploadList can parse a vector of log entry strings to a vector of
+// UploadInfo objects. See the UploadList declaration for a description of the
+// log entry string format.
+TEST(UploadListTest, ParseLogEntries) {
+  const char kTestTime[] = "1234567890";
+  const char kTestID[] = "0123456789abcdef";
+  std::string test_entry = kTestTime;
+  test_entry += ",";
+  test_entry.append(kTestID, sizeof(kTestID));
+
+  scoped_refptr<UploadList> upload_list =
+      new UploadList(NULL, base::FilePath());
+
+  // 1 entry.
+  std::vector<std::string> log_entries;
+  log_entries.push_back(test_entry);
+  upload_list->ParseLogEntries(log_entries);
+  EXPECT_EQ(1u, upload_list->uploads_.size());
+  double time_double = upload_list->uploads_[0].time.ToDoubleT();
+  EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
+  EXPECT_STREQ(kTestID, upload_list->uploads_[0].id.c_str());
+
+  // Add 3 more entries.
+  log_entries.push_back(test_entry);
+  log_entries.push_back(test_entry);
+  upload_list->ParseLogEntries(log_entries);
+  EXPECT_EQ(4u, upload_list->uploads_.size());
+  time_double = upload_list->uploads_[3].time.ToDoubleT();
+  EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
+  EXPECT_STREQ(kTestID, upload_list->uploads_[3].id.c_str());
+}
diff --git a/chrome/browser/usb/usb_device.cc b/chrome/browser/usb/usb_device_handle.cc
similarity index 82%
rename from chrome/browser/usb/usb_device.cc
rename to chrome/browser/usb/usb_device_handle.cc
index 13fc395..99faad1 100644
--- a/chrome/browser/usb/usb_device.cc
+++ b/chrome/browser/usb/usb_device_handle.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2012 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/usb/usb_device.h"
+#include "chrome/browser/usb/usb_device_handle.h"
 
+#include <algorithm>
 #include <vector>
 
 #include "base/stl_util.h"
@@ -28,36 +29,36 @@
 }
 
 static uint8 CreateRequestType(const UsbEndpointDirection direction,
-    const UsbDevice::TransferRequestType request_type,
-    const UsbDevice::TransferRecipient recipient) {
+    const UsbDeviceHandle::TransferRequestType request_type,
+    const UsbDeviceHandle::TransferRecipient recipient) {
   uint8 result = ConvertTransferDirection(direction);
 
   switch (request_type) {
-    case UsbDevice::STANDARD:
+    case UsbDeviceHandle::STANDARD:
       result |= LIBUSB_REQUEST_TYPE_STANDARD;
       break;
-    case UsbDevice::CLASS:
+    case UsbDeviceHandle::CLASS:
       result |= LIBUSB_REQUEST_TYPE_CLASS;
       break;
-    case UsbDevice::VENDOR:
+    case UsbDeviceHandle::VENDOR:
       result |= LIBUSB_REQUEST_TYPE_VENDOR;
       break;
-    case UsbDevice::RESERVED:
+    case UsbDeviceHandle::RESERVED:
       result |= LIBUSB_REQUEST_TYPE_RESERVED;
       break;
   }
 
   switch (recipient) {
-    case UsbDevice::DEVICE:
+    case UsbDeviceHandle::DEVICE:
       result |= LIBUSB_RECIPIENT_DEVICE;
       break;
-    case UsbDevice::INTERFACE:
+    case UsbDeviceHandle::INTERFACE:
       result |= LIBUSB_RECIPIENT_INTERFACE;
       break;
-    case UsbDevice::ENDPOINT:
+    case UsbDeviceHandle::ENDPOINT:
       result |= LIBUSB_RECIPIENT_ENDPOINT;
       break;
-    case UsbDevice::OTHER:
+    case UsbDeviceHandle::OTHER:
       result |= LIBUSB_RECIPIENT_OTHER;
       break;
   }
@@ -90,33 +91,35 @@
 
 static void LIBUSB_CALL HandleTransferCompletion(
     struct libusb_transfer* transfer) {
-  UsbDevice* const device = reinterpret_cast<UsbDevice*>(transfer->user_data);
+  UsbDeviceHandle* const device =
+      reinterpret_cast<UsbDeviceHandle*>(transfer->user_data);
   device->TransferComplete(transfer);
 }
 
 }  // namespace
 
-UsbDevice::Transfer::Transfer() : length(0) {}
+UsbDeviceHandle::Transfer::Transfer() : length(0) {}
 
-UsbDevice::Transfer::~Transfer() {}
+UsbDeviceHandle::Transfer::~Transfer() {}
 
-UsbDevice::UsbDevice(UsbService* service, PlatformUsbDeviceHandle handle)
+UsbDeviceHandle::UsbDeviceHandle(
+    UsbService* service,
+    PlatformUsbDeviceHandle handle)
     : service_(service), handle_(handle) {
   DCHECK(handle) << "Cannot create device with NULL handle.";
 }
 
-UsbDevice::UsbDevice() : service_(NULL), handle_(NULL) {}
+UsbDeviceHandle::UsbDeviceHandle() : service_(NULL), handle_(NULL) {}
 
-UsbDevice::~UsbDevice() {}
+UsbDeviceHandle::~UsbDeviceHandle() {}
 
-void UsbDevice::Close(const base::Callback<void()>& callback) {
+void UsbDeviceHandle::Close() {
   CheckDevice();
   service_->CloseDevice(this);
   handle_ = NULL;
-  callback.Run();
 }
 
-void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) {
+void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) {
   base::AutoLock lock(lock_);
 
   // TODO(gdk): Handle device disconnect.
@@ -196,8 +199,7 @@
   libusb_free_transfer(handle);
 }
 
-void UsbDevice::ListInterfaces(UsbConfigDescriptor* config,
-                               const UsbInterfaceCallback& callback) {
+bool UsbDeviceHandle::ListInterfaces(UsbConfigDescriptor* config) {
   CheckDevice();
 
   PlatformUsbDevice device = libusb_get_device(handle_);
@@ -208,39 +210,41 @@
   if (list_result == 0) {
     config->Reset(platform_config);
   }
-  callback.Run(list_result == 0);
+  return list_result == 0;
 }
 
-void UsbDevice::ClaimInterface(const int interface_number,
-                               const UsbInterfaceCallback& callback) {
+bool UsbDeviceHandle::ClaimInterface(const int interface_number) {
   CheckDevice();
 
   const int claim_result = libusb_claim_interface(handle_, interface_number);
-  callback.Run(claim_result == 0);
+  return claim_result == 0;
 }
 
-void UsbDevice::ReleaseInterface(const int interface_number,
-                                 const UsbInterfaceCallback& callback) {
+bool UsbDeviceHandle::ReleaseInterface(const int interface_number) {
   CheckDevice();
 
   const int release_result = libusb_release_interface(handle_,
                                                       interface_number);
-  callback.Run(release_result == 0);
+  return release_result == 0;
 }
 
-void UsbDevice::SetInterfaceAlternateSetting(
+bool UsbDeviceHandle::SetInterfaceAlternateSetting(
     const int interface_number,
-    const int alternate_setting,
-    const UsbInterfaceCallback& callback) {
+    const int alternate_setting) {
   CheckDevice();
 
   const int setting_result = libusb_set_interface_alt_setting(handle_,
       interface_number, alternate_setting);
 
-  callback.Run(setting_result == 0);
+  return setting_result == 0;
 }
 
-void UsbDevice::ControlTransfer(const UsbEndpointDirection direction,
+bool UsbDeviceHandle::ResetDevice() {
+  CheckDevice();
+  return libusb_reset_device(handle_) == 0;
+}
+
+void UsbDeviceHandle::ControlTransfer(const UsbEndpointDirection direction,
     const TransferRequestType request_type, const TransferRecipient recipient,
     const uint8 request, const uint16 value, const uint16 index,
     net::IOBuffer* buffer, const size_t length, const unsigned int timeout,
@@ -267,7 +271,7 @@
                  callback);
 }
 
-void UsbDevice::BulkTransfer(const UsbEndpointDirection direction,
+void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction,
     const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
     const unsigned int timeout, const UsbTransferCallback& callback) {
   CheckDevice();
@@ -280,7 +284,7 @@
   SubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback);
 }
 
-void UsbDevice::InterruptTransfer(const UsbEndpointDirection direction,
+void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction,
     const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
     const unsigned int timeout, const UsbTransferCallback& callback) {
   CheckDevice();
@@ -293,7 +297,7 @@
   SubmitTransfer(transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback);
 }
 
-void UsbDevice::IsochronousTransfer(const UsbEndpointDirection direction,
+void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction,
     const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
     const unsigned int packets, const unsigned int packet_length,
     const unsigned int timeout, const UsbTransferCallback& callback) {
@@ -313,16 +317,11 @@
   SubmitTransfer(transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback);
 }
 
-void UsbDevice::ResetDevice(const base::Callback<void(bool)>& callback) {
-  CheckDevice();
-  callback.Run(libusb_reset_device(handle_) == 0);
-}
-
-void UsbDevice::CheckDevice() {
+void UsbDeviceHandle::CheckDevice() {
   DCHECK(handle_) << "Device is already closed.";
 }
 
-void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle,
+void UsbDeviceHandle::SubmitTransfer(PlatformUsbTransferHandle handle,
                                UsbTransferType transfer_type,
                                net::IOBuffer* buffer,
                                const size_t length,
diff --git a/chrome/browser/usb/usb_device.h b/chrome/browser/usb/usb_device_handle.h
similarity index 81%
rename from chrome/browser/usb/usb_device.h
rename to chrome/browser/usb/usb_device_handle.h
index 0625e74..e46ab19 100644
--- a/chrome/browser/usb/usb_device.h
+++ b/chrome/browser/usb/usb_device_handle.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 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_USB_USB_DEVICE_H_
-#define CHROME_BROWSER_USB_USB_DEVICE_H_
+#ifndef CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_
+#define CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_
 
 #include <map>
 #include <vector>
@@ -43,12 +43,11 @@
 
 typedef base::Callback<void(UsbTransferStatus, scoped_refptr<net::IOBuffer>,
     size_t)> UsbTransferCallback;
-typedef base::Callback<void(bool)> UsbInterfaceCallback;
 
 // A UsbDevice wraps the platform's underlying representation of what a USB
 // device actually is, and provides accessors for performing many of the
 // standard USB operations.
-class UsbDevice : public base::RefCounted<UsbDevice> {
+class UsbDeviceHandle : public base::RefCounted<UsbDeviceHandle> {
  public:
   enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED };
   enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER };
@@ -56,28 +55,23 @@
   // Usually you will not want to directly create a UsbDevice, favoring to let
   // the UsbService take care of the logistics of getting a platform device
   // handle and handling events for it.
-  UsbDevice(UsbService* service, PlatformUsbDeviceHandle handle);
+  UsbDeviceHandle(UsbService* service, PlatformUsbDeviceHandle handle);
 
   PlatformUsbDeviceHandle handle() { return handle_; }
 
-  // Close the USB device and release the underlying platform device. |callback|
-  // is invoked after the device has been closed.
-  virtual void Close(const base::Callback<void()>& callback);
+  // Close the USB device and release the underlying platform device.
+  virtual void Close();
 
-  virtual void ListInterfaces(UsbConfigDescriptor* config,
-                              const UsbInterfaceCallback& callback);
-
-  virtual void ClaimInterface(const int interface_number,
-                              const UsbInterfaceCallback& callback);
-
-  virtual void ReleaseInterface(const int interface_number,
-                                const UsbInterfaceCallback& callback);
-
-  virtual void SetInterfaceAlternateSetting(
+  // Device manipulation operations. These methods are blocking.
+  virtual bool ListInterfaces(UsbConfigDescriptor* config);
+  virtual bool ClaimInterface(const int interface_number);
+  virtual bool ReleaseInterface(const int interface_number);
+  virtual bool SetInterfaceAlternateSetting(
       const int interface_number,
-      const int alternate_setting,
-      const UsbInterfaceCallback& callback);
+      const int alternate_setting);
+  virtual bool ResetDevice();
 
+  // Async IO.
   virtual void ControlTransfer(const UsbEndpointDirection direction,
                                const TransferRequestType request_type,
                                const TransferRecipient recipient,
@@ -112,8 +106,6 @@
                                    const unsigned int timeout,
                                    const UsbTransferCallback& callback);
 
-  virtual void ResetDevice(const base::Callback<void(bool)>& callback);
-
   // Normal code should not call this function. It is called by the platform's
   // callback mechanism in such a way that it cannot be made private. Invokes
   // the callbacks associated with a given transfer, and removes it from the
@@ -122,10 +114,10 @@
 
  protected:
   // This constructor variant is for use in testing only.
-  UsbDevice();
+  UsbDeviceHandle();
 
-  friend class base::RefCounted<UsbDevice>;
-  virtual ~UsbDevice();
+  friend class base::RefCounted<UsbDeviceHandle>;
+  virtual ~UsbDeviceHandle();
 
  private:
   struct Transfer {
@@ -163,7 +155,7 @@
   base::Lock lock_;
   std::map<PlatformUsbTransferHandle, Transfer> transfers_;
 
-  DISALLOW_COPY_AND_ASSIGN(UsbDevice);
+  DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandle);
 };
 
-#endif  // CHROME_BROWSER_USB_USB_DEVICE_H_
+#endif  // CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_
diff --git a/chrome/browser/usb/usb_interface.h b/chrome/browser/usb/usb_interface.h
index eb57f92..ca01210 100644
--- a/chrome/browser/usb/usb_interface.h
+++ b/chrome/browser/usb/usb_interface.h
@@ -18,7 +18,7 @@
 typedef const libusb_interface* PlatformUsbInterface;
 typedef const libusb_interface_descriptor* PlatformUsbInterfaceDescriptor;
 
-class UsbDevice;
+class UsbDeviceHandle;
 
 enum UsbTransferType {
   USB_TRANSFER_CONTROL = 0,
diff --git a/chrome/browser/usb/usb_service.cc b/chrome/browser/usb/usb_service.cc
index e44c8aa..33c54dd 100644
--- a/chrome/browser/usb/usb_service.cc
+++ b/chrome/browser/usb/usb_service.cc
@@ -10,7 +10,9 @@
 #include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "chrome/browser/usb/usb_device.h"
+#include "base/synchronization/waitable_event.h"
+#include "chrome/browser/usb/usb_device_handle.h"
+#include "third_party/libusb/src/libusb/interrupt.h"
 #include "third_party/libusb/src/libusb/libusb.h"
 
 #if defined(OS_CHROMEOS)
@@ -27,34 +29,38 @@
 class UsbEventHandler : public base::PlatformThread::Delegate {
  public:
   explicit UsbEventHandler(PlatformUsbContext context)
-      : running_(true), context_(context) {
-    base::PlatformThread::CreateNonJoinable(0, this);
+      : running_(true),
+        context_(context),
+        thread_handle_(0),
+        started_event_(false, false) {
+    base::PlatformThread::Create(0, this, &thread_handle_);
+    started_event_.Wait();
   }
 
   virtual ~UsbEventHandler() {}
 
   virtual void ThreadMain() OVERRIDE {
     base::PlatformThread::SetName("UsbEventHandler");
-
-    DLOG(INFO) << "UsbEventHandler started.";
-    while (running_) {
+    VLOG(1) << "UsbEventHandler started.";
+    started_event_.Signal();
+    while (running_)
       libusb_handle_events(context_);
-    }
-    DLOG(INFO) << "UsbEventHandler shutting down.";
-    libusb_exit(context_);
-
-    delete this;
+    VLOG(1) << "UsbEventHandler shutting down.";
   }
 
   void Stop() {
     running_ = false;
+    base::subtle::MemoryBarrier();
+    libusb_interrupt_handle_event(context_);
+    base::PlatformThread::Join(thread_handle_);
   }
 
  private:
-  bool running_;
+  volatile bool running_;
   PlatformUsbContext context_;
-
-  DISALLOW_EVIL_CONSTRUCTORS(UsbEventHandler);
+  base::PlatformThreadHandle thread_handle_;
+  base::WaitableEvent started_event_;
+  DISALLOW_COPY_AND_ASSIGN(UsbEventHandler);
 };
 
 UsbService::UsbService() {
@@ -64,15 +70,17 @@
 
 UsbService::~UsbService() {}
 
-void UsbService::Cleanup() {
+void UsbService::Shutdown() {
   event_handler_->Stop();
-  event_handler_ = NULL;
+  delete event_handler_;
+  libusb_exit(context_);
+  context_ = NULL;
 }
 
 void UsbService::FindDevices(const uint16 vendor_id,
                              const uint16 product_id,
                              int interface_id,
-                             vector<scoped_refptr<UsbDevice> >* devices,
+                             vector<scoped_refptr<UsbDeviceHandle> >* devices,
                              const base::Callback<void()>& callback) {
   DCHECK(event_handler_) << "FindDevices called after event handler stopped.";
 #if defined(OS_CHROMEOS)
@@ -105,7 +113,7 @@
 }
 
 void UsbService::EnumerateDevices(
-    std::vector<scoped_refptr<UsbDevice> >* devices) {
+    std::vector<scoped_refptr<UsbDeviceHandle> >* devices) {
   devices->clear();
 
   DeviceVector enumerated_devices;
@@ -114,17 +122,18 @@
   for (DeviceVector::iterator it = enumerated_devices.begin();
        it != enumerated_devices.end(); ++it) {
     PlatformUsbDevice device = it->device();
-    UsbDevice* const wrapper = LookupOrCreateDevice(device);
+    UsbDeviceHandle* const wrapper = LookupOrCreateDevice(device);
     if (wrapper)
       devices->push_back(wrapper);
   }
 }
 
-void UsbService::FindDevicesImpl(const uint16 vendor_id,
-                                 const uint16 product_id,
-                                 vector<scoped_refptr<UsbDevice> >* devices,
-                                 const base::Callback<void()>& callback,
-                                 bool success) {
+void UsbService::FindDevicesImpl(
+    const uint16 vendor_id,
+    const uint16 product_id,
+    vector<scoped_refptr<UsbDeviceHandle> >* devices,
+    const base::Callback<void()>& callback,
+    bool success) {
   base::ScopedClosureRunner run_callback(callback);
 
   devices->clear();
@@ -142,14 +151,14 @@
        it != enumerated_devices.end(); ++it) {
     PlatformUsbDevice device = it->device();
     if (DeviceMatches(device, vendor_id, product_id)) {
-      UsbDevice* const wrapper = LookupOrCreateDevice(device);
+      UsbDeviceHandle* const wrapper = LookupOrCreateDevice(device);
       if (wrapper)
         devices->push_back(wrapper);
     }
   }
 }
 
-void UsbService::CloseDevice(scoped_refptr<UsbDevice> device) {
+void UsbService::CloseDevice(scoped_refptr<UsbDeviceHandle> device) {
   DCHECK(event_handler_) << "CloseDevice called after event handler stopped.";
 
   PlatformUsbDevice platform_device = libusb_get_device(device->handle());
@@ -206,7 +215,7 @@
   return descriptor.idVendor == vendor_id && descriptor.idProduct == product_id;
 }
 
-UsbDevice* UsbService::LookupOrCreateDevice(PlatformUsbDevice device) {
+UsbDeviceHandle* UsbService::LookupOrCreateDevice(PlatformUsbDevice device) {
   if (!ContainsKey(devices_, device)) {
     libusb_device_handle* handle = NULL;
     if (libusb_open(device, &handle)) {
@@ -214,7 +223,7 @@
       return NULL;
     }
 
-    UsbDevice* wrapper = new UsbDevice(this, handle);
+    UsbDeviceHandle* wrapper = new UsbDeviceHandle(this, handle);
     devices_[device] = wrapper;
   }
   return devices_[device].get();
diff --git a/chrome/browser/usb/usb_service.h b/chrome/browser/usb/usb_service.h
index f2cfd3c..666a26c 100644
--- a/chrome/browser/usb/usb_service.h
+++ b/chrome/browser/usb/usb_service.h
@@ -11,7 +11,7 @@
 
 #include "base/basictypes.h"
 #include "base/threading/platform_thread.h"
-#include "chrome/browser/usb/usb_device.h"
+#include "chrome/browser/usb/usb_device_handle.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "third_party/libusb/src/libusb/libusb.h"
 
@@ -27,9 +27,9 @@
   UsbService();
   virtual ~UsbService();
 
-  // Cleanup must be invoked before the service is destroyed. It interrupts the
+  // Shutdown must be invoked before the service is destroyed. It interrupts the
   // event handling thread and disposes of open devices.
-  void Cleanup();
+  virtual void Shutdown() OVERRIDE;
 
   // Find all of the devices attached to the system that are identified by
   // |vendor_id| and |product_id|, inserting them into |devices|. Clears
@@ -37,16 +37,16 @@
   void FindDevices(const uint16 vendor_id,
                    const uint16 product_id,
                    int interface_id,
-                   std::vector<scoped_refptr<UsbDevice> >* devices,
+                   std::vector<scoped_refptr<UsbDeviceHandle> >* devices,
                    const base::Callback<void()>& callback);
 
   // Find all of the devices attached to the system, inserting them into
   // |devices|. Clears |devices| before use.
-  void EnumerateDevices(std::vector<scoped_refptr<UsbDevice> >* devices);
+  void EnumerateDevices(std::vector<scoped_refptr<UsbDeviceHandle> >* devices);
 
   // This function should not be called by normal code. It is invoked by a
   // UsbDevice's Close function and disposes of the associated platform handle.
-  void CloseDevice(scoped_refptr<UsbDevice> device);
+  void CloseDevice(scoped_refptr<UsbDeviceHandle> device);
 
  private:
   // RefCountedPlatformUsbDevice takes care of managing the underlying reference
@@ -78,7 +78,7 @@
   // FindDevices.
   void FindDevicesImpl(const uint16 vendor_id,
                        const uint16 product_id,
-                       std::vector<scoped_refptr<UsbDevice> >* devices,
+                       std::vector<scoped_refptr<UsbDeviceHandle> >* devices,
                        const base::Callback<void()>& callback,
                        bool success);
 
@@ -88,7 +88,7 @@
   // If a UsbDevice wrapper corresponding to |device| has already been created,
   // returns it. Otherwise, opens the device, creates a wrapper, and associates
   // the wrapper with the device internally.
-  UsbDevice* LookupOrCreateDevice(PlatformUsbDevice device);
+  UsbDeviceHandle* LookupOrCreateDevice(PlatformUsbDevice device);
 
   PlatformUsbContext context_;
   UsbEventHandler* event_handler_;
@@ -96,7 +96,8 @@
   // The devices_ map contains scoped_refptrs to all open devices, indicated by
   // their vendor and product id. This allows for reusing an open device without
   // creating another platform handle for it.
-  typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDevice> > DeviceMap;
+  typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDeviceHandle> >
+      DeviceMap;
   DeviceMap devices_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbService);
diff --git a/chrome/browser/usb/usb_service_unittest.cc b/chrome/browser/usb/usb_service_unittest.cc
new file mode 100644
index 0000000..b0eeb9b
--- /dev/null
+++ b/chrome/browser/usb/usb_service_unittest.cc
@@ -0,0 +1,34 @@
+// 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/usb/usb_service.h"
+
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+typedef testing::Test UsbServiceTest;
+
+#if defined(OS_LINUX)
+// Linux trybot does not support usb.
+#define MAYBE_GracefulShutdown DISABLED_GracefulShutdown
+#elif defined(OS_ANDROID)
+// Android build does not include usb support.
+#define MAYBE_GracefulShutdown DISABLED_GracefulShutdown
+#else
+#define MAYBE_GracefulShutdown GracefulShutdown
+#endif
+
+TEST_F(UsbServiceTest, MAYBE_GracefulShutdown) {
+  base::TimeTicks start = base::TimeTicks::Now();
+  scoped_ptr<UsbService> service(new UsbService());
+  service->Shutdown();
+  base::TimeDelta elapse = base::TimeTicks::Now() - start;
+  if (elapse > base::TimeDelta::FromSeconds(2)) {
+    FAIL();
+  }
+}
+
+}  // namespace
diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm
index ad056e7..a4957b8 100644
--- a/chrome/browser/web_applications/web_app_mac_unittest.mm
+++ b/chrome/browser/web_applications/web_app_mac_unittest.mm
@@ -54,49 +54,67 @@
   info.extension_path = base::FilePath("/fake/extension/path");
   info.title = ASCIIToUTF16("Shortcut Title");
   info.url = GURL("http://example.com/");
-  info.profile_path = base::FilePath("Profile 1");
+  info.profile_path = base::FilePath("user_data_dir").Append("Profile 1");
   info.profile_name = "profile name";
   return info;
 }
 
+class WebAppShortcutCreatorTest : public testing::Test {
+ protected:
+  WebAppShortcutCreatorTest() {}
+
+  virtual void SetUp() {
+    EXPECT_TRUE(app_data_path_temp_dir_.CreateUniqueTempDir());
+    EXPECT_TRUE(destination_path_temp_dir_.CreateUniqueTempDir());
+    app_data_path_ = app_data_path_temp_dir_.path();
+    destination_path_ = destination_path_temp_dir_.path();
+
+    info_ = GetShortcutInfo();
+    shim_base_name_ = base::FilePath(
+        info_.profile_path.BaseName().value() +
+        " " + info_.extension_id + ".app");
+    internal_shim_path_ = app_data_path_.Append(shim_base_name_);
+    shim_path_ = destination_path_.Append(shim_base_name_);
+  }
+
+  base::ScopedTempDir app_data_path_temp_dir_;
+  base::ScopedTempDir destination_path_temp_dir_;
+  base::FilePath app_data_path_;
+  base::FilePath destination_path_;
+
+  ShellIntegration::ShortcutInfo info_;
+  base::FilePath shim_base_name_;
+  base::FilePath internal_shim_path_;
+  base::FilePath shim_path_;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebAppShortcutCreatorTest);
+};
+
+
 }  // namespace
 
 namespace web_app {
 
-TEST(WebAppShortcutCreatorTest, CreateShortcuts) {
-  base::ScopedTempDir temp_app_data_path;
-  EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dst_dir;
-  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
-
-  ShellIntegration::ShortcutInfo info = GetShortcutInfo();
-
-  base::FilePath app_name(
-      info.profile_path.value() + " " + info.extension_id + ".app");
-  base::FilePath app_in_app_data_path_path =
-      temp_app_data_path.path().Append(app_name);
-  base::FilePath dst_folder = temp_dst_dir.path();
-  base::FilePath dst_path = dst_folder.Append(app_name);
-
-  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(
-      temp_app_data_path.path(), info);
+TEST_F(WebAppShortcutCreatorTest, CreateShortcuts) {
+  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_path_, info_);
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
-      .WillRepeatedly(Return(dst_folder));
+      .WillRepeatedly(Return(destination_path_));
   EXPECT_CALL(shortcut_creator, RevealAppShimInFinder());
 
   EXPECT_TRUE(shortcut_creator.CreateShortcuts());
-  EXPECT_TRUE(base::PathExists(app_in_app_data_path_path));
-  EXPECT_TRUE(base::PathExists(dst_path));
-  EXPECT_EQ(dst_path.BaseName(), shortcut_creator.GetShortcutName());
+  EXPECT_TRUE(base::PathExists(shim_path_));
+  EXPECT_TRUE(base::PathExists(destination_path_));
+  EXPECT_EQ(shim_base_name_, shortcut_creator.GetShortcutName());
 
-  base::FilePath plist_path = dst_path.Append("Contents").Append("Info.plist");
+  base::FilePath plist_path =
+      shim_path_.Append("Contents").Append("Info.plist");
   NSDictionary* plist = [NSDictionary dictionaryWithContentsOfFile:
       base::mac::FilePathToNSString(plist_path)];
-  EXPECT_NSEQ(base::SysUTF8ToNSString(info.extension_id),
+  EXPECT_NSEQ(base::SysUTF8ToNSString(info_.extension_id),
               [plist objectForKey:app_mode::kCrAppModeShortcutIDKey]);
-  EXPECT_NSEQ(base::SysUTF16ToNSString(info.title),
+  EXPECT_NSEQ(base::SysUTF16ToNSString(info_.title),
               [plist objectForKey:app_mode::kCrAppModeShortcutNameKey]);
-  EXPECT_NSEQ(base::SysUTF8ToNSString(info.url.spec()),
+  EXPECT_NSEQ(base::SysUTF8ToNSString(info_.url.spec()),
               [plist objectForKey:app_mode::kCrAppModeShortcutURLKey]);
 
   // Make sure all values in the plist are actually filled in.
@@ -110,137 +128,90 @@
   }
 }
 
-TEST(WebAppShortcutCreatorTest, UpdateShortcuts) {
-  base::ScopedTempDir temp_app_data_path;
-  EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dst_dir;
-  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dst_dir_other;
-  EXPECT_TRUE(temp_dst_dir_other.CreateUniqueTempDir());
+TEST_F(WebAppShortcutCreatorTest, UpdateShortcuts) {
+  base::ScopedTempDir other_folder_temp_dir;
+  EXPECT_TRUE(other_folder_temp_dir.CreateUniqueTempDir());
+  base::FilePath other_folder = other_folder_temp_dir.path();
+  base::FilePath other_shim_path = other_folder.Append(shim_base_name_);
 
-  ShellIntegration::ShortcutInfo info = GetShortcutInfo();
-
-  base::FilePath app_name(
-      info.profile_path.value() + " " + info.extension_id + ".app");
-  base::FilePath app_in_app_data_path_path =
-      temp_app_data_path.path().Append(app_name);
-  base::FilePath dst_folder = temp_dst_dir.path();
-  base::FilePath other_folder = temp_dst_dir_other.path();
-
-  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(
-      temp_app_data_path.path(), info);
+  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_path_, info_);
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
-      .WillRepeatedly(Return(dst_folder));
+      .WillRepeatedly(Return(destination_path_));
 
   std::string expected_bundle_id = kFakeChromeBundleId;
-  expected_bundle_id += ".app.Profile-1-" + info.extension_id;
+  expected_bundle_id += ".app.Profile-1-" + info_.extension_id;
   EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id))
-      .WillOnce(Return(other_folder.Append(app_name)));
+      .WillOnce(Return(other_shim_path));
 
-  shortcut_creator.BuildShortcut(other_folder.Append(app_name));
+  EXPECT_TRUE(shortcut_creator.BuildShortcut(other_shim_path));
 
-  EXPECT_TRUE(base::DeleteFile(
-      other_folder.Append(app_name).Append("Contents"), true));
+  EXPECT_TRUE(base::DeleteFile(other_shim_path.Append("Contents"), true));
 
   EXPECT_TRUE(shortcut_creator.UpdateShortcuts());
-  EXPECT_FALSE(base::PathExists(dst_folder.Append(app_name)));
-  EXPECT_TRUE(base::PathExists(
-      other_folder.Append(app_name).Append("Contents")));
+  EXPECT_FALSE(base::PathExists(shim_path_));
+  EXPECT_TRUE(base::PathExists(other_shim_path.Append("Contents")));
 
   // Also test case where GetAppBundleById fails.
   EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id))
       .WillOnce(Return(base::FilePath()));
 
-  shortcut_creator.BuildShortcut(other_folder.Append(app_name));
+  EXPECT_TRUE(shortcut_creator.BuildShortcut(other_shim_path));
 
-  EXPECT_TRUE(base::DeleteFile(
-      other_folder.Append(app_name).Append("Contents"), true));
+  EXPECT_TRUE(base::DeleteFile(other_shim_path.Append("Contents"), true));
 
   EXPECT_FALSE(shortcut_creator.UpdateShortcuts());
-  EXPECT_FALSE(base::PathExists(dst_folder.Append(app_name)));
-  EXPECT_FALSE(base::PathExists(
-      other_folder.Append(app_name).Append("Contents")));
+  EXPECT_FALSE(base::PathExists(shim_path_));
+  EXPECT_FALSE(base::PathExists(other_shim_path.Append("Contents")));
 }
 
-TEST(WebAppShortcutCreatorTest, CreateAppListShortcut) {
-  base::ScopedTempDir temp_dst_dir;
-  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
-
-  ShellIntegration::ShortcutInfo info = GetShortcutInfo();
-
-  base::FilePath dst_folder = temp_dst_dir.path();
-
+TEST_F(WebAppShortcutCreatorTest, CreateAppListShortcut) {
   // With an empty |profile_name|, the shortcut path should not have the profile
   // directory prepended to the extension id on the app bundle name.
-  info.profile_name.clear();
-  base::FilePath dst_path = dst_folder.Append(info.extension_id + ".app");
+  info_.profile_name.clear();
+  base::FilePath dst_path =
+      destination_path_.Append(info_.extension_id + ".app");
 
-  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(base::FilePath(), info);
+  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(base::FilePath(), info_);
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
-      .WillRepeatedly(Return(dst_folder));
+      .WillRepeatedly(Return(destination_path_));
   EXPECT_EQ(dst_path.BaseName(), shortcut_creator.GetShortcutName());
 }
 
-TEST(WebAppShortcutCreatorTest, RunShortcut) {
-  base::ScopedTempDir temp_app_data_path;
-  EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dst_dir;
-  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
-
-  ShellIntegration::ShortcutInfo info = GetShortcutInfo();
-
-  base::FilePath dst_folder = temp_dst_dir.path();
-  base::FilePath dst_path = dst_folder.Append(
-      info.profile_path.value() + " " + info.extension_id + ".app");
-
-  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(
-      temp_app_data_path.path(), info);
+TEST_F(WebAppShortcutCreatorTest, RunShortcut) {
+  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_path_, info_);
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
-      .WillRepeatedly(Return(dst_folder));
+      .WillRepeatedly(Return(destination_path_));
   EXPECT_CALL(shortcut_creator, RevealAppShimInFinder());
 
   EXPECT_TRUE(shortcut_creator.CreateShortcuts());
-  EXPECT_TRUE(base::PathExists(dst_path));
+  EXPECT_TRUE(base::PathExists(shim_path_));
 
   ssize_t status = getxattr(
-      dst_path.value().c_str(), "com.apple.quarantine", NULL, 0, 0, 0);
+      shim_path_.value().c_str(), "com.apple.quarantine", NULL, 0, 0, 0);
   EXPECT_EQ(-1, status);
   EXPECT_EQ(ENOATTR, errno);
 }
 
-TEST(WebAppShortcutCreatorTest, CreateFailure) {
-  base::ScopedTempDir temp_app_data_path;
-  EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dst_dir;
-  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
-
+TEST_F(WebAppShortcutCreatorTest, CreateFailure) {
   base::FilePath non_existent_path =
-      temp_dst_dir.path().Append("not-existent").Append("name.app");
+      destination_path_.Append("not-existent").Append("name.app");
 
-  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(
-      temp_app_data_path.path(), GetShortcutInfo());
+  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_path_, info_);
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
       .WillRepeatedly(Return(non_existent_path));
   EXPECT_FALSE(shortcut_creator.CreateShortcuts());
 }
 
-TEST(WebAppShortcutCreatorTest, UpdateIcon) {
-  base::ScopedTempDir temp_app_data_path;
-  EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dst_dir;
-  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
-  base::FilePath dst_path = temp_dst_dir.path();
-
-  ShellIntegration::ShortcutInfo info = GetShortcutInfo();
+TEST_F(WebAppShortcutCreatorTest, UpdateIcon) {
   gfx::Image product_logo =
       ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
           IDR_PRODUCT_LOGO_32);
-  info.favicon.Add(product_logo);
-  WebAppShortcutCreatorMock shortcut_creator(temp_app_data_path.path(), info);
+  info_.favicon.Add(product_logo);
+  WebAppShortcutCreatorMock shortcut_creator(app_data_path_, info_);
 
-  ASSERT_TRUE(shortcut_creator.UpdateIcon(dst_path));
+  ASSERT_TRUE(shortcut_creator.UpdateIcon(shim_path_));
   base::FilePath icon_path =
-      dst_path.Append("Contents").Append("Resources").Append("app.icns");
+      shim_path_.Append("Contents").Append("Resources").Append("app.icns");
 
   base::scoped_nsobject<NSImage> image([[NSImage alloc]
       initWithContentsOfFile:base::mac::FilePathToNSString(icon_path)]);