diff --git a/DEPS b/DEPS
index ffebe5e..75cfadb 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'c1eee0356bdae023dd05c15e27f02c5db0b17e49',
+  'v8_revision': '4bfecb6a9f37d83262c493545f43112266698e9a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/chrome/browser/history/web_history_service_factory.cc b/chrome/browser/history/web_history_service_factory.cc
index d0149fddb..a63cedc 100644
--- a/chrome/browser/history/web_history_service_factory.cc
+++ b/chrome/browser/history/web_history_service_factory.cc
@@ -20,9 +20,8 @@
 bool IsHistorySyncEnabled(Profile* profile) {
   browser_sync::ProfileSyncService* sync =
       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
-  return sync &&
-      sync->IsSyncActive() &&
-      sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES);
+  return sync && sync->IsSyncActive() && !sync->IsLocalSyncEnabled() &&
+         sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES);
 }
 
 }  // namespace
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc
index 9138af4c..1f19e9d6 100644
--- a/chrome/browser/prefs/chrome_command_line_pref_store.cc
+++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc
@@ -83,7 +83,7 @@
 #endif
         {switches::kUnsafePacUrl, prefs::kPacHttpsUrlStrippingEnabled, false},
         {switches::kEnableLocalSyncBackend,
-         syncer::prefs::kEnableLocalSyncBackend, false},
+         syncer::prefs::kEnableLocalSyncBackend, true},
 };
 
 const CommandLinePrefStore::SwitchToPreferenceMapEntry
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index ce61b07..f9c8481 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -74,6 +74,11 @@
                  latency, base::TimeTicks::Now()));
 }
 
+#if defined(OS_WIN)
+static const base::FilePath::CharType kLoopbackServerBackendFilename[] =
+    FILE_PATH_LITERAL("profile.pb");
+#endif
+
 }  // anonymous namespace
 
 // static
@@ -142,33 +147,68 @@
 
   Profile* profile = Profile::FromBrowserContext(context);
 
-  SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile);
+  init_params.network_time_update_callback = base::Bind(&UpdateNetworkTime);
+  init_params.base_directory = profile->GetPath();
+  init_params.url_request_context = profile->GetRequestContext();
+  init_params.debug_identifier = profile->GetDebugName();
+  init_params.channel = chrome::GetChannel();
+  init_params.blocking_pool = content::BrowserThread::GetBlockingPool();
 
-  // Always create the GCMProfileService instance such that we can listen to
-  // the profile notifications and purge the GCM store when the profile is
-  // being signed out.
-  gcm::GCMProfileServiceFactory::GetForProfile(profile);
+  bool local_sync_backend_enabled = false;
 
-  // TODO(atwilson): Change AboutSigninInternalsFactory to load on startup
-  // once http://crbug.com/171406 has been fixed.
-  AboutSigninInternalsFactory::GetForProfile(profile);
+// Since the local sync backend is currently only supported on Windows don't
+// even check the pref on other os-es.
+#if defined(OS_WIN)
+  syncer::SyncPrefs prefs(profile->GetPrefs());
+  local_sync_backend_enabled = prefs.IsLocalSyncEnabled();
+  if (local_sync_backend_enabled) {
+    // This code as it is now will assume the same profile order is present on
+    // all machines, which is not a given. It is to be defined if only the
+    // Default profile should get this treatment or all profile as is the case
+    // now. The solution for now will be to assume profiles are created in the
+    // same order on all machines and in the future decide if only the Default
+    // one should be considered roamed.
+    init_params.local_sync_backend_folder = prefs.GetLocalSyncBackendDir();
+    init_params.local_sync_backend_folder =
+        init_params.local_sync_backend_folder.Append(
+            init_params.base_directory.BaseName());
+    init_params.local_sync_backend_folder =
+        init_params.local_sync_backend_folder.Append(
+            kLoopbackServerBackendFilename);
 
-  init_params.signin_wrapper =
-      base::MakeUnique<SupervisedUserSigninManagerWrapper>(profile, signin);
-  init_params.oauth2_token_service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
-  init_params.gaia_cookie_manager_service =
-      GaiaCookieManagerServiceFactory::GetForProfile(profile);
+    init_params.start_behavior = ProfileSyncService::AUTO_START;
+  }
+#endif  // defined(OS_WIN)
 
-  // TODO(tim): Currently, AUTO/MANUAL settings refer to the *first* time sync
-  // is set up and *not* a browser restart for a manual-start platform (where
-  // sync has already been set up, and should be able to start without user
-  // intervention). We can get rid of the browser_default eventually, but
-  // need to take care that ProfileSyncService doesn't get tripped up between
-  // those two cases. Bug 88109.
-  init_params.start_behavior = browser_defaults::kSyncAutoStarts
-                                   ? ProfileSyncService::AUTO_START
-                                   : ProfileSyncService::MANUAL_START;
+  if (!local_sync_backend_enabled) {
+    SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile);
+
+    // Always create the GCMProfileService instance such that we can listen to
+    // the profile notifications and purge the GCM store when the profile is
+    // being signed out.
+    gcm::GCMProfileServiceFactory::GetForProfile(profile);
+
+    // TODO(atwilson): Change AboutSigninInternalsFactory to load on startup
+    // once http://crbug.com/171406 has been fixed.
+    AboutSigninInternalsFactory::GetForProfile(profile);
+
+    init_params.signin_wrapper =
+        base::MakeUnique<SupervisedUserSigninManagerWrapper>(profile, signin);
+    init_params.oauth2_token_service =
+        ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+    init_params.gaia_cookie_manager_service =
+        GaiaCookieManagerServiceFactory::GetForProfile(profile);
+
+    // TODO(tim): Currently, AUTO/MANUAL settings refer to the *first* time sync
+    // is set up and *not* a browser restart for a manual-start platform (where
+    // sync has already been set up, and should be able to start without user
+    // intervention). We can get rid of the browser_default eventually, but
+    // need to take care that ProfileSyncService doesn't get tripped up between
+    // those two cases. Bug 88109.
+    init_params.start_behavior = browser_defaults::kSyncAutoStarts
+                                     ? ProfileSyncService::AUTO_START
+                                     : ProfileSyncService::MANUAL_START;
+  }
 
   if (!client_factory_) {
     init_params.sync_client =
@@ -177,13 +217,6 @@
     init_params.sync_client = client_factory_->Run(profile);
   }
 
-  init_params.network_time_update_callback = base::Bind(&UpdateNetworkTime);
-  init_params.base_directory = profile->GetPath();
-  init_params.url_request_context = profile->GetRequestContext();
-  init_params.debug_identifier = profile->GetDebugName();
-  init_params.channel = chrome::GetChannel();
-  init_params.blocking_pool = content::BrowserThread::GetBlockingPool();
-
   auto pss = base::MakeUnique<ProfileSyncService>(std::move(init_params));
 
   // Will also initialize the sync client.
diff --git a/chrome/browser/ui/sync/sync_promo_ui.cc b/chrome/browser/ui/sync/sync_promo_ui.cc
index 3fa574b6..f84177a7 100644
--- a/chrome/browser/ui/sync/sync_promo_ui.cc
+++ b/chrome/browser/ui/sync/sync_promo_ui.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_promo_util.h"
+#include "components/sync/base/sync_prefs.h"
 
 bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) {
   // Don't show sync promo if the sign in promo should not be shown.
@@ -13,8 +14,9 @@
     return false;
   }
 
-  // Don't show if sync is not allowed to start.
-  if (!profile->IsSyncAllowed())
+  syncer::SyncPrefs prefs(profile->GetPrefs());
+  // Don't show if sync is not allowed to start or is running in local mode.
+  if (!profile->IsSyncAllowed() || prefs.IsLocalSyncEnabled())
     return false;
 
   return true;
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index ca5c58f..c17718f 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -198,6 +198,7 @@
       engine_initialized_(false),
       sync_disabled_by_admin_(false),
       is_auth_in_progress_(false),
+      local_sync_backend_folder_(init_params.local_sync_backend_folder),
       unrecoverable_error_reason_(ERROR_REASON_UNSET),
       expect_sync_configuration_aborted_(false),
       encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()),
@@ -241,7 +242,8 @@
 
 bool ProfileSyncService::CanSyncStart() const {
   DCHECK(thread_checker_.CalledOnValidThread());
-  return IsSyncAllowed() && IsSyncRequested() && IsSignedIn();
+  return (IsSyncAllowed() && IsSyncRequested() &&
+          (IsLocalSyncEnabled() || IsSignedIn()));
 }
 
 void ProfileSyncService::Initialize() {
@@ -308,7 +310,7 @@
   sync_prefs_.AddSyncPrefObserver(this);
 
   SyncInitialState sync_state = CAN_START;
-  if (!IsSignedIn()) {
+  if (!IsLocalSyncEnabled() && !IsSignedIn()) {
     sync_state = NOT_SIGNED_IN;
   } else if (IsManaged()) {
     sync_state = IS_MANAGED;
@@ -335,11 +337,13 @@
     return;
   }
 
-  RegisterAuthNotifications();
+  if (!IsLocalSyncEnabled()) {
+    RegisterAuthNotifications();
 
-  if (!IsSignedIn()) {
-    // Clean up in case of previous crash during signout.
-    StopImpl(CLEAR_DATA);
+    if (!IsSignedIn()) {
+      // Clean up in case of previous crash during signout.
+      StopImpl(CLEAR_DATA);
+    }
   }
 
 #if defined(OS_CHROMEOS)
@@ -362,8 +366,8 @@
                  sync_enabled_weak_factory_.GetWeakPtr()));
   startup_controller_->Reset(GetRegisteredDataTypes());
 
-  // Auto-start means means the first time the profile starts up, sync should
-  // start up immediately.
+  // Auto-start means the first time the profile starts up, sync should start up
+  // immediately.
   if (start_behavior_ == AUTO_START && IsSyncRequested() &&
       !IsFirstSetupComplete()) {
     startup_controller_->TryStartImmediately();
@@ -399,7 +403,8 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   if (signin())
     signin()->RemoveObserver(this);
-  oauth2_token_service_->RemoveObserver(this);
+  if (oauth2_token_service_)
+    oauth2_token_service_->RemoveObserver(this);
 }
 
 void ProfileSyncService::RegisterDataTypeController(
@@ -475,6 +480,11 @@
 
 SyncCredentials ProfileSyncService::GetCredentials() {
   SyncCredentials credentials;
+
+  // No credentials exist or are needed for the local sync backend.
+  if (IsLocalSyncEnabled())
+    return credentials;
+
   credentials.account_id = signin_->GetAccountIdToUse();
   DCHECK(!credentials.account_id.empty());
   credentials.email = signin_->GetEffectiveUsername();
@@ -949,10 +959,15 @@
   sync_js_controller_.AttachJsBackend(js_backend);
   debug_info_listener_ = debug_info_listener;
 
-  SigninClient* signin_client = signin_->GetOriginal()->signin_client();
-  DCHECK(signin_client);
-  std::string signin_scoped_device_id =
-      signin_client->GetSigninScopedDeviceId();
+  std::string signin_scoped_device_id;
+  if (IsLocalSyncEnabled()) {
+    signin_scoped_device_id = "local_device";
+  } else {
+    SigninClient* signin_client = signin_->GetOriginal()->signin_client();
+    DCHECK(signin_client);
+    std::string signin_scoped_device_id =
+        signin_client->GetSigninScopedDeviceId();
+  }
 
   // Initialize local device info.
   local_device_->Initialize(cache_guid, signin_scoped_device_id,
@@ -1002,6 +1017,10 @@
   }
 
   NotifyObservers();
+
+  // Nobody will call us to start if no sign in is going to happen.
+  if (IsLocalSyncEnabled())
+    RequestStart();
 }
 
 void ProfileSyncService::OnSyncCycleCompleted() {
@@ -1530,6 +1549,11 @@
          data_type_manager_->state() != DataTypeManager::STOPPED;
 }
 
+bool ProfileSyncService::IsLocalSyncEnabled() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return sync_prefs_.IsLocalSyncEnabled();
+}
+
 void ProfileSyncService::TriggerRefresh(const syncer::ModelTypeSet& types) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (engine_initialized_)
@@ -1542,6 +1566,8 @@
 }
 
 bool ProfileSyncService::CanEngineStart() const {
+  if (IsLocalSyncEnabled())
+    return true;
   return CanSyncStart() && oauth2_token_service_ &&
          oauth2_token_service_->RefreshTokenIsAvailable(
              signin_->GetAccountIdToUse());
@@ -2498,7 +2524,7 @@
 }
 
 void ProfileSyncService::UpdateFirstSyncTimePref() {
-  if (!IsSignedIn()) {
+  if (!IsLocalSyncEnabled() && !IsSignedIn()) {
     sync_prefs_.ClearFirstSyncTime();
   } else if (sync_prefs_.GetFirstSyncTime().is_null()) {
     // Set if not set before and it's syncing now.
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 92356b51..8aaf07b 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -245,6 +245,7 @@
     std::string debug_identifier;
     version_info::Channel channel = version_info::Channel::UNKNOWN;
     base::SequencedWorkerPool* blocking_pool = nullptr;
+    base::FilePath local_sync_backend_folder;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(InitParams);
@@ -262,6 +263,7 @@
   bool IsFirstSetupComplete() const override;
   bool IsSyncAllowed() const override;
   bool IsSyncActive() const override;
+  bool IsLocalSyncEnabled() const override;
   void TriggerRefresh(const syncer::ModelTypeSet& types) override;
   void OnDataTypeRequestsSyncStartup(syncer::ModelType type) override;
   bool CanSyncStart() const override;
@@ -814,6 +816,9 @@
   // engine to refresh its credentials.
   bool is_auth_in_progress_;
 
+  // The location where the local sync backend stores its data.
+  base::FilePath local_sync_backend_folder_;
+
   // Information describing an unrecoverable error.
   UnrecoverableErrorReason unrecoverable_error_reason_;
   std::string unrecoverable_error_message_;
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc
index abe8f86..dba0ea9 100644
--- a/components/browser_sync/profile_sync_service_unittest.cc
+++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -211,14 +211,24 @@
         base::MakeUnique<syncer::FakeDataTypeController>(syncer::BOOKMARKS));
   }
 
-#if defined(OS_WIN) || defined(OS_MACOSX) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
-  void CreateServiceWithoutSignIn() {
-    CreateService(ProfileSyncService::AUTO_START);
-    signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST,
-                              signin_metrics::SignoutDelete::IGNORE_METRIC);
+  void CreateServiceWithLocalSyncBackend() {
+    component_factory_ = profile_sync_service_bundle_.component_factory();
+    ProfileSyncServiceBundle::SyncClientBuilder builder(
+        &profile_sync_service_bundle_);
+    ProfileSyncService::InitParams init_params =
+        profile_sync_service_bundle_.CreateBasicInitParams(
+            ProfileSyncService::AUTO_START, builder.Build());
+
+    prefs()->SetBoolean(syncer::prefs::kEnableLocalSyncBackend, true);
+    init_params.local_sync_backend_folder =
+        base::FilePath(FILE_PATH_LITERAL("dummyPath"));
+    init_params.oauth2_token_service = nullptr;
+    init_params.gaia_cookie_manager_service = nullptr;
+
+    service_ = base::MakeUnique<ProfileSyncService>(std::move(init_params));
+    service_->RegisterDataTypeController(
+        base::MakeUnique<syncer::FakeDataTypeController>(syncer::BOOKMARKS));
   }
-#endif
 
   void ShutdownAndDeleteService() {
     if (service_)
@@ -372,6 +382,19 @@
   EXPECT_TRUE(service()->IsSyncActive());
 }
 
+// Verify a successful initialization.
+TEST_F(ProfileSyncServiceTest, SuccessfulLocalBackendInitialization) {
+  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+                          new base::FundamentalValue(false));
+  IssueTestTokens();
+  CreateServiceWithLocalSyncBackend();
+  ExpectDataTypeManagerCreation(1, GetDefaultConfigureCalledCallback());
+  ExpectSyncEngineCreation(1);
+  InitializeForNthSync();
+  EXPECT_FALSE(service()->IsManaged());
+  EXPECT_TRUE(service()->IsSyncActive());
+}
+
 // Verify that an initialization where first setup is not complete does not
 // start up the backend.
 TEST_F(ProfileSyncServiceTest, NeedsConfirmation) {
diff --git a/components/browsing_data/core/history_notice_utils_unittest.cc b/components/browsing_data/core/history_notice_utils_unittest.cc
index 6c4363c0..2701c85 100644
--- a/components/browsing_data/core/history_notice_utils_unittest.cc
+++ b/components/browsing_data/core/history_notice_utils_unittest.cc
@@ -28,9 +28,9 @@
 class TestSyncService : public syncer::FakeSyncService {
  public:
   // Getters (FakeSyncService implementation). ---------------------------------
-  bool IsSyncActive() const override {
-   return sync_active_;
-  }
+  bool IsSyncActive() const override { return sync_active_; }
+
+  bool IsLocalSyncEnabled() const override { return false; }
 
   syncer::ModelTypeSet GetActiveDataTypes() const override {
     return active_data_types_;
diff --git a/components/dom_distiller/ios/BUILD.gn b/components/dom_distiller/ios/BUILD.gn
index fe60646..241042b3 100644
--- a/components/dom_distiller/ios/BUILD.gn
+++ b/components/dom_distiller/ios/BUILD.gn
@@ -8,13 +8,14 @@
     "distiller_page_factory_ios.mm",
     "distiller_page_ios.h",
     "distiller_page_ios.mm",
+    "favicon_web_state_dispatcher.h",
   ]
 
   deps = [
     "//base",
     "//components/dom_distiller/core",
     "//components/dom_distiller/core/proto",
-    "//ios/public/provider/web",
+    "//components/favicon/ios",
     "//ios/web",
     "//url",
   ]
diff --git a/components/dom_distiller/ios/DEPS b/components/dom_distiller/ios/DEPS
index 450c6e9..ea0729b 100644
--- a/components/dom_distiller/ios/DEPS
+++ b/components/dom_distiller/ios/DEPS
@@ -1,4 +1,4 @@
 include_rules = [
-  "+ios/public/provider/web",
+  "+components/favicon/ios",
   "+ios/web/public",
 ]
diff --git a/components/dom_distiller/ios/distiller_page_factory_ios.h b/components/dom_distiller/ios/distiller_page_factory_ios.h
index f3fb0e8..1f2250e 100644
--- a/components/dom_distiller/ios/distiller_page_factory_ios.h
+++ b/components/dom_distiller/ios/distiller_page_factory_ios.h
@@ -9,18 +9,18 @@
 
 #include "components/dom_distiller/core/distiller_page.h"
 
-namespace web {
-class BrowserState;
-}
-
 namespace dom_distiller {
 
+class FaviconWebStateDispatcher;
+
 // DistillerPageFactoryIOS is an iOS-specific implementation of the
 // DistillerPageFactory interface allowing the creation of DistillerPage
 // instances.
 class DistillerPageFactoryIOS : public DistillerPageFactory {
  public:
-  DistillerPageFactoryIOS(web::BrowserState* browser_state);
+  explicit DistillerPageFactoryIOS(
+      std::unique_ptr<FaviconWebStateDispatcher> web_state_dispatcher);
+  ~DistillerPageFactoryIOS() override;
 
   // Implementation of DistillerPageFactory:
   std::unique_ptr<DistillerPage> CreateDistillerPage(
@@ -29,7 +29,9 @@
       std::unique_ptr<SourcePageHandle> handle) const override;
 
  private:
-  web::BrowserState* browser_state_;
+  std::unique_ptr<FaviconWebStateDispatcher> web_state_dispatcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(DistillerPageFactoryIOS);
 };
 
 }  // namespace dom_distiller
diff --git a/components/dom_distiller/ios/distiller_page_factory_ios.mm b/components/dom_distiller/ios/distiller_page_factory_ios.mm
index ad355f9..1e3f7f4 100644
--- a/components/dom_distiller/ios/distiller_page_factory_ios.mm
+++ b/components/dom_distiller/ios/distiller_page_factory_ios.mm
@@ -6,24 +6,26 @@
 
 #include "base/memory/ptr_util.h"
 #include "components/dom_distiller/ios/distiller_page_ios.h"
+#include "components/dom_distiller/ios/favicon_web_state_dispatcher.h"
 #include "ios/web/public/browser_state.h"
 
 namespace dom_distiller {
 
 DistillerPageFactoryIOS::DistillerPageFactoryIOS(
-    web::BrowserState* browser_state)
-    : browser_state_(browser_state) {
-}
+    std::unique_ptr<FaviconWebStateDispatcher> web_state_dispatcher)
+    : web_state_dispatcher_(std::move(web_state_dispatcher)) {}
+
+DistillerPageFactoryIOS::~DistillerPageFactoryIOS() {}
 
 std::unique_ptr<DistillerPage> DistillerPageFactoryIOS::CreateDistillerPage(
     const gfx::Size& view_size) const {
-  return base::WrapUnique<DistillerPage>(new DistillerPageIOS(browser_state_));
+  return base::MakeUnique<DistillerPageIOS>(web_state_dispatcher_.get());
 }
 
 std::unique_ptr<DistillerPage>
 DistillerPageFactoryIOS::CreateDistillerPageWithHandle(
     std::unique_ptr<SourcePageHandle> handle) const {
-  return base::WrapUnique<DistillerPage>(new DistillerPageIOS(browser_state_));
+  return base::MakeUnique<DistillerPageIOS>(web_state_dispatcher_.get());
 }
 
 }  // namespace dom_distiller
diff --git a/components/dom_distiller/ios/distiller_page_ios.h b/components/dom_distiller/ios/distiller_page_ios.h
index 9c79985..ddd55f3 100644
--- a/components/dom_distiller/ios/distiller_page_ios.h
+++ b/components/dom_distiller/ios/distiller_page_ios.h
@@ -10,17 +10,10 @@
 
 #include "base/memory/weak_ptr.h"
 #include "components/dom_distiller/core/distiller_page.h"
+#include "components/dom_distiller/ios/favicon_web_state_dispatcher.h"
 #include "ios/web/public/web_state/web_state_observer.h"
 #include "url/gurl.h"
 
-namespace ios {
-class WebControllerProvider;
-}
-
-namespace web {
-class BrowserState;
-}
-
 namespace dom_distiller {
 
 class DistillerWebStateObserver;
@@ -29,7 +22,7 @@
 // content.
 class DistillerPageIOS : public DistillerPage {
  public:
-  explicit DistillerPageIOS(web::BrowserState* browser_state);
+  explicit DistillerPageIOS(FaviconWebStateDispatcher* web_state_dispatcher);
   ~DistillerPageIOS() override;
 
  protected:
@@ -48,10 +41,10 @@
   // Converts result of WKWebView script evaluation to base::Value
   std::unique_ptr<base::Value> ValueResultFromScriptResult(id wk_result);
 
-  web::BrowserState* browser_state_;
   GURL url_;
   std::string script_;
-  std::unique_ptr<ios::WebControllerProvider> provider_;
+  web::WebState* web_state_;
+  FaviconWebStateDispatcher* web_state_dispatcher_;
   std::unique_ptr<DistillerWebStateObserver> web_state_observer_;
   base::WeakPtrFactory<DistillerPageIOS> weak_ptr_factory_;
 };
diff --git a/components/dom_distiller/ios/distiller_page_ios.mm b/components/dom_distiller/ios/distiller_page_ios.mm
index 8ae4962..8ffacdf 100644
--- a/components/dom_distiller/ios/distiller_page_ios.mm
+++ b/components/dom_distiller/ios/distiller_page_ios.mm
@@ -13,10 +13,14 @@
 #include "base/mac/foundation_util.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "ios/public/provider/web/web_controller_provider.h"
-#include "ios/public/provider/web/web_controller_provider_factory.h"
+#include "components/favicon/ios/web_favicon_driver.h"
 #include "ios/web/public/browser_state.h"
+#import "ios/web/public/navigation_manager.h"
+#import "ios/web/public/web_state/js/crw_js_injection_manager.h"
+#import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/web_state.h"
 
 namespace {
 
@@ -105,6 +109,7 @@
   // WebStateObserver implementation:
   void PageLoaded(
       web::PageLoadCompletionStatus load_completion_status) override;
+  void WebStateDestroyed() override;
 
  private:
   DistillerPageIOS* distiller_page_;  // weak, owns this object.
@@ -123,11 +128,15 @@
   distiller_page_->OnLoadURLDone(load_completion_status);
 }
 
+void DistillerWebStateObserver::WebStateDestroyed() {
+  distiller_page_->web_state_ = nullptr;
+}
+
 #pragma mark -
 
-DistillerPageIOS::DistillerPageIOS(web::BrowserState* browser_state)
-    : browser_state_(browser_state), weak_ptr_factory_(this) {
-}
+DistillerPageIOS::DistillerPageIOS(
+    FaviconWebStateDispatcher* web_state_dispatcher)
+    : web_state_dispatcher_(web_state_dispatcher), weak_ptr_factory_(this) {}
 
 DistillerPageIOS::~DistillerPageIOS() {
 }
@@ -143,44 +152,56 @@
   url_ = url;
   script_ = script;
 
-  // Lazily create provider.
-  if (!provider_) {
-    if (ios::GetWebControllerProviderFactory()) {
-      provider_ =
-          ios::GetWebControllerProviderFactory()->CreateWebControllerProvider(
-              browser_state_);
-      web_state_observer_.reset(
-          new DistillerWebStateObserver(provider_->GetWebState(), this));
-    }
+  web_state_ = web_state_dispatcher_->RequestWebState();
+
+  if (!web_state_) {
+    OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE);
+    return;
   }
 
-  // Load page using provider.
-  if (provider_)
-    provider_->LoadURL(url_);
-  else
-    OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE);
+  web_state_observer_ =
+      base::MakeUnique<DistillerWebStateObserver>(web_state_, this);
+
+  // The favicon driver needs to know which URL is currently fetched.
+  favicon::WebFaviconDriver* favicon_driver =
+      favicon::WebFaviconDriver::FromWebState(web_state_);
+  favicon_driver->FetchFavicon(url_);
+
+  // Load page using WebState.
+  web::NavigationManager::WebLoadParams params(url_);
+  web_state_->SetWebUsageEnabled(true);
+  web_state_->GetNavigationManager()->LoadURLWithParams(params);
+  // GetView is needed because the view is not created (but needed) when
+  // loading the page.
+  web_state_->GetView();
 }
 
 void DistillerPageIOS::OnLoadURLDone(
     web::PageLoadCompletionStatus load_completion_status) {
   // Don't attempt to distill if the page load failed or if there is no
-  // provider.
+  // WebState.
   if (load_completion_status == web::PageLoadCompletionStatus::FAILURE ||
-      !provider_) {
+      !web_state_) {
     HandleJavaScriptResult(nil);
     return;
   }
 
   // Inject the script.
   base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr();
-  provider_->InjectScript(script_, ^(id result, NSError* error) {
-    DistillerPageIOS* distiller_page = weak_this.get();
-    if (distiller_page)
-      distiller_page->HandleJavaScriptResult(result);
-  });
+
+  [[web_state_->GetJSInjectionReceiver()
+      instanceOfClass:[CRWJSInjectionManager class]]
+      executeJavaScript:base::SysUTF8ToNSString(script_)
+      completionHandler:^(id result, NSError* error) {
+        DistillerPageIOS* distiller_page = weak_this.get();
+        if (distiller_page)
+          distiller_page->HandleJavaScriptResult(result);
+      }];
 }
 
 void DistillerPageIOS::HandleJavaScriptResult(id result) {
+  web_state_dispatcher_->ReturnWebState(web_state_);
+  web_state_ = nullptr;
   std::unique_ptr<base::Value> resultValue = base::Value::CreateNullValue();
   if (result) {
     resultValue = ValueResultFromScriptResult(result);
diff --git a/components/dom_distiller/ios/favicon_web_state_dispatcher.h b/components/dom_distiller/ios/favicon_web_state_dispatcher.h
new file mode 100644
index 0000000..c34e6985
--- /dev/null
+++ b/components/dom_distiller/ios/favicon_web_state_dispatcher.h
@@ -0,0 +1,34 @@
+// Copyright 2016 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 COMPONENTS_DOM_DISTILLER_IOS_FAVICON_WEB_STATE_DISPATCHER_H_
+#define COMPONENTS_DOM_DISTILLER_IOS_FAVICON_WEB_STATE_DISPATCHER_H_
+
+namespace web {
+class WebState;
+}
+
+namespace dom_distiller {
+
+// Dispatcher for WebState having a Favicon Driver, with BookmarkModel and
+// HistoryService attached, as observer. The Webstates are kept alive between
+// their creation and their return. After a WebState is returned, the dispatcher
+// keeps it alive long enough for it to download the favicons.
+class FaviconWebStateDispatcher {
+ public:
+  FaviconWebStateDispatcher() {}
+  virtual ~FaviconWebStateDispatcher() {}
+  // Returns a WebState with a Favicon Driver attached.
+  virtual web::WebState* RequestWebState() = 0;
+  // Called to return a WebState. The WebState should not be used after being
+  // returned.
+  virtual void ReturnWebState(web::WebState* web_state) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FaviconWebStateDispatcher);
+};
+
+}  // namespace dom_distiller
+
+#endif  // COMPONENTS_DOM_DISTILLER_IOS_FAVICON_WEB_STATE_DISPATCHER_H_
diff --git a/components/precache/content/precache_manager.cc b/components/precache/content/precache_manager.cc
index 204ab49..1bb6820 100644
--- a/components/precache/content/precache_manager.cc
+++ b/components/precache/content/precache_manager.cc
@@ -123,10 +123,11 @@
     return AllowedType::PENDING;
 
   // SyncService delegates to SyncPrefs, which must be called on the UI thread.
-  if (history_service_ &&
+  if (history_service_ && !sync_service_->IsLocalSyncEnabled() &&
       sync_service_->GetActiveDataTypes().Has(syncer::SESSIONS) &&
-      !sync_service_->GetEncryptedDataTypes().Has(syncer::SESSIONS))
+      !sync_service_->GetEncryptedDataTypes().Has(syncer::SESSIONS)) {
     return AllowedType::ALLOWED;
+  }
 
   return AllowedType::DISALLOWED;
 }
diff --git a/components/suggestions/suggestions_service_impl.cc b/components/suggestions/suggestions_service_impl.cc
index ae792b1..f181599c 100644
--- a/components/suggestions/suggestions_service_impl.cc
+++ b/components/suggestions/suggestions_service_impl.cc
@@ -66,7 +66,7 @@
 };
 
 SyncState GetSyncState(syncer::SyncService* sync) {
-  if (!sync || !sync->CanSyncStart())
+  if (!sync || !sync->CanSyncStart() || sync->IsLocalSyncEnabled())
     return SYNC_OR_HISTORY_SYNC_DISABLED;
   if (!sync->IsSyncActive() || !sync->ConfigurationDone())
     return NOT_INITIALIZED_ENABLED;
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 8a9d6df..3c047ea 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -336,6 +336,20 @@
     "engine_impl/js_sync_encryption_handler_observer.h",
     "engine_impl/js_sync_manager_observer.cc",
     "engine_impl/js_sync_manager_observer.h",
+    "engine_impl/loopback_server/loopback_connection_manager.cc",
+    "engine_impl/loopback_server/loopback_connection_manager.h",
+    "engine_impl/loopback_server/loopback_server.cc",
+    "engine_impl/loopback_server/loopback_server.h",
+    "engine_impl/loopback_server/loopback_server_entity.cc",
+    "engine_impl/loopback_server/loopback_server_entity.h",
+    "engine_impl/loopback_server/persistent_bookmark_entity.cc",
+    "engine_impl/loopback_server/persistent_bookmark_entity.h",
+    "engine_impl/loopback_server/persistent_permanent_entity.cc",
+    "engine_impl/loopback_server/persistent_permanent_entity.h",
+    "engine_impl/loopback_server/persistent_tombstone_entity.cc",
+    "engine_impl/loopback_server/persistent_tombstone_entity.h",
+    "engine_impl/loopback_server/persistent_unique_client_entity.cc",
+    "engine_impl/loopback_server/persistent_unique_client_entity.h",
     "engine_impl/model_type_connector_proxy.cc",
     "engine_impl/model_type_connector_proxy.h",
     "engine_impl/model_type_registry.cc",
@@ -607,25 +621,6 @@
     ]
   }
 
-  if (is_win) {
-    sources += [
-      "engine_impl/loopback_server/loopback_connection_manager.cc",
-      "engine_impl/loopback_server/loopback_connection_manager.h",
-      "engine_impl/loopback_server/loopback_server.cc",
-      "engine_impl/loopback_server/loopback_server.h",
-      "engine_impl/loopback_server/loopback_server_entity.cc",
-      "engine_impl/loopback_server/loopback_server_entity.h",
-      "engine_impl/loopback_server/persistent_bookmark_entity.cc",
-      "engine_impl/loopback_server/persistent_bookmark_entity.h",
-      "engine_impl/loopback_server/persistent_permanent_entity.cc",
-      "engine_impl/loopback_server/persistent_permanent_entity.h",
-      "engine_impl/loopback_server/persistent_tombstone_entity.cc",
-      "engine_impl/loopback_server/persistent_tombstone_entity.h",
-      "engine_impl/loopback_server/persistent_unique_client_entity.cc",
-      "engine_impl/loopback_server/persistent_unique_client_entity.h",
-    ]
-  }
-
   if (!is_ios) {
     sources += [
       "driver/sync_policy_handler.cc",
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index e0adcb3..25b54cf 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -5,7 +5,9 @@
 #include "components/sync/base/sync_prefs.h"
 
 #include "base/base64.h"
+#include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -553,7 +555,20 @@
 }
 
 base::FilePath SyncPrefs::GetLocalSyncBackendDir() const {
-  return pref_service_->GetFilePath(prefs::kLocalSyncBackendDir);
+  base::FilePath local_sync_backend_folder =
+      pref_service_->GetFilePath(prefs::kLocalSyncBackendDir);
+
+#if defined(OS_WIN)
+  if (local_sync_backend_folder.empty()) {
+    // TODO(pastarmovj): Add DIR_ROAMING_USER_DATA to PathService to simplify
+    // this code and move the logic in its right place. See crbug/657810.
+    CHECK(
+        base::PathService::Get(base::DIR_APP_DATA, &local_sync_backend_folder));
+    local_sync_backend_folder =
+        local_sync_backend_folder.Append(FILE_PATH_LITERAL("Chrome/User Data"));
+  }
+#endif  // defined(OS_WIN)
+  return local_sync_backend_folder;
 }
 
 }  // namespace syncer
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc
index fcc3d69c..71abee3 100644
--- a/components/sync/driver/fake_sync_service.cc
+++ b/components/sync/driver/fake_sync_service.cc
@@ -30,6 +30,10 @@
   return false;
 }
 
+bool FakeSyncService::IsLocalSyncEnabled() const {
+  return false;
+}
+
 void FakeSyncService::TriggerRefresh(const ModelTypeSet& types) {}
 
 ModelTypeSet FakeSyncService::GetActiveDataTypes() const {
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h
index fa031a83..543a382 100644
--- a/components/sync/driver/fake_sync_service.h
+++ b/components/sync/driver/fake_sync_service.h
@@ -28,6 +28,7 @@
   bool IsFirstSetupComplete() const override;
   bool IsSyncAllowed() const override;
   bool IsSyncActive() const override;
+  bool IsLocalSyncEnabled() const override;
   void TriggerRefresh(const ModelTypeSet& types) override;
   ModelTypeSet GetActiveDataTypes() const override;
   SyncClient* GetSyncClient() const override;
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index a07f5d5e..364ec99 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -108,6 +108,12 @@
   // datetypes are actually syncing, see GetActiveTypes() below.
   virtual bool IsSyncActive() const = 0;
 
+  // Returns true if the local sync backend server has been enabled through a
+  // command line flag or policy. In this case sync is considered active but any
+  // implied consent for further related services e.g. Suggestions, Web History
+  // etc. is considered not granted.
+  virtual bool IsLocalSyncEnabled() const = 0;
+
   // Triggers a GetUpdates call for the specified |types|, pulling any new data
   // from the sync server.
   virtual void TriggerRefresh(const ModelTypeSet& types) = 0;
diff --git a/components/sync/driver/sync_service_base.cc b/components/sync/driver/sync_service_base.cc
index 37eacd8..b534aba 100644
--- a/components/sync/driver/sync_service_base.cc
+++ b/components/sync/driver/sync_service_base.cc
@@ -136,6 +136,7 @@
   // solution for now will be to assume profiles are created in the same order
   // on all machines and in the future decide if only the Default one should be
   // considered roamed.
+  // See http://crbug.com/674928.
   *local_sync_backend_folder =
       local_sync_backend_folder->Append(base_directory_.BaseName());
   *local_sync_backend_folder =
diff --git a/components/sync/engine/engine_components_factory.h b/components/sync/engine/engine_components_factory.h
index fb80d03..70c6b1f 100644
--- a/components/sync/engine/engine_components_factory.h
+++ b/components/sync/engine/engine_components_factory.h
@@ -90,7 +90,8 @@
   virtual std::unique_ptr<SyncScheduler> BuildScheduler(
       const std::string& name,
       SyncCycleContext* context,
-      CancelationSignal* cancelation_signal) = 0;
+      CancelationSignal* cancelation_signal,
+      bool ignore_auth_credentials) = 0;
 
   virtual std::unique_ptr<SyncCycleContext> BuildContext(
       ServerConnectionManager* connection_manager,
diff --git a/components/sync/engine/engine_components_factory_impl.cc b/components/sync/engine/engine_components_factory_impl.cc
index d3d3a88..dd913f9 100644
--- a/components/sync/engine/engine_components_factory_impl.cc
+++ b/components/sync/engine/engine_components_factory_impl.cc
@@ -28,7 +28,8 @@
 std::unique_ptr<SyncScheduler> EngineComponentsFactoryImpl::BuildScheduler(
     const std::string& name,
     SyncCycleContext* context,
-    CancelationSignal* cancelation_signal) {
+    CancelationSignal* cancelation_signal,
+    bool ignore_auth_credentials) {
   std::unique_ptr<BackoffDelayProvider> delay(
       BackoffDelayProvider::FromDefaults());
 
@@ -38,7 +39,8 @@
 
   std::unique_ptr<SyncSchedulerImpl> scheduler =
       base::MakeUnique<SyncSchedulerImpl>(name, delay.release(), context,
-                                          new Syncer(cancelation_signal));
+                                          new Syncer(cancelation_signal),
+                                          ignore_auth_credentials);
   if (switches_.nudge_delay == NudgeDelay::SHORT_NUDGE_DELAY) {
     // Set the default nudge delay to 0 because the default is used as a floor
     // for override values, and we don't want the below override to be ignored.
diff --git a/components/sync/engine/engine_components_factory_impl.h b/components/sync/engine/engine_components_factory_impl.h
index 6bf4ef9..a16cc5e 100644
--- a/components/sync/engine/engine_components_factory_impl.h
+++ b/components/sync/engine/engine_components_factory_impl.h
@@ -24,7 +24,8 @@
   std::unique_ptr<SyncScheduler> BuildScheduler(
       const std::string& name,
       SyncCycleContext* context,
-      CancelationSignal* cancelation_signal) override;
+      CancelationSignal* cancelation_signal,
+      bool ignore_auth_credentials) override;
 
   std::unique_ptr<SyncCycleContext> BuildContext(
       ServerConnectionManager* connection_manager,
diff --git a/components/sync/engine/test_engine_components_factory.cc b/components/sync/engine/test_engine_components_factory.cc
index 116c6d2b..d71f1b53 100644
--- a/components/sync/engine/test_engine_components_factory.cc
+++ b/components/sync/engine/test_engine_components_factory.cc
@@ -25,7 +25,8 @@
 std::unique_ptr<SyncScheduler> TestEngineComponentsFactory::BuildScheduler(
     const std::string& name,
     SyncCycleContext* context,
-    CancelationSignal* cancelation_signal) {
+    CancelationSignal* cancelation_signal,
+    bool ignore_auth_credentials) {
   return std::unique_ptr<SyncScheduler>(new FakeSyncScheduler());
 }
 
diff --git a/components/sync/engine/test_engine_components_factory.h b/components/sync/engine/test_engine_components_factory.h
index 575f8c5..0f2ec77 100644
--- a/components/sync/engine/test_engine_components_factory.h
+++ b/components/sync/engine/test_engine_components_factory.h
@@ -24,7 +24,8 @@
   std::unique_ptr<SyncScheduler> BuildScheduler(
       const std::string& name,
       SyncCycleContext* context,
-      CancelationSignal* cancelation_signal) override;
+      CancelationSignal* cancelation_signal,
+      bool ignore_auth_credentials) override;
 
   std::unique_ptr<SyncCycleContext> BuildContext(
       ServerConnectionManager* connection_manager,
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc
index 87dd222..cbacc993 100644
--- a/components/sync/engine_impl/sync_manager_impl.cc
+++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -30,6 +30,7 @@
 #include "components/sync/engine/net/http_post_provider_factory.h"
 #include "components/sync/engine/polling_constants.h"
 #include "components/sync/engine_impl/cycle/directory_type_debug_info_emitter.h"
+#include "components/sync/engine_impl/loopback_server/loopback_connection_manager.h"
 #include "components/sync/engine_impl/model_type_connector_proxy.h"
 #include "components/sync/engine_impl/net/sync_server_connection_manager.h"
 #include "components/sync/engine_impl/sync_scheduler.h"
@@ -47,9 +48,6 @@
 #include "components/sync/syncable/write_node.h"
 #include "components/sync/syncable/write_transaction.h"
 
-#if defined(OS_WIN)
-#include "components/sync/engine_impl/loopback_server/loopback_connection_manager.h"
-#endif
 
 using base::TimeDelta;
 using sync_pb::GetUpdatesCallerInfo;
@@ -212,9 +210,11 @@
   CHECK(!initialized_);
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(args->post_factory.get());
-  DCHECK(!args->credentials.account_id.empty());
-  DCHECK(!args->credentials.sync_token.empty());
-  DCHECK(!args->credentials.scope_set.empty());
+  if (!args->enable_local_sync_backend) {
+    DCHECK(!args->credentials.account_id.empty());
+    DCHECK(!args->credentials.sync_token.empty());
+    DCHECK(!args->credentials.scope_set.empty());
+  }
   DCHECK(args->cancelation_signal);
   DVLOG(1) << "SyncManager starting Init...";
 
@@ -276,13 +276,9 @@
   }
 
   if (args->enable_local_sync_backend) {
-#if defined(OS_WIN)
     VLOG(1) << "Running against local sync backend.";
     connection_manager_ = base::MakeUnique<LoopbackConnectionManager>(
         args->cancelation_signal, args->local_sync_backend_folder);
-#else
-    NOTREACHED();
-#endif  // defined(OS_WIN)
   } else {
     connection_manager_ = base::MakeUnique<SyncServerConnectionManager>(
         args->service_url.host() + args->service_url.path(),
@@ -316,17 +312,22 @@
       listeners, &debug_info_event_listener_, model_type_registry_.get(),
       args->invalidator_client_id);
   scheduler_ = args->engine_components_factory->BuildScheduler(
-      name_, cycle_context_.get(), args->cancelation_signal);
+      name_, cycle_context_.get(), args->cancelation_signal,
+      args->enable_local_sync_backend);
 
   scheduler_->Start(SyncScheduler::CONFIGURATION_MODE, base::Time());
 
   initialized_ = true;
 
-  net::NetworkChangeNotifier::AddIPAddressObserver(this);
-  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
-  observing_network_connectivity_changes_ = true;
+  if (!args->enable_local_sync_backend) {
+    net::NetworkChangeNotifier::AddIPAddressObserver(this);
+    net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+    observing_network_connectivity_changes_ = true;
 
-  UpdateCredentials(args->credentials);
+    UpdateCredentials(args->credentials);
+  } else {
+    scheduler_->OnCredentialsUpdated();
+  }
 
   NotifyInitializationSuccess();
 }
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc
index 5f9db5d8..afaab93 100644
--- a/components/sync/engine_impl/sync_manager_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -996,8 +996,7 @@
 
   virtual ~SyncManagerTest() {}
 
-  // Test implementation.
-  void SetUp() {
+  virtual void DoSetUp(bool enable_local_sync_backend) {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 
     extensions_activity_ = new ExtensionsActivity();
@@ -1035,8 +1034,11 @@
     args.workers = workers;
     args.extensions_activity = extensions_activity_.get(),
     args.change_delegate = this;
-    args.credentials = credentials;
+    if (!enable_local_sync_backend)
+      args.credentials = credentials;
     args.invalidator_client_id = "fake_invalidator_client_id";
+    args.enable_local_sync_backend = enable_local_sync_backend;
+    args.local_sync_backend_folder = temp_dir_.GetPath();
     args.engine_components_factory.reset(GetFactory());
     args.encryptor = &encryptor_;
     args.unrecoverable_error_handler =
@@ -1060,6 +1062,9 @@
     PumpLoop();
   }
 
+  // Test implementation.
+  void SetUp() { DoSetUp(false); }
+
   void TearDown() {
     sync_manager_.RemoveObserver(&manager_observer_);
     sync_manager_.ShutdownOnSyncThread(STOP_SYNC);
@@ -2692,6 +2697,38 @@
   }
 }
 
+class SyncManagerWithLocalBackendTest : public SyncManagerTest {
+ protected:
+  void SetUp() override { DoSetUp(true); }
+};
+
+// This test checks that we can successfully initialize without credentials in
+// the local backend case.
+TEST_F(SyncManagerWithLocalBackendTest, StartSyncInLocalMode) {
+  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
+  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
+  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
+  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
+
+  sync_manager_.GetEncryptionHandler()->Init();
+  PumpLoop();
+
+  const ModelTypeSet encrypted_types = GetEncryptedTypes();
+  EXPECT_TRUE(encrypted_types.Has(PASSWORDS));
+  EXPECT_FALSE(IsEncryptEverythingEnabledForTest());
+
+  {
+    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
+    ReadNode node(&trans);
+    EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(GetIdForDataType(NIGORI)));
+    sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics();
+    EXPECT_TRUE(nigori.has_encryption_keybag());
+    Cryptographer* cryptographer = trans.GetCryptographer();
+    EXPECT_TRUE(cryptographer->is_ready());
+    EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encryption_keybag()));
+  }
+}
+
 class MockSyncScheduler : public FakeSyncScheduler {
  public:
   MockSyncScheduler() : FakeSyncScheduler() {}
@@ -2717,7 +2754,8 @@
   std::unique_ptr<SyncScheduler> BuildScheduler(
       const std::string& name,
       SyncCycleContext* context,
-      CancelationSignal* stop_handle) override {
+      CancelationSignal* stop_handle,
+      bool local_sync_backend_enabled) override {
     *cycle_context_ = context;
     return std::move(scheduler_to_use_);
   }
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc
index edc26fc..69559b51 100644
--- a/components/sync/engine_impl/sync_scheduler_impl.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -151,7 +151,8 @@
 SyncSchedulerImpl::SyncSchedulerImpl(const std::string& name,
                                      BackoffDelayProvider* delay_provider,
                                      SyncCycleContext* context,
-                                     Syncer* syncer)
+                                     Syncer* syncer,
+                                     bool ignore_auth_credentials)
     : name_(name),
       started_(false),
       syncer_short_poll_interval_seconds_(
@@ -163,6 +164,7 @@
       syncer_(syncer),
       cycle_context_(context),
       next_sync_cycle_job_priority_(NORMAL_PRIORITY),
+      ignore_auth_credentials_(ignore_auth_credentials),
       weak_ptr_factory_(this),
       weak_ptr_factory_for_weak_handle_(this) {
   weak_handle_this_ =
@@ -337,7 +339,8 @@
     return false;
   }
 
-  if (cycle_context_->connection_manager()->HasInvalidAuthToken()) {
+  if (!ignore_auth_credentials_ &&
+      cycle_context_->connection_manager()->HasInvalidAuthToken()) {
     SDVLOG(1) << "Unable to run a job because we have no valid auth token.";
     return false;
   }
diff --git a/components/sync/engine_impl/sync_scheduler_impl.h b/components/sync/engine_impl/sync_scheduler_impl.h
index 6a6208a..c9fe0bd 100644
--- a/components/sync/engine_impl/sync_scheduler_impl.h
+++ b/components/sync/engine_impl/sync_scheduler_impl.h
@@ -40,7 +40,8 @@
   SyncSchedulerImpl(const std::string& name,
                     BackoffDelayProvider* delay_provider,
                     SyncCycleContext* context,
-                    Syncer* syncer);
+                    Syncer* syncer,
+                    bool ignore_auth_credentials);
 
   // Calls Stop().
   ~SyncSchedulerImpl() override;
@@ -291,6 +292,9 @@
   // One-shot timer for scheduling GU retry according to delay set by server.
   base::OneShotTimer retry_timer_;
 
+  // Dictates if the scheduler should wait for authentication to happen or not.
+  bool ignore_auth_credentials_;
+
   base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_;
 
   // A second factory specially for weak_handle_this_, to allow the handle
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
index 94f7e78..d4d6734 100644
--- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -159,7 +159,7 @@
     context_->set_account_name("Test");
     scheduler_ = base::MakeUnique<SyncSchedulerImpl>(
         "TestSyncScheduler", BackoffDelayProvider::FromDefaults(), context(),
-        syncer_);
+        syncer_, false);
     scheduler_->SetDefaultNudgeDelay(default_delay());
   }
 
@@ -283,6 +283,15 @@
     tracker_it->second->wait_interval_->mode = mode;
   }
 
+  void NewSchedulerForLocalBackend() {
+    // The old syncer is destroyed with the scheduler that owns it.
+    syncer_ = new testing::StrictMock<MockSyncer>();
+    scheduler_ = base::MakeUnique<SyncSchedulerImpl>(
+        "TestSyncScheduler", BackoffDelayProvider::FromDefaults(), context(),
+        syncer_, true);
+    scheduler_->SetDefaultNudgeDelay(default_delay());
+  }
+
  private:
   syncable::Directory* directory() {
     return test_user_share_.user_share()->directory.get();
@@ -468,6 +477,56 @@
   ASSERT_EQ(0, retry_counter.times_called());
 }
 
+// Verify that in the absence of valid auth token the command will fail.
+TEST_F(SyncSchedulerImplTest, ConfigNoAuthToken) {
+  SyncShareTimes times;
+  const ModelTypeSet model_types(THEMES);
+
+  connection()->ResetAuthToken();
+
+  StartSyncConfiguration();
+
+  CallbackCounter ready_counter;
+  CallbackCounter retry_counter;
+  ConfigurationParams params(
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
+      TypesToRoutingInfo(model_types),
+      base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+      base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+  scheduler()->ScheduleConfiguration(params);
+  PumpLoop();
+  ASSERT_EQ(0, ready_counter.times_called());
+  ASSERT_EQ(1, retry_counter.times_called());
+}
+
+// Verify that in the absence of valid auth token the command will pass if local
+// sync backend is used.
+TEST_F(SyncSchedulerImplTest, ConfigNoAuthTokenLocalSync) {
+  SyncShareTimes times;
+  const ModelTypeSet model_types(THEMES);
+
+  NewSchedulerForLocalBackend();
+  connection()->ResetAuthToken();
+
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(test_util::SimulateConfigureSuccess),
+                      RecordSyncShare(&times, true)));
+
+  StartSyncConfiguration();
+
+  CallbackCounter ready_counter;
+  CallbackCounter retry_counter;
+  ConfigurationParams params(
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
+      TypesToRoutingInfo(model_types),
+      base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+      base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+  scheduler()->ScheduleConfiguration(params);
+  PumpLoop();
+  ASSERT_EQ(1, ready_counter.times_called());
+  ASSERT_EQ(0, retry_counter.times_called());
+}
+
 // Issue a nudge when the config has failed. Make sure both the config and
 // nudge are executed.
 TEST_F(SyncSchedulerImplTest, NudgeWithConfigWithBackingOff) {
diff --git a/components/sync/engine_impl/syncer_unittest.cc b/components/sync/engine_impl/syncer_unittest.cc
index 627e673..c07f91a 100644
--- a/components/sync/engine_impl/syncer_unittest.cc
+++ b/components/sync/engine_impl/syncer_unittest.cc
@@ -302,7 +302,7 @@
         "TestSyncScheduler", BackoffDelayProvider::FromDefaults(),
         context_.get(),
         // scheduler_ owned syncer_ now and will manage the memory of syncer_
-        syncer_);
+        syncer_, false);
 
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Directory::Metahandles children;
diff --git a/components/sync/test/engine/mock_connection_manager.h b/components/sync/test/engine/mock_connection_manager.h
index 37e42bc..46fc150 100644
--- a/components/sync/test/engine/mock_connection_manager.h
+++ b/components/sync/test/engine/mock_connection_manager.h
@@ -272,6 +272,8 @@
   // Adds a new progress marker to the last update.
   sync_pb::DataTypeProgressMarker* AddUpdateProgressMarker();
 
+  void ResetAuthToken() { auth_token_.clear(); }
+
  private:
   sync_pb::SyncEntity* AddUpdateFull(syncable::Id id,
                                      syncable::Id parentid,
diff --git a/ios/chrome/browser/dom_distiller/BUILD.gn b/ios/chrome/browser/dom_distiller/BUILD.gn
index 67b4e9e..809293d9 100644
--- a/ios/chrome/browser/dom_distiller/BUILD.gn
+++ b/ios/chrome/browser/dom_distiller/BUILD.gn
@@ -8,19 +8,44 @@
     "distiller_viewer.h",
     "dom_distiller_service_factory.cc",
     "dom_distiller_service_factory.h",
+    "favicon_web_state_dispatcher_impl.h",
+    "favicon_web_state_dispatcher_impl.mm",
   ]
   deps = [
     "//base",
-    "//components/dom_distiller/core",
     "//components/dom_distiller/ios",
+    "//components/favicon/core",
+    "//components/favicon/ios",
     "//components/keyed_service/core",
     "//components/keyed_service/ios",
     "//components/leveldb_proto",
+    "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/favicon",
+    "//ios/chrome/browser/history",
+    "//ios/public/provider/web",
     "//ios/web",
     "//ui/gfx",
+    "//url",
   ]
   public_deps = [
     "//components/dom_distiller/core",
   ]
 }
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "favicon_web_state_dispatcher_impl_unittest.mm",
+  ]
+  deps = [
+    ":dom_distiller",
+    "//base",
+    "//components/favicon/ios",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/testing:ios_test_support",
+    "//ios/web",
+    "//ios/web:test_support",
+    "//testing/gtest",
+  ]
+}
diff --git a/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc b/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
index 2367b128..23a86a1 100644
--- a/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
+++ b/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
@@ -20,17 +20,20 @@
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/leveldb_proto/proto_database.h"
 #include "components/leveldb_proto/proto_database_impl.h"
+#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.h"
+#include "ios/chrome/browser/favicon/favicon_service_factory.h"
+#include "ios/chrome/browser/history/history_service_factory.h"
 #include "ios/web/public/browser_state.h"
 #include "ios/web/public/web_thread.h"
 
 namespace {
 // A simple wrapper for DomDistillerService to expose it as a
 // KeyedService.
-class DomDistillerKeyedService
-    : public KeyedService,
-      public dom_distiller::DomDistillerService {
+class DomDistillerKeyedService : public KeyedService,
+                                 public dom_distiller::DomDistillerService {
  public:
   DomDistillerKeyedService(
       std::unique_ptr<dom_distiller::DomDistillerStoreInterface> store,
@@ -68,10 +71,12 @@
     : BrowserStateKeyedServiceFactory(
           "DomDistillerService",
           BrowserStateDependencyManager::GetInstance()) {
+  DependsOn(ios::FaviconServiceFactory::GetInstance());
+  DependsOn(ios::HistoryServiceFactory::GetInstance());
+  DependsOn(ios::BookmarkModelFactory::GetInstance());
 }
 
-DomDistillerServiceFactory::~DomDistillerServiceFactory() {
-}
+DomDistillerServiceFactory::~DomDistillerServiceFactory() {}
 
 std::unique_ptr<KeyedService>
 DomDistillerServiceFactory::BuildServiceInstanceFor(
@@ -80,27 +85,33 @@
       web::WebThread::GetBlockingPool()->GetSequencedTaskRunner(
           web::WebThread::GetBlockingPool()->GetSequenceToken());
 
-  std::unique_ptr<leveldb_proto::ProtoDatabaseImpl<ArticleEntry>> db(
-      new leveldb_proto::ProtoDatabaseImpl<ArticleEntry>(
-          background_task_runner));
+  std::unique_ptr<leveldb_proto::ProtoDatabaseImpl<ArticleEntry>> db =
+      base::MakeUnique<leveldb_proto::ProtoDatabaseImpl<ArticleEntry>>(
+          background_task_runner);
 
   base::FilePath database_dir(
       context->GetStatePath().Append(FILE_PATH_LITERAL("Articles")));
 
-  std::unique_ptr<DomDistillerStore> dom_distiller_store(
-      new DomDistillerStore(std::move(db), database_dir));
+  std::unique_ptr<DomDistillerStore> dom_distiller_store =
+      base::MakeUnique<DomDistillerStore>(std::move(db), database_dir);
 
-  std::unique_ptr<DistillerPageFactory> distiller_page_factory(
-      new DistillerPageFactoryIOS(context));
-  std::unique_ptr<DistillerURLFetcherFactory> distiller_url_fetcher_factory(
-      new DistillerURLFetcherFactory(context->GetRequestContext()));
+  std::unique_ptr<FaviconWebStateDispatcher> web_state_dispatcher =
+      base::MakeUnique<FaviconWebStateDispatcherImpl>(context, -1);
+  std::unique_ptr<DistillerPageFactory> distiller_page_factory =
+      base::MakeUnique<DistillerPageFactoryIOS>(
+          std::move(web_state_dispatcher));
+
+  std::unique_ptr<DistillerURLFetcherFactory> distiller_url_fetcher_factory =
+      base::MakeUnique<DistillerURLFetcherFactory>(
+          context->GetRequestContext());
 
   dom_distiller::proto::DomDistillerOptions options;
-  std::unique_ptr<DistillerFactory> distiller_factory(new DistillerFactoryImpl(
-      std::move(distiller_url_fetcher_factory), options));
-  std::unique_ptr<DistilledPagePrefs> distilled_page_prefs(
-      new DistilledPagePrefs(
-          ios::ChromeBrowserState::FromBrowserState(context)->GetPrefs()));
+  std::unique_ptr<DistillerFactory> distiller_factory =
+      base::MakeUnique<DistillerFactoryImpl>(
+          std::move(distiller_url_fetcher_factory), options);
+  std::unique_ptr<DistilledPagePrefs> distilled_page_prefs =
+      base::MakeUnique<DistilledPagePrefs>(
+          ios::ChromeBrowserState::FromBrowserState(context)->GetPrefs());
 
   return base::MakeUnique<DomDistillerKeyedService>(
       std::move(dom_distiller_store), std::move(distiller_factory),
diff --git a/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.h b/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.h
new file mode 100644
index 0000000..d2e976813
--- /dev/null
+++ b/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.h
@@ -0,0 +1,44 @@
+// Copyright 2016 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 IOS_CHROME_BROWSER_DOM_DISTILLER_FAVICON_WEB_STATE_DISPATCHER_IMPL_H_
+#define IOS_CHROME_BROWSER_DOM_DISTILLER_FAVICON_WEB_STATE_DISPATCHER_IMPL_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "components/dom_distiller/ios/favicon_web_state_dispatcher.h"
+
+namespace web {
+class BrowserState;
+}
+
+namespace dom_distiller {
+
+// Implementation of the FaviconWebStateDispatcher.
+class FaviconWebStateDispatcherImpl : public FaviconWebStateDispatcher {
+ public:
+  // Constructor for keeping the WebStates alive for |keep_alive_second|
+  // seconds. If |keep_alive_second| < 0 then the default value is used.
+  FaviconWebStateDispatcherImpl(web::BrowserState* browser_state,
+                                int64_t keep_alive_second);
+  ~FaviconWebStateDispatcherImpl() override;
+
+  // FaviconWebStateDispatcher implementation.
+  web::WebState* RequestWebState() override;
+  void ReturnWebState(web::WebState* web_state) override;
+
+ private:
+  web::BrowserState* browser_state_;
+  // Map of the WebStates currently alive.
+  std::vector<std::unique_ptr<web::WebState>> web_states_;
+  // Time during which the WebState will be kept alive after being returned.
+  int64_t keep_alive_second_;
+  base::WeakPtrFactory<FaviconWebStateDispatcherImpl> weak_ptr_factory_;
+};
+
+}  // namespace dom_distiller
+
+#endif  // IOS_CHROME_BROWSER_DOM_DISTILLER_FAVICON_WEB_STATE_DISPATCHER_IMPL_H_
diff --git a/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.mm b/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.mm
new file mode 100644
index 0000000..e74431d1
--- /dev/null
+++ b/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.mm
@@ -0,0 +1,77 @@
+// Copyright 2016 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 "ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.h"
+
+#include "components/favicon/ios/web_favicon_driver.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/favicon/favicon_service_factory.h"
+#include "ios/chrome/browser/history/history_service_factory.h"
+#import "ios/web/public/web_state/web_state.h"
+
+namespace {
+// Default delay to download the favicon when the WebState is handed back.
+const int64_t kDefaultDelayFaviconSecond = 10;
+}
+
+namespace dom_distiller {
+
+FaviconWebStateDispatcherImpl::FaviconWebStateDispatcherImpl(
+    web::BrowserState* browser_state,
+    int64_t keep_alive_second)
+    : FaviconWebStateDispatcher(),
+      browser_state_(browser_state),
+      keep_alive_second_(keep_alive_second),
+      weak_ptr_factory_(this) {
+  if (keep_alive_second_ < 0)
+    keep_alive_second_ = kDefaultDelayFaviconSecond;
+}
+
+FaviconWebStateDispatcherImpl::~FaviconWebStateDispatcherImpl() {}
+
+web::WebState* FaviconWebStateDispatcherImpl::RequestWebState() {
+  const web::WebState::CreateParams web_state_create_params(browser_state_);
+  std::unique_ptr<web::WebState> web_state_unique =
+      web::WebState::Create(web_state_create_params);
+  web::WebState* web_state = web_state_unique.get();
+
+  web_states_.push_back(std::move(web_state_unique));
+
+  ios::ChromeBrowserState* original_browser_state =
+      ios::ChromeBrowserState::FromBrowserState(browser_state_);
+
+  favicon::WebFaviconDriver::CreateForWebState(
+      web_state,
+      ios::FaviconServiceFactory::GetForBrowserState(
+          original_browser_state, ServiceAccessType::EXPLICIT_ACCESS),
+      ios::HistoryServiceFactory::GetForBrowserState(
+          original_browser_state, ServiceAccessType::EXPLICIT_ACCESS),
+      ios::BookmarkModelFactory::GetForBrowserState(original_browser_state));
+
+  return web_state;
+}
+
+void FaviconWebStateDispatcherImpl::ReturnWebState(web::WebState* web_state) {
+  base::WeakPtr<FaviconWebStateDispatcherImpl> weak_this =
+      weak_ptr_factory_.GetWeakPtr();
+  dispatch_after(
+      dispatch_time(DISPATCH_TIME_NOW, keep_alive_second_ * NSEC_PER_SEC),
+      dispatch_get_main_queue(), ^{
+        FaviconWebStateDispatcherImpl* web_state_dispatcher = weak_this.get();
+        if (web_state_dispatcher) {
+          auto it = find_if(
+              web_state_dispatcher->web_states_.begin(),
+              web_state_dispatcher->web_states_.end(),
+              [web_state](std::unique_ptr<web::WebState>& unique_web_state) {
+                return unique_web_state.get() == web_state;
+              });
+          if (it != web_state_dispatcher->web_states_.end())
+            web_state_dispatcher->web_states_.erase(it);
+        }
+      });
+}
+
+}  // namespace dom_distiller
diff --git a/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl_unittest.mm b/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl_unittest.mm
new file mode 100644
index 0000000..2c791ee
--- /dev/null
+++ b/ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl_unittest.mm
@@ -0,0 +1,76 @@
+// Copyright 2016 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.
+
+#import "ios/chrome/browser/dom_distiller/favicon_web_state_dispatcher_impl.h"
+
+#include "base/memory/ptr_util.h"
+#include "components/favicon/ios/web_favicon_driver.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#import "ios/testing/wait_util.h"
+#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "ios/web/public/web_state/web_state_observer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace dom_distiller {
+
+// Test class.
+class FaviconWebStateDispatcherTest : public PlatformTest {
+ public:
+  FaviconWebStateDispatcherTest() : web_state_destroyed_(false) {
+    TestChromeBrowserState::Builder builder;
+    browser_state_ = builder.Build();
+  }
+
+  web::BrowserState* GetBrowserState() { return browser_state_.get(); }
+
+  bool IsWebStateDestroyed() { return web_state_destroyed_; }
+  void WebStateDestroyed() { web_state_destroyed_ = true; }
+
+ private:
+  web::TestWebThreadBundle thread_bundle_;
+  std::unique_ptr<TestChromeBrowserState> browser_state_;
+  bool web_state_destroyed_;
+};
+
+// Observer for the test.
+class TestFaviconWebStateDispatcherObserver : public web::WebStateObserver {
+ public:
+  TestFaviconWebStateDispatcherObserver(web::WebState* web_state,
+                                        FaviconWebStateDispatcherTest* owner)
+      : web::WebStateObserver(web_state), owner_(owner) {}
+
+  // WebStateObserver implementation:
+  void WebStateDestroyed() override { owner_->WebStateDestroyed(); };
+
+ private:
+  FaviconWebStateDispatcherTest* owner_;  // weak, owns this object.
+};
+
+// Tests that RequestWebState returns a WebState with a FaviconDriver attached.
+TEST_F(FaviconWebStateDispatcherTest, RequestWebState) {
+  FaviconWebStateDispatcherImpl dispatcher(GetBrowserState(), -1);
+  web::WebState* web_state = dispatcher.RequestWebState();
+
+  favicon::WebFaviconDriver* driver =
+      favicon::WebFaviconDriver::FromWebState(web_state);
+  EXPECT_NE(driver, nullptr);
+}
+
+// Tests that the WebState returned will be destroyed after a delay.
+TEST_F(FaviconWebStateDispatcherTest, ReturnWebState) {
+  FaviconWebStateDispatcherImpl dispatcher(GetBrowserState(), 0);
+  web::WebState* web_state = dispatcher.RequestWebState();
+
+  TestFaviconWebStateDispatcherObserver observer(web_state, this);
+
+  ConditionBlock condition = ^{
+    return IsWebStateDestroyed();
+  };
+
+  dispatcher.ReturnWebState(web_state);
+
+  ASSERT_TRUE(testing::WaitUntilConditionOrTimeout(0.5, condition));
+}
+}  // namespace dom_distiller
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 4dd78dcb..77b7009 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -112,6 +112,7 @@
     "//ios/chrome/browser/browsing_data:unit_tests",
     "//ios/chrome/browser/crash_report:unit_tests",
     "//ios/chrome/browser/device_sharing:unit_tests",
+    "//ios/chrome/browser/dom_distiller:unit_tests",
     "//ios/chrome/browser/favicon:unit_tests",
     "//ios/chrome/browser/geolocation:unit_tests",
     "//ios/chrome/browser/itunes_links:unit_tests",
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
index d33bfa43..3abbe46d 100644
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -500,8 +500,6 @@
                 status = MEDIA_CODEC_OK;
                 index = indexOrStatus;
             } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                // TODO(crbug.com/665478)
-                // assert Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT;
                 mOutputBuffers = mMediaCodec.getOutputBuffers();
                 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED;
             } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
diff --git a/media/midi/java/src/org/chromium/midi/MidiManagerAndroid.java b/media/midi/java/src/org/chromium/midi/MidiManagerAndroid.java
index e657d17..e0d208d9 100644
--- a/media/midi/java/src/org/chromium/midi/MidiManagerAndroid.java
+++ b/media/midi/java/src/org/chromium/midi/MidiManagerAndroid.java
@@ -67,8 +67,7 @@
      * @param nativeManagerPointer The native pointer to a midi::MidiManagerAndroid object.
      */
     private MidiManagerAndroid(Context context, long nativeManagerPointer) {
-        // TODO(crbug.com/665157)
-        // assert ThreadUtils.runningOnUiThread();
+        assert !ThreadUtils.runningOnUiThread();
 
         mManager = (MidiManager) context.getSystemService(Context.MIDI_SERVICE);
         mHandler = new Handler(ThreadUtils.getUiThreadLooper());
diff --git a/third_party/WebKit/LayoutTests/editing/spelling/spellcheck_test.js b/third_party/WebKit/LayoutTests/editing/spelling/spellcheck_test.js
index e221b6d..95d1035a 100644
--- a/third_party/WebKit/LayoutTests/editing/spelling/spellcheck_test.js
+++ b/third_party/WebKit/LayoutTests/editing/spelling/spellcheck_test.js
@@ -275,15 +275,6 @@
   }
 }
 
-/**
- * @param {!Document} document
- * @return {boolean}
- */
-function hasPendingSpellCheckRequest(document) {
-  return internals.lastSpellCheckRequestSequence(document) !==
-      internals.lastSpellCheckProcessedSequence(document);
-}
-
 /** @type {string} */
 const kTitle = 'title';
 /** @type {string} */
@@ -291,6 +282,46 @@
 /** @type {string} */
 const kIsSpellcheckTest = 'isSpellcheckTest';
 
+/**
+ * @param {!Test} testObject
+ * @param {!Sample} sample
+ * @param {string} expectedText
+ * @param {number} remainingRetry
+ * @param {number} retryInterval
+ */
+function verifyMarkers(
+    testObject, sample, expectedText, remainingRetry, retryInterval) {
+  assert_not_equals(
+      window.internals, undefined,
+      'window.internals is required for running automated spellcheck tests.');
+
+  /** @type {!MarkerSerializer} */
+  const serializer = new MarkerSerializer({
+    spelling: '#',
+    grammar: '~'});
+
+  try {
+    assert_equals(serializer.serialize(sample.document), expectedText);
+    testObject.done();
+  } catch (error) {
+    if (remainingRetry <= 0)
+      throw error;
+
+    // Force invoking idle time spellchecker in case it has not been run yet.
+    if (window.testRunner)
+      window.testRunner.runIdleTasks(() => {});
+
+    // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger
+    // something in JavaScript (e.g., a |Promise|), so that we can actively
+    // know the completion of spellchecking instead of passively waiting for
+    // markers to appear or disappear.
+    testObject.step_timeout(
+        () => verifyMarkers(testObject, sample, expectedText,
+                            remainingRetry - 1, retryInterval),
+        retryInterval);
+  }
+}
+
 // Spellchecker gets triggered not only by text and selection change, but also
 // by focus change. For example, misspelling markers in <INPUT> disappear when
 // the window loses focus, even though the selection does not change.
@@ -304,37 +335,6 @@
 /** @type {!Array<!Object>} */
 const testQueue = [];
 
-// We need to ensure correct usage of testRunner.runIdleTasks() that:
-// 1. We don't call runIdleTasks if another runIdleTasks is called but the
-//    callback has not been invoked yet; Otherwise, the current call is ignored.
-// 2. When the callback is invoked, we only verify test cases whose testers
-//    finished before calling runIdleTasks(); Otherwise, the idle time spell
-//    check may have not been invoked at the verification time.
-
-/** @type {boolean} */
-var runIdleTasksRequested = false;
-/**
- * @type {!Array<!Function>} Verification functions of test cases whose idle
- * idle spell checkers are requested before the current call of runIdleTasks.
- */
-var idleVerificationReadyQueue = [];
-/**
- * @type {!Array<!Function>} Verification functions of test cases whose idle
- * idle spell checkers are requested after the current call of runIdleTasks.
- */
-var idleVerificationWaitingQueue = [];
-
-function batchIdleVerification() {
-  runIdleTasksRequested = false;
-  idleVerificationReadyQueue.forEach(func => func());
-  idleVerificationReadyQueue = idleVerificationWaitingQueue;
-  idleVerificationWaitingQueue = [];
-  if (idleVerificationReadyQueue.length) {
-    runIdleTasksRequested = true;
-    testRunner.runIdleTasks(batchIdleVerification);
-  }
-}
-
 /**
  * @param {!Test} testObject
  * @param {!Sample|string} input
@@ -359,41 +359,19 @@
       assert_unreached(`Invalid tester: ${tester}`);
     }
 
-    assert_not_equals(
-        window.testRunner, undefined,
-        'window.testRunner is required for automated spellcheck tests.');
-    assert_not_equals(
-        window.internals, undefined,
-        'window.internals is required for automated spellcheck tests.');
+    /** @type {number} */
+    const kMaxRetry = 10;
+    /** @type {number} */
+    const kRetryInterval = 50;
 
-    /** @type {!Function} */
-    const verification = () => {
-      testObject.step(() => {
-        if (hasPendingSpellCheckRequest(sample.document))
-          return;
-
-        /** @type {!MarkerSerializer} */
-        const serializer = new MarkerSerializer({
-          spelling: '#',
-          grammar: '~'});
-
-        assert_equals(serializer.serialize(sample.document), expectedText);
-        testObject.done();
-      });
-    }
-
-    // Verify when all spell check requests are resolved.
-    testRunner.setSpellCheckResolvedCallback(verification);
-
-    // For tests that do not expect new markers, verify with runIdleTasks.
-    if (runIdleTasksRequested) {
-      idleVerificationWaitingQueue.push(verification);
-      return;
-    }
-
-    idleVerificationReadyQueue.push(verification);
-    runIdleTasksRequested = true;
-    testRunner.runIdleTasks(batchIdleVerification);
+    // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger
+    // something in JavaScript (e.g., a |Promise|), so that we can actively know
+    // the completion of spellchecking instead of passively waiting for markers
+    // to appear or disappear.
+    testObject.step_timeout(
+        () => verifyMarkers(testObject, sample, expectedText,
+                            kMaxRetry, kRetryInterval),
+        kRetryInterval);
   });
 }
 
@@ -416,22 +394,15 @@
     if (shouldRemoveSample)
       testObj.sample.remove();
 
-    // We may be in a spellCheckResolvedCallback here, so removing the callback
-    // (and hence, all remaining tasks) must be done asynchronously.
-    setTimeout(() => {
-      if (window.testRunner)
-        testRunner.removeSpellCheckResolvedCallback();
+    // This is the earliest timing when a new spellcheck_test can be started.
+    spellcheckTestRunning = false;
 
-      // This is the earliest timing when a new spellcheck_test can be started.
-      spellcheckTestRunning = false;
-
-      /** @type {Object} */
-      const next = testQueue.shift();
-      if (next === undefined)
-        return;
-      invokeSpellcheckTest(next.testObject, next.input,
-                           next.tester, next.expectedText);
-    }, 0);
+    /** @type {Object} */
+    const next = testQueue.shift();
+    if (next === undefined)
+      return;
+    invokeSpellcheckTest(next.testObject, next.input,
+                         next.tester, next.expectedText);
 });
 
 /**
diff --git a/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-8-expected.txt b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-8-expected.txt
new file mode 100644
index 0000000..2293822
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-8-expected.txt
@@ -0,0 +1 @@
+<html><head></head><body><div class="line-gutter-backdrop"></div><table><tbody><tr><td class="line-number" value="1"></td><td class="line-content"><span class="html-doctype">&lt;!DOCTYPE html&gt;</span></td></tr><tr><td class="line-number" value="2"></td><td class="line-content"><span class="html-tag">&lt;html&gt;</span></td></tr><tr><td class="line-number" value="3"></td><td class="line-content"><span class="html-tag">&lt;body&gt;</span></td></tr><tr><td class="line-number" value="4"></td><td class="line-content"><span class="html-tag">&lt;img <span class="html-attribute-name">src</span>="<a class="html-attribute-value html-resource-link" target="_blank" href="img.png">img.png</a>" /&gt;</span></td></tr><tr><td class="line-number" value="5"></td><td class="line-content"><span class="html-tag">&lt;img <span class="html-attribute-name">srcset</span>="<a class="html-attribute-value html-resource-link" target="_blank" href="img.png">img.png</a>,<a class="html-attribute-value html-resource-link" target="_blank" href="img2.png"> img2.png</a>" /&gt;</span></td></tr><tr><td class="line-number" value="6"></td><td class="line-content"><span class="html-tag">&lt;img <span class="html-attribute-name">src</span>="<a class="html-attribute-value html-resource-link" target="_blank" href="img.png">img.png</a>" <span class="html-attribute-name">srcset</span>="<a class="html-attribute-value html-resource-link" target="_blank" href="img.png">img.png 1x</a>,<a class="html-attribute-value html-resource-link" target="_blank" href="img2.png"> img2.png 2x</a>,<a class="html-attribute-value html-resource-link" target="_blank" href="img3.png"> img3.png 3x</a>" /&gt;</span></td></tr><tr><td class="line-number" value="7"></td><td class="line-content"><span class="html-tag">&lt;img <span class="html-attribute-name">srcset</span>="<a class="html-attribute-value html-resource-link" target="_blank" href="img.png">img.png 480w</a>,<a class="html-attribute-value html-resource-link" target="_blank" href="img2.png"> img2.png 640w</a>,<a class="html-attribute-value html-resource-link" target="_blank" href="img3.png"> img3.png 1024w</a>" /&gt;</span></td></tr><tr><td class="line-number" value="8"></td><td class="line-content"><span class="html-tag">&lt;/body&gt;</span></td></tr><tr><td class="line-number" value="9"></td><td class="line-content"><span class="html-tag">&lt;/html&gt;</span></td></tr><tr><td class="line-number" value="10"></td><td class="line-content"><span class="html-end-of-file"></span></td></tr></tbody></table></body></html>
diff --git a/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-8.html b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-8.html
new file mode 100644
index 0000000..3545290
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-8.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<body>
+<img src="img.png" />
+<img srcset="img.png, img2.png" />
+<img src="img.png" srcset="img.png 1x, img2.png 2x, img3.png 3x" />
+<img srcset="img.png 480w, img2.png 640w, img3.png 1024w" />
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-getStats-promise.html b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-getStats-promise.html
index 79e9c67e..8d24cbd4 100644
--- a/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-getStats-promise.html
+++ b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-getStats-promise.html
@@ -46,26 +46,22 @@
 }
 
 promise_test(function() {
+  let test = this;
   return navigator.mediaDevices.getUserMedia({audio:true, video:true})
     .then(function(mediaStream) {
         pc.addStream(mediaStream);
         var selector = pc.getLocalStreams()[0].getVideoTracks()[0];
         assert_not_equals(selector, null);
-        return pc.getStats(selector)
-          .then(function(report) {
-              assert_expected_report(report);
-            });
+        return promise_rejects(test, new TypeError(), pc.getStats(selector));
       });
 }, 'getStats(MediaStreamTrack selector)');
 
 promise_test(function() {
+  let test = this;
   return navigator.mediaDevices.getUserMedia({audio:true, video:true})
     .then(function(mediaStream) {
         pc.addStream(mediaStream);
-        return pc.getStats(null)
-          .then(function(report) {
-              assert_expected_report(report);
-            });
+        return promise_rejects(test, new TypeError(), pc.getStats(null));
       });
 }, 'getStats(null)');
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h
index 4387453..eaaeacd 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h
@@ -126,12 +126,23 @@
     // objects or if we are outside of object construction.
     if (!IsGarbageCollectedMixin<T>::value ||
         !threadState->isMixinInConstruction()) {
+      // If the wrapper is already marked we can bail out here.
       if (TraceTrait<T>::heapObjectHeader(dstObject)->isWrapperHeaderMarked())
         return;
+      // Otherwise, eagerly mark the wrapper header and put the object on the
+      // marking deque for further processing.
+      WrapperVisitor* const visitor = currentVisitor(threadState->isolate());
+      TraceTrait<T>::markWrapperNoTracing(visitor, dstObject);
+      visitor->pushToMarkingDeque(TraceTrait<T>::traceMarkedWrapper,
+                                  TraceTrait<T>::heapObjectHeader, dstObject);
+      return;
     }
 
+    // We cannot eagerly mark the wrapper header because of mixin
+    // construction. Delay further processing until AdvanceMarking, which has to
+    // be in a non-construction state. This path may result in duplicates.
     currentVisitor(threadState->isolate())
-        ->pushToMarkingDeque(TraceTrait<T>::markWrapper,
+        ->pushToMarkingDeque(TraceTrait<T>::markAndTraceWrapper,
                              TraceTrait<T>::heapObjectHeader, dstObject);
   }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp
index 0442037..15cad2e 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp
@@ -188,7 +188,7 @@
   ScriptWrappableVisitor* visitor =
       V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor();
   visitor->pushToMarkingDeque(
-      TraceTrait<DeathAwareScriptWrappable>::markWrapper,
+      TraceTrait<DeathAwareScriptWrappable>::markAndTraceWrapper,
       TraceTrait<DeathAwareScriptWrappable>::heapObjectHeader, object);
 
   EXPECT_EQ(visitor->getMarkingDeque()->first().rawObjectPointer(), object);
@@ -282,6 +282,7 @@
 
   visitor->getMarkingDeque()->clear();
   visitor->getVerifierDeque()->clear();
+  visitor->getHeadersToUnmark()->clear();
 }
 
 namespace {
diff --git a/third_party/WebKit/Source/core/frame/DOMWindowProperty.h b/third_party/WebKit/Source/core/frame/DOMWindowProperty.h
index 06257b3..283f23b 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindowProperty.h
+++ b/third_party/WebKit/Source/core/frame/DOMWindowProperty.h
@@ -37,7 +37,7 @@
  public:
   explicit DOMWindowProperty(LocalFrame*);
 
-  virtual void frameDestroyed();
+  void frameDestroyed();
 
   LocalFrame* frame() const { return m_frame; }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp b/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp
index f385cd8..1187e24 100644
--- a/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp
@@ -162,9 +162,13 @@
     index = addRange(source, index,
                      iter->valueRange().start - token.startIndex(), emptyAtom);
 
-    bool isLink = name == srcAttr || name == hrefAttr;
-    index = addRange(source, index, iter->valueRange().end - token.startIndex(),
-                     "html-attribute-value", isLink, tagName == aTag, value);
+    if (name == srcsetAttr) {
+        index = addSrcset(source, index, iter->valueRange().end - token.startIndex());
+    } else {
+        bool isLink = name == srcAttr || name == hrefAttr;
+        index = addRange(source, index, iter->valueRange().end - token.startIndex(),
+                         "html-attribute-value", isLink, tagName == aTag, value);
+    }
 
     ++iter;
   }
@@ -312,6 +316,30 @@
   return anchor;
 }
 
+int HTMLViewSourceDocument::addSrcset(const String& source,
+                                     int start,
+                                     int end) {
+  String srcset = source.substring(start, end-start);
+  Vector<String> srclist;
+  srcset.split(',', true, srclist);
+  unsigned size = srclist.size();
+  for (unsigned i = 0; i < size; i++) {
+    Vector<String> tmp;
+    srclist[i].split(' ', tmp);
+    if (tmp.size() > 0) {
+      AtomicString link(tmp[0]);
+      m_current = addLink(link, false);
+      addText(srclist[i], "html-attribute-value");
+      m_current = toElement(m_current->parentNode());
+    } else {
+      addText(srclist[i], "html-attribute-value");
+    }
+    if (i + 1 < size)
+      addText(",", "html-attribute-value");
+  }
+  return end;
+}
+
 void HTMLViewSourceDocument::maybeAddSpanForAnnotation(
     SourceAnnotation annotation) {
   if (annotation == AnnotateSourceAsXSS) {
diff --git a/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h b/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h
index bac36aa..daa2a87 100644
--- a/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h
+++ b/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h
@@ -74,6 +74,9 @@
                bool isLink = false,
                bool isAnchor = false,
                const AtomicString& link = nullAtom);
+  int addSrcset(const String& source,
+               int start,
+               int end);
   void maybeAddSpanForAnnotation(SourceAnnotation);
 
   Element* addLink(const AtomicString& url, bool isAnchor);
diff --git a/third_party/WebKit/Source/devtools/.gitignore b/third_party/WebKit/Source/devtools/.gitignore
index 49b6d02..46c94cb 100644
--- a/third_party/WebKit/Source/devtools/.gitignore
+++ b/third_party/WebKit/Source/devtools/.gitignore
@@ -1,5 +1,6 @@
 *.Makefile
 *.mk
+*.pyc
 *.rules
 *.sln
 *.tmp
@@ -16,4 +17,4 @@
 /scripts/local_node/runtimes
 /front_end/protocol_externs.js
 /front_end/InspectorBackendCommands.js
-/front_end/SupportedCSSProperties.js
\ No newline at end of file
+/front_end/SupportedCSSProperties.js
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js b/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
index 75cde63..f9f4664 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
@@ -39,17 +39,16 @@
   constructor(name, visibleByDefault) {
     super();
     this.registerRequiredCSS('ui/filter.css');
-    this._filtersShown = false;
     this._enabled = true;
     this.element.classList.add('filter-bar');
 
-    this._filterButton = new UI.ToolbarToggle(Common.UIString('Filter'), 'largeicon-filter');
-    this._filterButton.addEventListener(UI.ToolbarButton.Events.Click, this._handleFilterButtonClick, this);
+    this._stateSetting = Common.settings.createSetting('filterBar-' + name + '-toggled', !!visibleByDefault);
+    this._filterButton = new UI.ToolbarSettingToggle(this._stateSetting, 'largeicon-filter', Common.UIString('Filter'));
 
     this._filters = [];
 
-    this._stateSetting = Common.settings.createSetting('filterBar-' + name + '-toggled', !!visibleByDefault);
-    this._setState(this._stateSetting.get());
+    this._updateFilterBar();
+    this._stateSetting.addChangeListener(this._updateFilterBar.bind(this));
   }
 
   /**
@@ -81,27 +80,30 @@
   }
 
   /**
-   * @override
-   */
-  wasShown() {
-    this._updateFilterBar();
-  }
-
-  /**
    * @param {!Common.Event} event
    */
   _filterChanged(event) {
     this._updateFilterButton();
   }
 
+  /**
+   * @override
+   */
+  wasShown() {
+    super.wasShown();
+    this._updateFilterBar();
+  }
+
   _updateFilterBar() {
     if (!this.parentWidget())
       return;
-    var visible = this._alwaysShowFilters || (this._filtersShown && this._enabled);
-    if (visible)
+    var visible = this._alwaysShowFilters || (this._stateSetting.get() && this._enabled);
+    if (visible) {
       this.showWidget();
-    else
+      this._focusTextField();
+    } else {
       this.hideWidget();
+    }
   }
 
   _focusTextField() {
@@ -115,41 +117,11 @@
   }
 
   _updateFilterButton() {
-    if (this._filtersShown) {
-      this._filterButton.setToggled(true);
-      this._filterButton.setToggleWithRedColor(false);
-      return;
-    }
-    this._filterButton.setToggleWithRedColor(true);
     var isActive = false;
     for (var filter of this._filters)
       isActive = isActive || filter.isActive();
-    this._filterButton.setToggled(isActive);
-  }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _handleFilterButtonClick(event) {
-    this._setState(!this._filtersShown);
-  }
-
-  /**
-   * @param {boolean} filtersShown
-   */
-  _setState(filtersShown) {
-    if (this._filtersShown === filtersShown)
-      return;
-
-    this._filtersShown = filtersShown;
-    if (this._stateSetting)
-      this._stateSetting.set(filtersShown);
-
-    this._updateFilterButton();
-    this._updateFilterBar();
-    if (this._filtersShown)
-      this._focusTextField();
-    this.dispatchEventToListeners(UI.FilterBar.Events.Toggled);
+    this._filterButton.setDefaultWithRedColor(isActive);
+    this._filterButton.setToggleWithRedColor(isActive);
   }
 
   clear() {
@@ -165,11 +137,6 @@
   Shown: 'on'
 };
 
-/** @enum {symbol} */
-UI.FilterBar.Events = {
-  Toggled: Symbol('Toggled')
-};
-
 /**
  * @interface
  * @extends {Common.EventTarget}
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
index 7645e41..de940f2e 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
@@ -1147,8 +1147,7 @@
   return promise;
 }
 
-ScriptPromise RTCPeerConnection::getStats(ScriptState* scriptState,
-                                          MediaStreamTrack* selector) {
+ScriptPromise RTCPeerConnection::getStats(ScriptState* scriptState) {
   ExecutionContext* context = scriptState->getExecutionContext();
   UseCounter::count(context, UseCounter::RTCPeerConnectionGetStats);
 
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
index 443aa91..746fba4 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
@@ -147,7 +147,7 @@
   ScriptPromise getStats(ScriptState*,
                          RTCStatsCallback* successCallback,
                          MediaStreamTrack* selector = nullptr);
-  ScriptPromise getStats(ScriptState*, MediaStreamTrack* selector = nullptr);
+  ScriptPromise getStats(ScriptState*);
 
   RTCDataChannel* createDataChannel(ExecutionContext*,
                                     String label,
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.idl b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.idl
index de9f6a4..8394fc8f 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.idl
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.idl
@@ -107,7 +107,10 @@
     // non-optional) argument, and there should be a third failureCallback
     // argument.
     [CallWith=ScriptState, LegacyInterfaceTypeChecking] Promise<void> getStats(RTCStatsCallback successCallback, optional MediaStreamTrack? selector);
-    [CallWith=ScriptState, RuntimeEnabled=RTCPeerConnectionNewGetStats] Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector);
+    // TODO(hbos): The spec has an optional |selector| argument that is not
+    // supported yet. There is a discussion about what to do with it (clarify
+    // spec, remove it or change it?): https://github.com/w3c/webrtc-stats/issues/116
+    [CallWith=ScriptState, RuntimeEnabled=RTCPeerConnectionNewGetStats] Promise<RTCStatsReport> getStats();
 
     // https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api
     // TODO(guidou): The label argument should have [TreatNullAs=EmptyString]
diff --git a/third_party/WebKit/Source/platform/heap/GarbageCollected.h b/third_party/WebKit/Source/platform/heap/GarbageCollected.h
index 42f78a3..e814c8c0 100644
--- a/third_party/WebKit/Source/platform/heap/GarbageCollected.h
+++ b/third_party/WebKit/Source/platform/heap/GarbageCollected.h
@@ -77,7 +77,9 @@
   virtual void trace(Visitor*) {}
   virtual void adjustAndMark(InlinedGlobalMarkingVisitor) const = 0;
   virtual void trace(InlinedGlobalMarkingVisitor);
-  virtual void adjustAndMarkWrapper(const WrapperVisitor*) const = 0;
+  virtual void adjustAndMarkAndTraceWrapper(const WrapperVisitor*) const = 0;
+  virtual void adjustAndMarkWrapperNoTracing(const WrapperVisitor*) const = 0;
+  virtual void adjustAndTraceMarkedWrapper(const WrapperVisitor*) const = 0;
   virtual bool isHeapObjectAlive() const = 0;
   virtual HeapObjectHeader* adjustAndGetHeapObjectHeader() const = 0;
 };
@@ -102,29 +104,45 @@
                                                                               \
  private:
 
-#define DEFINE_GARBAGE_COLLECTED_MIXIN_WRAPPER_METHODS(TYPE)                  \
- public:                                                                      \
-  void adjustAndMarkWrapper(const WrapperVisitor* visitor) const override {   \
-    typedef WTF::IsSubclassOfTemplate<typename std::remove_const<TYPE>::type, \
-                                      blink::GarbageCollected>                \
-        IsSubclassOfGarbageCollected;                                         \
-    static_assert(                                                            \
-        IsSubclassOfGarbageCollected::value,                                  \
-        "only garbage collected objects can have garbage collected mixins");  \
-    AdjustAndMarkTrait<TYPE>::markWrapper(visitor,                            \
-                                          static_cast<const TYPE*>(this));    \
-  }                                                                           \
-  HeapObjectHeader* adjustAndGetHeapObjectHeader() const override {           \
-    typedef WTF::IsSubclassOfTemplate<typename std::remove_const<TYPE>::type, \
-                                      blink::GarbageCollected>                \
-        IsSubclassOfGarbageCollected;                                         \
-    static_assert(                                                            \
-        IsSubclassOfGarbageCollected::value,                                  \
-        "only garbage collected objects can have garbage collected mixins");  \
-    return AdjustAndMarkTrait<TYPE>::heapObjectHeader(                        \
-        static_cast<const TYPE*>(this));                                      \
-  }                                                                           \
-                                                                              \
+#define DEFINE_GARBAGE_COLLECTED_MIXIN_WRAPPER_METHODS(TYPE)                 \
+ private:                                                                    \
+  typedef WTF::IsSubclassOfTemplate<typename std::remove_const<TYPE>::type,  \
+                                    blink::GarbageCollected>                 \
+      IsSubclassOfGarbageCollected;                                          \
+                                                                             \
+ public:                                                                     \
+  void adjustAndMarkAndTraceWrapper(const WrapperVisitor* visitor)           \
+      const override {                                                       \
+    static_assert(                                                           \
+        IsSubclassOfGarbageCollected::value,                                 \
+        "only garbage collected objects can have garbage collected mixins"); \
+    return AdjustAndMarkTrait<TYPE>::markAndTraceWrapper(                    \
+        visitor, static_cast<const TYPE*>(this));                            \
+  }                                                                          \
+  void adjustAndMarkWrapperNoTracing(const WrapperVisitor* visitor)          \
+      const override {                                                       \
+    static_assert(                                                           \
+        IsSubclassOfGarbageCollected::value,                                 \
+        "only garbage collected objects can have garbage collected mixins"); \
+    return AdjustAndMarkTrait<TYPE>::markWrapperNoTracing(                   \
+        visitor, static_cast<const TYPE*>(this));                            \
+  }                                                                          \
+  void adjustAndTraceMarkedWrapper(const WrapperVisitor* visitor)            \
+      const override {                                                       \
+    static_assert(                                                           \
+        IsSubclassOfGarbageCollected::value,                                 \
+        "only garbage collected objects can have garbage collected mixins"); \
+    AdjustAndMarkTrait<TYPE>::traceMarkedWrapper(                            \
+        visitor, static_cast<const TYPE*>(this));                            \
+  }                                                                          \
+  HeapObjectHeader* adjustAndGetHeapObjectHeader() const override {          \
+    static_assert(                                                           \
+        IsSubclassOfGarbageCollected::value,                                 \
+        "only garbage collected objects can have garbage collected mixins"); \
+    return AdjustAndMarkTrait<TYPE>::heapObjectHeader(                       \
+        static_cast<const TYPE*>(this));                                     \
+  }                                                                          \
+                                                                             \
  private:
 
 // A C++ object's vptr will be initialized to its leftmost base's vtable after
diff --git a/third_party/WebKit/Source/platform/heap/TraceTraits.h b/third_party/WebKit/Source/platform/heap/TraceTraits.h
index a56ccf1..8e37a659 100644
--- a/third_party/WebKit/Source/platform/heap/TraceTraits.h
+++ b/third_party/WebKit/Source/platform/heap/TraceTraits.h
@@ -47,12 +47,24 @@
   STATIC_ONLY(AdjustAndMarkTrait);
 
  public:
-  static void markWrapper(const WrapperVisitor* visitor, const T* t) {
+  static void markAndTraceWrapper(const WrapperVisitor* visitor, const T* t) {
     if (visitor->markWrapperHeader(heapObjectHeader(t))) {
       visitor->markWrappersInAllWorlds(t);
       visitor->dispatchTraceWrappers(t);
     }
   }
+  static void markWrapperNoTracing(const WrapperVisitor* visitor, const T* t) {
+    DCHECK(!heapObjectHeader(t)->isWrapperHeaderMarked());
+    visitor->markWrapperHeader(heapObjectHeader(t));
+  }
+  static void traceMarkedWrapper(const WrapperVisitor* visitor, const T* t) {
+    DCHECK(heapObjectHeader(t)->isWrapperHeaderMarked());
+    // The term *mark* is misleading here as we effectively trace through the
+    // API boundary, i.e., tell V8 that an object is alive. Actual marking
+    // will be done in V8.
+    visitor->markWrappersInAllWorlds(t);
+    visitor->dispatchTraceWrappers(t);
+  }
   static HeapObjectHeader* heapObjectHeader(const T* t) {
     return HeapObjectHeader::fromPayload(t);
   }
@@ -99,8 +111,14 @@
   STATIC_ONLY(AdjustAndMarkTrait);
 
  public:
-  static void markWrapper(const WrapperVisitor* visitor, const T* t) {
-    t->adjustAndMarkWrapper(visitor);
+  static void markAndTraceWrapper(const WrapperVisitor* visitor, const T* t) {
+    t->adjustAndMarkAndTraceWrapper(visitor);
+  }
+  static void markWrapperNoTracing(const WrapperVisitor* visitor, const T* t) {
+    t->adjustAndMarkWrapperNoTracing(visitor);
+  }
+  static void traceMarkedWrapper(const WrapperVisitor* visitor, const T* t) {
+    t->adjustAndTraceMarkedWrapper(visitor);
   }
   static HeapObjectHeader* heapObjectHeader(const T* t) {
     return t->adjustAndGetHeapObjectHeader();
@@ -205,11 +223,28 @@
   static void trace(Visitor*, void* self);
   static void trace(InlinedGlobalMarkingVisitor, void* self);
 
-  static void markWrapper(const WrapperVisitor* visitor, const void* t) {
+  static void markAndTraceWrapper(const WrapperVisitor* visitor,
+                                  const void* t) {
     static_assert(CanTraceWrappers<T>::value,
                   "T should be able to trace wrappers. See "
                   "dispatchTraceWrappers in WrapperVisitor.h");
-    AdjustAndMarkTrait<T>::markWrapper(visitor, reinterpret_cast<const T*>(t));
+    AdjustAndMarkTrait<T>::markAndTraceWrapper(visitor,
+                                               reinterpret_cast<const T*>(t));
+  }
+  static void markWrapperNoTracing(const WrapperVisitor* visitor,
+                                   const void* t) {
+    static_assert(CanTraceWrappers<T>::value,
+                  "T should be able to trace wrappers. See "
+                  "dispatchTraceWrappers in WrapperVisitor.h");
+    AdjustAndMarkTrait<T>::markWrapperNoTracing(visitor,
+                                                reinterpret_cast<const T*>(t));
+  }
+  static void traceMarkedWrapper(const WrapperVisitor* visitor, const void* t) {
+    static_assert(CanTraceWrappers<T>::value,
+                  "T should be able to trace wrappers. See "
+                  "dispatchTraceWrappers in WrapperVisitor.h");
+    AdjustAndMarkTrait<T>::traceMarkedWrapper(visitor,
+                                              reinterpret_cast<const T*>(t));
   }
   static HeapObjectHeader* heapObjectHeader(const void* t) {
     static_assert(CanTraceWrappers<T>::value,
diff --git a/third_party/WebKit/Source/platform/heap/WrapperVisitor.h b/third_party/WebKit/Source/platform/heap/WrapperVisitor.h
index f85668a..6315aad 100644
--- a/third_party/WebKit/Source/platform/heap/WrapperVisitor.h
+++ b/third_party/WebKit/Source/platform/heap/WrapperVisitor.h
@@ -93,10 +93,9 @@
   template <typename T>
   void traceWrappers(const T* traceable) const {
     static_assert(sizeof(T), "T must be fully defined");
-    // Ideally, we'd assert that we can cast to TraceWrapperBase here.
-    static_assert(
-        IsGarbageCollectedType<T>::value,
-        "Only garbage collected objects can be used in traceWrappers().");
+    static_assert(CanTraceWrappers<T>::value,
+                  "T should be able to trace wrappers. See "
+                  "dispatchTraceWrappers in WrapperVisitor.h");
 
     if (!traceable) {
       return;
@@ -106,7 +105,8 @@
       return;
     }
 
-    pushToMarkingDeque(TraceTrait<T>::markWrapper,
+    TraceTrait<T>::markWrapperNoTracing(this, traceable);
+    pushToMarkingDeque(TraceTrait<T>::traceMarkedWrapper,
                        TraceTrait<T>::heapObjectHeader, traceable);
   }