diff --git a/DEPS b/DEPS
index 0ba78fe..fd55e29 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': '266b05464b10b98ac2cccfe44d83ad428e2b8162',
+  'v8_revision': 'ae09c747d60152f286b665eafd702cd1ef2d5827',
   # 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.
@@ -232,7 +232,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'eed2ae257f91a209b6fbe313903aec83250a6a63', # commit position 16296
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '8ff7cecc5bc21065d2ca7ae4b65a2f28887466e0', # commit position 16354
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/build/config/android/BUILD.gn b/build/config/android/BUILD.gn
index 27000347..73c49f4 100644
--- a/build/config/android/BUILD.gn
+++ b/build/config/android/BUILD.gn
@@ -30,7 +30,7 @@
     rebased_android_toolchain_root =
         rebase_path(android_toolchain_root, root_build_dir)
     assert(rebased_android_toolchain_root != "")  # Mark as used.
-    if (current_cpu == "mipsel" || current_cpu == "mips64el") {
+    if (current_cpu == "mips64el") {
       cflags += [
         # TODO(gordanac) Enable integrated-as.
         "-fno-integrated-as",
diff --git a/chromeos/dbus/fake_auth_policy_client.cc b/chromeos/dbus/fake_auth_policy_client.cc
index 4f3a35de..08a46b2 100644
--- a/chromeos/dbus/fake_auth_policy_client.cc
+++ b/chromeos/dbus/fake_auth_policy_client.cc
@@ -12,6 +12,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_split.h"
 #include "base/task_scheduler/post_task.h"
+#include "base/threading/platform_thread.h"
 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
 #include "chromeos/chromeos_paths.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
@@ -28,11 +29,17 @@
 const size_t kMaxMachineNameLength = 15;
 const char kInvalidMachineNameCharacters[] = "\\/:*?\"<>|";
 
+// Delay policy fetch to be more realistic.
+constexpr int kPolicyFetchDelaySeconds = 5;
+
 // Drop stub policy file of |policy_type| at |policy_path| containing
 // |serialized_payload|.
 bool WritePolicyFile(const base::FilePath& policy_path,
                      const std::string& serialized_payload,
                      const std::string& policy_type) {
+  base::PlatformThread::Sleep(
+      base::TimeDelta::FromSeconds(kPolicyFetchDelaySeconds));
+
   em::PolicyData data;
   data.set_policy_value(serialized_payload);
   data.set_policy_type(policy_type);
diff --git a/components/cronet/ios/cronet_environment.mm b/components/cronet/ios/cronet_environment.mm
index f8f794a..68d09a3 100644
--- a/components/cronet/ios/cronet_environment.mm
+++ b/components/cronet/ios/cronet_environment.mm
@@ -311,9 +311,9 @@
 
   context_builder.set_host_resolver(std::move(mapped_host_resolver));
 
-  std::unique_ptr<net::CookieStore> cookie_store(
-      net::CookieStoreIOS::CreateCookieStore(
-          [NSHTTPCookieStorage sharedHTTPCookieStorage]));
+  std::unique_ptr<net::CookieStore> cookie_store =
+      base::MakeUnique<CookieStoreIOS>(
+          [NSHTTPCookieStorage sharedHTTPCookieStorage]);
   context_builder.SetCookieAndChannelIdStores(std::move(cookie_store), nullptr);
 
   std::unordered_set<std::string> quic_host_whitelist;
diff --git a/components/password_manager/core/browser/log_router_unittest.cc b/components/password_manager/core/browser/log_router_unittest.cc
index 1af1bf4..b4ab911 100644
--- a/components/password_manager/core/browser/log_router_unittest.cc
+++ b/components/password_manager/core/browser/log_router_unittest.cc
@@ -120,7 +120,7 @@
   EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
   // The manager should be told the LogRouter has some receivers.
   EXPECT_TRUE(router.RegisterManager(&manager_));
-  // Now unregister the reciever. The manager should be told the LogRouter has
+  // Now unregister the receiver. The manager should be told the LogRouter has
   // no receivers.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(false));
   router.UnregisterReceiver(&receiver_);
@@ -137,7 +137,7 @@
   EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
   // Now unregister the manager.
   router.UnregisterManager(&manager_);
-  // Now unregister the reciever. The manager should not hear about it.
+  // Now unregister the receiver. The manager should not hear about it.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(_)).Times(0);
   router.UnregisterReceiver(&receiver_);
 }
@@ -153,10 +153,10 @@
   // Now register the 2nd receiver. The manager should not be notified.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(true)).Times(0);
   EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver2_));
-  // Now unregister the 1st reciever. The manager should not hear about it.
+  // Now unregister the 1st receiver. The manager should not hear about it.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(false)).Times(0);
   router.UnregisterReceiver(&receiver_);
-  // Now unregister the 2nd reciever. The manager should hear about it.
+  // Now unregister the 2nd receiver. The manager should hear about it.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(false));
   router.UnregisterReceiver(&receiver2_);
   // Now unregister the manager.
diff --git a/ios/chrome/browser/net/cookie_util.mm b/ios/chrome/browser/net/cookie_util.mm
index 424a107a..fe48775 100644
--- a/ios/chrome/browser/net/cookie_util.mm
+++ b/ios/chrome/browser/net/cookie_util.mm
@@ -13,7 +13,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/net/cookies/cookie_store_ios.h"
+#include "ios/net/cookies/cookie_store_ios_persistent.h"
 #include "ios/web/public/web_thread.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/cookies/cookie_store.h"
@@ -96,7 +96,8 @@
         config.path, true /* restore_old_session_cookies */,
         config.crypto_delegate);
   }
-  return base::MakeUnique<net::CookieStoreIOS>(persistent_store.get());
+  return base::MakeUnique<net::CookieStoreIOSPersistent>(
+      persistent_store.get());
 }
 
 bool ShouldClearSessionCookies() {
diff --git a/ios/chrome/browser/payments/payment_request_manager.h b/ios/chrome/browser/payments/payment_request_manager.h
index 317169d..9a7d9e72 100644
--- a/ios/chrome/browser/payments/payment_request_manager.h
+++ b/ios/chrome/browser/payments/payment_request_manager.h
@@ -37,7 +37,7 @@
 - (instancetype)init NS_UNAVAILABLE;
 
 // Sets the WebState to be observed for invocations of the Payment Request API.
-// |webState|'s lifetime should be greater than the reciever's. |webState| can
+// |webState|'s lifetime should be greater than the receiver's. |webState| can
 // be nil.
 - (void)setWebState:(web::WebState*)webState;
 
diff --git a/ios/chrome/browser/sessions/session_service.h b/ios/chrome/browser/sessions/session_service.h
index c80740fd..661b677 100644
--- a/ios/chrome/browser/sessions/session_service.h
+++ b/ios/chrome/browser/sessions/session_service.h
@@ -23,7 +23,7 @@
 @property(nonatomic, readonly) ios::ChromeBrowserState* browserState;
 
 // Inits exactly as initForReadingWithData: does, additionally setting
-// |browserState| on the reciever.
+// |browserState| on the receiver.
 - (instancetype)initForReadingWithData:(NSData*)data
                           browserState:(ios::ChromeBrowserState*)browserState;
 
diff --git a/ios/chrome/browser/sessions/session_service.mm b/ios/chrome/browser/sessions/session_service.mm
index 6aaf7d9e..806b528 100644
--- a/ios/chrome/browser/sessions/session_service.mm
+++ b/ios/chrome/browser/sessions/session_service.mm
@@ -188,7 +188,7 @@
     [NSObject cancelPreviousPerformRequestsWithTarget:self];
     [self performSaveToDirectoryInBackground:stashPath];
   } else if (!pendingSession) {
-    // If there wasn't previously a delayed save pending for |stashPath}|,
+    // If there wasn't previously a delayed save pending for |stashPath|,
     // enqueue one now.
     [self performSelector:@selector(performSaveToDirectoryInBackground:)
                withObject:stashPath
diff --git a/ios/chrome/browser/sessions/session_window.h b/ios/chrome/browser/sessions/session_window.h
index e2b838d..0e4615d 100644
--- a/ios/chrome/browser/sessions/session_window.h
+++ b/ios/chrome/browser/sessions/session_window.h
@@ -21,9 +21,9 @@
 // initialized "empty" (without any sessions) and sessions are added one at a
 // time.  For example:
 //  SessionWindowIOS* window = [[SessionWindow alloc] init];
-//  [window addSession:session_storage];
+//  [window addSerializedSession:session_storage];
 //  ...
-//  [window setSelectedInex:mySelectedIndex];
+//  [window setSelectedIndex:mySelectedIndex];
 - (void)addSerializedSession:(CRWNavigationManagerStorage*)session;
 
 // Clears all added sessions.
diff --git a/ios/chrome/browser/ui/contextual_search/contextual_search_controller.h b/ios/chrome/browser/ui/contextual_search/contextual_search_controller.h
index 5b30b3ce..f7a97da 100644
--- a/ios/chrome/browser/ui/contextual_search/contextual_search_controller.h
+++ b/ios/chrome/browser/ui/contextual_search/contextual_search_controller.h
@@ -97,7 +97,7 @@
                                          delegate;
 
 // Set the Tab to be used as the opener for the search results tab. |opener|'s
-// lifetime should be greater than the reciever's. |opener| can be nil.
+// lifetime should be greater than the receiver's. |opener| can be nil.
 - (void)setTab:(Tab*)tab;
 
 // Enable or disable contextual search for the current WebState. If
diff --git a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h
index 8cb8fe0d..9cacede 100644
--- a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h
+++ b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h
@@ -10,7 +10,7 @@
 @interface UILabel (CRUILabelAttributeUtils)
 @property(nonatomic, assign, setter=cr_setLineHeight:) CGFloat cr_lineHeight;
 
-// Adjusts the line height of the reciever so that the lines will evenly f
+// Adjusts the line height of the receiver so that the lines will evenly f
 - (void)cr_adjustLineHeightForMaximimumLines:(NSUInteger)maximumLines;
 
 @end
diff --git a/ios/clean/chrome/browser/browser_coordinator+internal.h b/ios/clean/chrome/browser/browser_coordinator+internal.h
index 32e1541..95197cc 100644
--- a/ios/clean/chrome/browser/browser_coordinator+internal.h
+++ b/ios/clean/chrome/browser/browser_coordinator+internal.h
@@ -59,7 +59,7 @@
 
 // Returns YES if the receiver will take |overlayCoordinator| as a child.
 // The default is to return YES only if the receiver has no children, if
-// the reciever has a nil -overlayCoordinator, and if |overlayCoordinator|
+// the receiver has a nil -overlayCoordinator, and if |overlayCoordinator|
 // is not already overlaying.
 - (BOOL)canAddOverlayCoordinator:(BrowserCoordinator*)overlayCoordinator;
 
@@ -67,7 +67,7 @@
 // added, recursively add it to the receiver's child. If a receiver has
 // multiple children and returns YES from -canAddOverlayCoordinator:, it
 // must override this method to determines how the overlay is added.
-// If neither the reciever or any child can add |overlayCoordinator|, then
+// If neither the receiver or any child can add |overlayCoordinator|, then
 // nothing happens.
 - (void)addOverlayCoordinator:(BrowserCoordinator*)overlayCoordinator;
 
diff --git a/ios/crnet/crnet_environment.mm b/ios/crnet/crnet_environment.mm
index 1c0ed42..94572a2 100644
--- a/ios/crnet/crnet_environment.mm
+++ b/ios/crnet/crnet_environment.mm
@@ -477,7 +477,7 @@
   main_context_->set_http_transaction_factory(main_cache);
 
   // Cookies
-  cookie_store_ = net::CookieStoreIOS::CreateCookieStore(
+  cookie_store_ = base::MakeUnique<CookieStoreIOS>(
       [NSHTTPCookieStorage sharedHTTPCookieStorage]);
   main_context_->set_cookie_store(cookie_store_.get());
 
diff --git a/ios/net/BUILD.gn b/ios/net/BUILD.gn
index 90c6225..818ee63 100644
--- a/ios/net/BUILD.gn
+++ b/ios/net/BUILD.gn
@@ -32,6 +32,8 @@
     "cookies/cookie_store_ios.mm",
     "cookies/cookie_store_ios_client.h",
     "cookies/cookie_store_ios_client.mm",
+    "cookies/cookie_store_ios_persistent.h",
+    "cookies/cookie_store_ios_persistent.mm",
     "cookies/system_cookie_util.h",
     "cookies/system_cookie_util.mm",
     "crn_http_protocol_handler.h",
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h
index 4ef0d6e..fd42187 100644
--- a/ios/net/cookies/cookie_store_ios.h
+++ b/ios/net/cookies/cookie_store_ios.h
@@ -41,36 +41,32 @@
 
 // The CookieStoreIOS is an implementation of CookieStore relying on
 // NSHTTPCookieStorage, ensuring that the cookies are consistent between the
-// network stack and NSHTTPCookieStorage.
-// CookieStoreIOS is not thread safe.
+// network stack and NSHTTPCookieStorage. CookieStoreIOS is not thread safe.
 //
-// CookieStoreIOS can be created synchronized with the system cookie store (via
-// CreateCookieStore) or not (other constructors). If a CookieStoreIOS is not
-// synchronized with the system store, changes are written back to the backing
-// CookieStore. If a CookieStoreIOS is synchronized with the system store,
+// CookieStoreIOS is created synchronized with the system cookie store -
 // changes are written directly to the system cookie store, then propagated to
 // the backing store by OnSystemCookiesChanged, which is called by the system
 // store once the change to the system store is written back.
+// For not synchronized CookieStore, please see CookieStoreIOSPersistent.
 class CookieStoreIOS : public net::CookieStore,
                        public CookieNotificationObserver {
  public:
-  // Creates a CookieStoreIOS with a default value of
-  // |NSHTTPCookieStorage sharedCookieStorage| as the system's cookie store.
-  explicit CookieStoreIOS(
-      net::CookieMonster::PersistentCookieStore* persistent_store);
-
-  ~CookieStoreIOS() override;
-
-  enum CookiePolicy { ALLOW, BLOCK };
-
-  // Create an instance of CookieStoreIOS that is generated from the cookies
+  // Creates an instance of CookieStoreIOS that is generated from the cookies
   // stored in |cookie_storage|. The CookieStoreIOS uses the |cookie_storage|
   // as its default backend and is initially synchronized with it.
   // Apple does not persist the cookies' creation dates in NSHTTPCookieStorage,
   // so callers should not expect these values to be populated.
+  explicit CookieStoreIOS(NSHTTPCookieStorage* cookie_storage);
+
+  // Creates a CookieStoreIOS with NSHTTPCookieStorage backend.
+  // TODO(crbug.com/683964): Remove this method.
   static std::unique_ptr<CookieStoreIOS> CreateCookieStore(
       NSHTTPCookieStorage* cookie_storage);
 
+  ~CookieStoreIOS() override;
+
+  enum CookiePolicy { ALLOW, BLOCK };
+
   // Must be called when the state of
   // |NSHTTPCookieStorage sharedHTTPCookieStorage| changes.
   // Affects only those CookieStoreIOS instances that are backed by
@@ -130,21 +126,28 @@
 
   bool IsEphemeral() override;
 
+ protected:
+  CookieStoreIOS(net::CookieMonster::PersistentCookieStore* persistent_store,
+                 NSHTTPCookieStorage* system_store);
+
+  // These three functions are used for wrapping user-supplied callbacks given
+  // to CookieStoreIOS mutator methods. Given a callback, they return a new
+  // callback that invokes UpdateCachesFromCookieMonster() to schedule an
+  // asynchronous synchronization of the cookie cache and then calls the
+  // original callback.
+  SetCookiesCallback WrapSetCallback(const SetCookiesCallback& callback);
+  DeleteCallback WrapDeleteCallback(const DeleteCallback& callback);
+  base::Closure WrapClosure(const base::Closure& callback);
+
+  bool metrics_enabled() { return metrics_enabled_; }
+
+  net::CookieMonster* cookie_monster() { return cookie_monster_.get(); }
+
+  const base::ThreadChecker& thread_checker() { return thread_checker_; }
+
  private:
-  CookieStoreIOS(
-      net::CookieMonster::PersistentCookieStore* persistent_store,
-      NSHTTPCookieStorage* system_store);
-
-  // For tests.
-  friend struct CookieStoreIOSTestTraits;
-
-  enum SynchronizationState {
-    NOT_SYNCHRONIZED,  // Uses CookieMonster as backend.
-    SYNCHRONIZED       // Uses NSHTTPCookieStorage as backend.
-  };
-
-  // Cookie fliter for DeleteCookiesWithFilter().
-  // Takes a cookie and a creation time and returns true if the cookie must be
+  // Cookie filter for DeleteCookiesWithFilter().
+  // Takes a cookie and a creation time and returns true the cookie must be
   // deleted.
   typedef base::Callback<bool(NSHTTPCookie*, base::Time)> CookieFilterFunction;
 
@@ -153,9 +156,8 @@
   // Returns true if the system cookie store policy is
   // |NSHTTPCookieAcceptPolicyAlways|.
   bool SystemCookiesAllowed();
-  // Copies the cookies to the backing CookieMonster. If the cookie store is not
-  // synchronized with the system store, this is a no-op.
-  void WriteToCookieMonster(NSArray* system_cookies);
+  // Copies the cookies to the backing CookieMonster.
+  virtual void WriteToCookieMonster(NSArray* system_cookies);
 
   // Inherited CookieNotificationObserver methods.
   void OnSystemCookiesChanged() override;
@@ -169,8 +171,6 @@
   bool metrics_enabled_;
   base::CancelableClosure flush_closure_;
 
-  SynchronizationState synchronization_state_;
-
   base::ThreadChecker thread_checker_;
 
   // Cookie notification methods.
@@ -264,16 +264,6 @@
   // creation date.
   net::CookieList CanonicalCookieListFromSystemCookies(NSArray* cookies);
 
-  // These three functions are used for wrapping user-supplied callbacks given
-  // to CookieStoreIOS mutator methods. Given a callback, they return a new
-  // callback that invokes UpdateCachesFromCookieMonster() to schedule an
-  // asynchronous synchronization of the cookie cache and then calls the
-  // original callback.
-
-  SetCookiesCallback WrapSetCallback(const SetCookiesCallback& callback);
-  DeleteCallback WrapDeleteCallback(const DeleteCallback& callback);
-  base::Closure WrapClosure(const base::Closure& callback);
-
   // Cached values of system cookies. Only cookies which have an observer added
   // with AddCallbackForCookie are kept in this cache.
   std::unique_ptr<CookieCache> cookie_cache_;
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index e0e5280..fb231140 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -274,11 +274,8 @@
 #pragma mark -
 #pragma mark CookieStoreIOS
 
-CookieStoreIOS::CookieStoreIOS(
-    net::CookieMonster::PersistentCookieStore* persistent_store)
-    : CookieStoreIOS(persistent_store,
-                     [NSHTTPCookieStorage sharedHTTPCookieStorage]) {
-}
+CookieStoreIOS::CookieStoreIOS(NSHTTPCookieStorage* cookie_storage)
+    : CookieStoreIOS(nullptr, cookie_storage) {}
 
 CookieStoreIOS::~CookieStoreIOS() {
   NotificationTrampoline::GetInstance()->RemoveObserver(this);
@@ -294,8 +291,7 @@
   // Create a cookie store with no persistent store backing. Then, populate
   // it from the system's cookie jar.
   std::unique_ptr<CookieStoreIOS> cookie_store(
-      new CookieStoreIOS(nullptr, cookie_storage));
-  cookie_store->synchronization_state_ = SYNCHRONIZED;
+      new CookieStoreIOS(cookie_storage));
   cookie_store->FlushStore(base::Closure());
   return cookie_store;
 }
@@ -323,57 +319,49 @@
     const SetCookiesCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->SetCookieWithOptionsAsync(url, cookie_line, options,
-                                                 WrapSetCallback(callback));
-      break;
-    case SYNCHRONIZED:
-      // The exclude_httponly() option would only be used by a javascript
-      // engine.
-      DCHECK(!options.exclude_httponly());
-      // If cookies are not allowed, they are stashed in the CookieMonster, and
-      // should be written there instead.
-      DCHECK(SystemCookiesAllowed());
+  // The exclude_httponly() option would only be used by a javascript
+  // engine.
+  DCHECK(!options.exclude_httponly());
 
-      base::Time server_time =
-          options.has_server_time() ? options.server_time() : base::Time();
-      NSHTTPCookie* cookie =
-          GetNSHTTPCookieFromCookieLine(cookie_line, url, server_time);
-      DLOG_IF(WARNING, !cookie)
-          << "Could not create cookie for line: " << cookie_line;
+  // If cookies are not allowed, they are stashed in the CookieMonster, and
+  // should be written there instead.
+  DCHECK(SystemCookiesAllowed());
 
-      // On iOS, [cookie domain] is not empty when the cookie domain is not
-      // specified: it is inferred from the URL instead. The only case when it
-      // is empty is when the domain attribute is incorrectly formatted.
-      std::string domain_string(base::SysNSStringToUTF8([cookie domain]));
-      std::string dummy;
-      bool has_explicit_domain = HasExplicitDomain(cookie_line);
-      bool has_valid_domain =
-          net::cookie_util::GetCookieDomainWithString(
-              url, domain_string, &dummy);
-      // A cookie can be set if all of:
-      //   a) The cookie line is well-formed
-      //   b) The Domain attribute, if present, was not malformed
-      //   c) At least one of:
-      //       1) The cookie had no explicit Domain, so the Domain was inferred
-      //          from the URL, or
-      //       2) The cookie had an explicit Domain for which the URL is allowed
-      //          to set cookies.
-      bool success = (cookie != nil) && !domain_string.empty() &&
-                     (!has_explicit_domain || has_valid_domain);
+  base::Time server_time =
+      options.has_server_time() ? options.server_time() : base::Time();
+  NSHTTPCookie* cookie =
+      GetNSHTTPCookieFromCookieLine(cookie_line, url, server_time);
+  DLOG_IF(WARNING, !cookie) << "Could not create cookie for line: "
+                            << cookie_line;
 
-      if (success) {
-        [system_store_ setCookie:cookie];
-        creation_time_manager_->SetCreationTime(
-            cookie,
-            creation_time_manager_->MakeUniqueCreationTime(base::Time::Now()));
-      }
+  // On iOS, [cookie domain] is not empty when the cookie domain is not
+  // specified: it is inferred from the URL instead. The only case when it
+  // is empty is when the domain attribute is incorrectly formatted.
+  std::string domain_string(base::SysNSStringToUTF8([cookie domain]));
+  std::string dummy;
+  bool has_explicit_domain = HasExplicitDomain(cookie_line);
+  bool has_valid_domain =
+      net::cookie_util::GetCookieDomainWithString(url, domain_string, &dummy);
+  // A cookie can be set if all of:
+  //   a) The cookie line is well-formed
+  //   b) The Domain attribute, if present, was not malformed
+  //   c) At least one of:
+  //       1) The cookie had no explicit Domain, so the Domain was inferred
+  //          from the URL, or
+  //       2) The cookie had an explicit Domain for which the URL is allowed
+  //          to set cookies.
+  bool success = (cookie != nil) && !domain_string.empty() &&
+                 (!has_explicit_domain || has_valid_domain);
 
-      if (!callback.is_null())
-        callback.Run(success);
-      break;
+  if (success) {
+    [system_store_ setCookie:cookie];
+    creation_time_manager_->SetCreationTime(
+        cookie,
+        creation_time_manager_->MakeUniqueCreationTime(base::Time::Now()));
   }
+
+  if (!callback.is_null())
+    callback.Run(success);
 }
 
 void CookieStoreIOS::SetCookieWithDetailsAsync(
@@ -391,48 +379,36 @@
     CookiePriority priority,
     const SetCookiesCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  // If cookies are not allowed, they are stashed in the CookieMonster, and
+  // should be written there instead.
+  DCHECK(SystemCookiesAllowed());
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->SetCookieWithDetailsAsync(
+  bool success = false;
+
+  if (creation_time.is_null())
+    creation_time = base::Time::Now();
+
+  // First create a CanonicalCookie, to normalize the arguments,
+  // particularly domain and path, and perform validation.
+  std::unique_ptr<net::CanonicalCookie> canonical_cookie =
+      net::CanonicalCookie::Create(
           url, name, value, domain, path, creation_time, expiration_time,
-          last_access_time, secure, http_only, same_site, priority,
-          WrapSetCallback(callback));
-      break;
-    case SYNCHRONIZED:
-      // If cookies are not allowed, they are stashed in the CookieMonster, and
-      // should be written there instead.
-      DCHECK(SystemCookiesAllowed());
+          secure, http_only, same_site, priority);
 
-      bool success = false;
+  if (canonical_cookie) {
+    NSHTTPCookie* cookie = SystemCookieFromCanonicalCookie(*canonical_cookie);
 
-      if (creation_time.is_null())
-        creation_time = base::Time::Now();
-
-      // First create a CanonicalCookie, to normalize the arguments,
-      // particularly domain and path, and perform validation.
-      std::unique_ptr<net::CanonicalCookie> canonical_cookie =
-          net::CanonicalCookie::Create(
-              url, name, value, domain, path, creation_time, expiration_time,
-              secure, http_only, same_site, priority);
-
-      if (canonical_cookie) {
-        NSHTTPCookie* cookie =
-            SystemCookieFromCanonicalCookie(*canonical_cookie);
-
-        if (cookie != nil) {
-          [system_store_ setCookie:cookie];
-          creation_time_manager_->SetCreationTime(
-              cookie, creation_time_manager_->MakeUniqueCreationTime(
-                          canonical_cookie->CreationDate()));
-          success = true;
-        }
-      }
-
-      if (!callback.is_null())
-        callback.Run(success);
-      break;
+    if (cookie != nil) {
+      [system_store_ setCookie:cookie];
+      creation_time_manager_->SetCreationTime(
+          cookie, creation_time_manager_->MakeUniqueCreationTime(
+              canonical_cookie->CreationDate()));
+      success = true;
+    }
   }
+
+  if (!callback.is_null())
+    callback.Run(success);
 }
 
 void CookieStoreIOS::GetCookiesWithOptionsAsync(
@@ -441,26 +417,19 @@
     const GetCookiesCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->GetCookiesWithOptionsAsync(url, options, callback);
-      break;
-    case SYNCHRONIZED:
-      // If cookies are not allowed, they are stashed in the CookieMonster, and
-      // should be read from there instead.
-      DCHECK(SystemCookiesAllowed());
-      // The exclude_httponly() option would only be used by a javascript
-      // engine.
-      DCHECK(!options.exclude_httponly());
+  // If cookies are not allowed, they are stashed in the CookieMonster, and
+  // should be read from there instead.
+  DCHECK(SystemCookiesAllowed());
+  // The exclude_httponly() option would only be used by a javascript
+  // engine.
+  DCHECK(!options.exclude_httponly());
 
-      // TODO(mkwst): If/when iOS supports Same-Site cookies, we'll need to pass
-      // options in here as well. https://crbug.com/459154
-      NSArray* cookies = GetCookiesForURL(system_store_,
-                                          url, creation_time_manager_.get());
-      if (!callback.is_null())
-        callback.Run(BuildCookieLineWithOptions(cookies, options));
-      break;
-  }
+  // TODO(mkwst): If/when iOS supports Same-Site cookies, we'll need to pass
+  // options in here as well. https://crbug.com/459154
+  NSArray* cookies =
+      GetCookiesForURL(system_store_, url, creation_time_manager_.get());
+  if (!callback.is_null())
+    callback.Run(BuildCookieLineWithOptions(cookies, options));
 }
 
 void CookieStoreIOS::GetCookieListWithOptionsAsync(
@@ -468,54 +437,36 @@
     const net::CookieOptions& options,
     const GetCookieListCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->GetCookieListWithOptionsAsync(url, options, callback);
-      break;
-    case SYNCHRONIZED:
-      if (!SystemCookiesAllowed()) {
-        // If cookies are not allowed, the cookies are stashed in the
-        // CookieMonster, so get them from there.
-        cookie_monster_->GetCookieListWithOptionsAsync(url, options, callback);
-        return;
-      }
-
-      // TODO(mkwst): If/when iOS supports Same-Site cookies, we'll need to pass
-      // options in here as well. https://crbug.com/459154
-      NSArray* cookies = GetCookiesForURL(system_store_,
-                                          url, creation_time_manager_.get());
-      net::CookieList cookie_list = CanonicalCookieListFromSystemCookies(
-          cookies);
-      if (!callback.is_null())
-        callback.Run(cookie_list);
-      break;
+  if (!SystemCookiesAllowed()) {
+    // If cookies are not allowed, the cookies are stashed in the
+    // CookieMonster, so get them from there.
+    cookie_monster_->GetCookieListWithOptionsAsync(url, options, callback);
+    return;
   }
+
+  // TODO(mkwst): If/when iOS supports Same-Site cookies, we'll need to pass
+  // options in here as well. https://crbug.com/459154
+  NSArray* cookies =
+      GetCookiesForURL(system_store_, url, creation_time_manager_.get());
+  net::CookieList cookie_list = CanonicalCookieListFromSystemCookies(cookies);
+  if (!callback.is_null())
+    callback.Run(cookie_list);
 }
 
 void CookieStoreIOS::GetAllCookiesAsync(const GetCookieListCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->GetAllCookiesAsync(callback);
-      break;
-    case SYNCHRONIZED:
-      if (!SystemCookiesAllowed()) {
-        // If cookies are not allowed, the cookies are stashed in the
-        // CookieMonster, so get them from there.
-        cookie_monster_->GetAllCookiesAsync(callback);
-        return;
-      }
+  if (!SystemCookiesAllowed()) {
+    // If cookies are not allowed, the cookies are stashed in the
+    // CookieMonster, so get them from there.
+    cookie_monster_->GetAllCookiesAsync(callback);
+    return;
+  }
 
-      NSArray* cookies = GetAllCookies(system_store_,
-                                       creation_time_manager_.get());
-      net::CookieList cookie_list = CanonicalCookieListFromSystemCookies(
-          cookies);
-      if (!callback.is_null()) {
-        callback.Run(cookie_list);
-      }
-      break;
+  NSArray* cookies = GetAllCookies(system_store_, creation_time_manager_.get());
+  net::CookieList cookie_list = CanonicalCookieListFromSystemCookies(cookies);
+  if (!callback.is_null()) {
+    callback.Run(cookie_list);
   }
 }
 
@@ -524,25 +475,17 @@
                                        const base::Closure& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->DeleteCookieAsync(url, cookie_name,
-                                         WrapClosure(callback));
-      break;
-    case SYNCHRONIZED:
-      NSArray* cookies = GetCookiesForURL(system_store_,
-                                          url, creation_time_manager_.get());
-      for (NSHTTPCookie* cookie in cookies) {
-        if ([[cookie name]
-                isEqualToString:base::SysUTF8ToNSString(cookie_name)]) {
-          [system_store_ deleteCookie:cookie];
-          creation_time_manager_->DeleteCreationTime(cookie);
-        }
-      }
-      if (!callback.is_null())
-        callback.Run();
-      break;
+  NSArray* cookies =
+      GetCookiesForURL(system_store_, url, creation_time_manager_.get());
+  for (NSHTTPCookie* cookie in cookies) {
+    if ([[cookie name] isEqualToString:base::SysUTF8ToNSString(cookie_name)]) {
+      [system_store_ deleteCookie:cookie];
+      creation_time_manager_->DeleteCreationTime(cookie);
+    }
   }
+
+  if (!callback.is_null())
+    callback.Run();
 }
 
 void CookieStoreIOS::DeleteCanonicalCookieAsync(
@@ -550,17 +493,10 @@
     const DeleteCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->DeleteCanonicalCookieAsync(cookie,
-                                                  WrapDeleteCallback(callback));
-      break;
-    case SYNCHRONIZED:
-      // This relies on the fact cookies are given unique creation dates.
-      CookieFilterFunction filter = base::Bind(
-          IsCookieCreatedBetween, cookie.CreationDate(), cookie.CreationDate());
-      DeleteCookiesWithFilter(filter, callback);
-  }
+  // This relies on the fact cookies are given unique creation dates.
+  CookieFilterFunction filter = base::Bind(
+      IsCookieCreatedBetween, cookie.CreationDate(), cookie.CreationDate());
+  DeleteCookiesWithFilter(filter, callback);
 }
 
 void CookieStoreIOS::DeleteAllCreatedBetweenAsync(
@@ -572,17 +508,9 @@
   if (metrics_enabled_)
     ResetCookieCountMetrics();
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->DeleteAllCreatedBetweenAsync(
-          delete_begin, delete_end, WrapDeleteCallback(callback));
-      break;
-    case SYNCHRONIZED:
-      CookieFilterFunction filter =
-          base::Bind(&IsCookieCreatedBetween, delete_begin, delete_end);
-      DeleteCookiesWithFilter(filter, callback);
-      break;
-  }
+  CookieFilterFunction filter = base::Bind(
+      &IsCookieCreatedBetween, delete_begin, delete_end);
+  DeleteCookiesWithFilter(filter, callback);
 }
 
 void CookieStoreIOS::DeleteAllCreatedBetweenWithPredicateAsync(
@@ -595,18 +523,9 @@
   if (metrics_enabled_)
     ResetCookieCountMetrics();
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->DeleteAllCreatedBetweenWithPredicateAsync(
-          delete_begin, delete_end, predicate, WrapDeleteCallback(callback));
-      break;
-    case SYNCHRONIZED:
-      CookieFilterFunction filter =
-          base::Bind(IsCookieCreatedBetweenWithPredicate, delete_begin,
-                     delete_end, predicate);
-      DeleteCookiesWithFilter(filter, callback);
-      break;
-  }
+  CookieFilterFunction filter = base::Bind(
+      IsCookieCreatedBetweenWithPredicate, delete_begin, delete_end, predicate);
+  DeleteCookiesWithFilter(filter, callback);
 }
 
 void CookieStoreIOS::DeleteSessionCookiesAsync(const DeleteCallback& callback) {
@@ -615,15 +534,8 @@
   if (metrics_enabled_)
     ResetCookieCountMetrics();
 
-  switch (synchronization_state_) {
-    case NOT_SYNCHRONIZED:
-      cookie_monster_->DeleteSessionCookiesAsync(WrapDeleteCallback(callback));
-      break;
-    case SYNCHRONIZED:
-      CookieFilterFunction filter = base::Bind(&IsCookieSessionCookie);
-      DeleteCookiesWithFilter(filter, callback);
-      break;
-  }
+  CookieFilterFunction filter = base::Bind(&IsCookieSessionCookie);
+  DeleteCookiesWithFilter(filter, callback);
 }
 
 void CookieStoreIOS::FlushStore(const base::Closure& closure) {
@@ -639,7 +551,7 @@
 }
 
 #pragma mark -
-#pragma mark Private methods
+#pragma mark Protected methods
 
 CookieStoreIOS::CookieStoreIOS(
     net::CookieMonster::PersistentCookieStore* persistent_store,
@@ -648,7 +560,6 @@
       system_store_(system_store),
       creation_time_manager_(new CookieCreationTimeManager),
       metrics_enabled_(false),
-      synchronization_state_(NOT_SYNCHRONIZED),
       cookie_cache_(new CookieCache()),
       weak_factory_(this) {
   DCHECK(system_store);
@@ -659,6 +570,29 @@
   cookie_monster_->SetForceKeepSessionState();
 }
 
+CookieStoreIOS::SetCookiesCallback CookieStoreIOS::WrapSetCallback(
+    const SetCookiesCallback& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return base::Bind(&CookieStoreIOS::UpdateCachesAfterSet,
+                    weak_factory_.GetWeakPtr(), callback);
+}
+
+CookieStoreIOS::DeleteCallback CookieStoreIOS::WrapDeleteCallback(
+    const DeleteCallback& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return base::Bind(&CookieStoreIOS::UpdateCachesAfterDelete,
+                    weak_factory_.GetWeakPtr(), callback);
+}
+
+base::Closure CookieStoreIOS::WrapClosure(const base::Closure& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return base::Bind(&CookieStoreIOS::UpdateCachesAfterClosure,
+                    weak_factory_.GetWeakPtr(), callback);
+}
+
+#pragma mark -
+#pragma mark Private methods
+
 void CookieStoreIOS::ClearSystemStore() {
   DCHECK(thread_checker_.CalledOnValidThread());
   base::scoped_nsobject<NSArray> copy(
@@ -677,9 +611,6 @@
 
 void CookieStoreIOS::WriteToCookieMonster(NSArray* system_cookies) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (synchronization_state_ != SYNCHRONIZED)
-    return;
-
   // Copy the cookies from the global cookie store to |cookie_monster_|.
   // Unlike the system store, CookieMonster requires unique creation times.
   net::CookieList cookie_list;
@@ -699,7 +630,6 @@
 void CookieStoreIOS::DeleteCookiesWithFilter(const CookieFilterFunction& filter,
                                              const DeleteCallback& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_EQ(SYNCHRONIZED, synchronization_state_);
   NSArray* cookies = [system_store_ cookies];
 
   // Collect the cookies to delete.
@@ -724,13 +654,6 @@
 void CookieStoreIOS::OnSystemCookiesChanged() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  // If the CookieStoreIOS is not synchronized or is not backed by
-  // |NSHTTPCookieStorage sharedHTTPCookieStorage| this callback is irrelevant.
-  if (synchronization_state_ != SYNCHRONIZED ||
-      system_store_ != [NSHTTPCookieStorage sharedHTTPCookieStorage]) {
-    return;
-  }
-
   for (const auto& hook_map_entry : hook_map_) {
     std::pair<GURL, std::string> key = hook_map_entry.first;
     std::vector<net::CanonicalCookie> removed_cookies;
@@ -914,24 +837,4 @@
   return cookie_list;
 }
 
-CookieStoreIOS::SetCookiesCallback CookieStoreIOS::WrapSetCallback(
-    const SetCookiesCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return base::Bind(&CookieStoreIOS::UpdateCachesAfterSet,
-                    weak_factory_.GetWeakPtr(), callback);
-}
-
-CookieStoreIOS::DeleteCallback CookieStoreIOS::WrapDeleteCallback(
-    const DeleteCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return base::Bind(&CookieStoreIOS::UpdateCachesAfterDelete,
-                    weak_factory_.GetWeakPtr(), callback);
-}
-
-base::Closure CookieStoreIOS::WrapClosure(const base::Closure& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return base::Bind(&CookieStoreIOS::UpdateCachesAfterClosure,
-                    weak_factory_.GetWeakPtr(), callback);
-}
-
 }  // namespace net
diff --git a/ios/net/cookies/cookie_store_ios_persistent.h b/ios/net/cookies/cookie_store_ios_persistent.h
new file mode 100644
index 0000000..ce3bd470
--- /dev/null
+++ b/ios/net/cookies/cookie_store_ios_persistent.h
@@ -0,0 +1,89 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_NET_COOKIES_COOKIE_STORE_IOS_PERSISTENT_H_
+#define IOS_NET_COOKIES_COOKIE_STORE_IOS_PERSISTENT_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#import "ios/net/cookies/cookie_store_ios.h"
+#include "net/cookies/cookie_monster.h"
+#include "net/cookies/cookie_store.h"
+#include "url/gurl.h"
+
+@class NSHTTPCookieStorage;
+
+namespace net {
+
+// The CookieStoreIOSPersistent is an implementation of CookieStore relying on
+// on backing CookieStore.
+// CookieStoreIOSPersistent is not thread safe.
+//
+// All the changes are written back to the backing CookieStore.
+// For synchronized CookieStore, please see CookieStoreIOS.
+//
+// TODO(crbug.com/686147): evaluate if inheritance is
+// needed here.
+class CookieStoreIOSPersistent : public CookieStoreIOS {
+ public:
+  // Creates a CookieStoreIOS with a default value of
+  // |NSHTTPCookieStorage sharedCookieStorage| as the system's cookie store.
+  explicit CookieStoreIOSPersistent(
+      net::CookieMonster::PersistentCookieStore* persistent_store);
+
+  ~CookieStoreIOSPersistent() override;
+
+  // Inherited CookieStore methods.
+  void SetCookieWithOptionsAsync(const GURL& url,
+                                 const std::string& cookie_line,
+                                 const net::CookieOptions& options,
+                                 const SetCookiesCallback& callback) override;
+  void SetCookieWithDetailsAsync(const GURL& url,
+                                 const std::string& name,
+                                 const std::string& value,
+                                 const std::string& domain,
+                                 const std::string& path,
+                                 base::Time creation_time,
+                                 base::Time expiration_time,
+                                 base::Time last_access_time,
+                                 bool secure,
+                                 bool http_only,
+                                 CookieSameSite same_site,
+                                 CookiePriority priority,
+                                 const SetCookiesCallback& callback) override;
+  void GetCookiesWithOptionsAsync(const GURL& url,
+                                  const net::CookieOptions& options,
+                                  const GetCookiesCallback& callback) override;
+  void GetCookieListWithOptionsAsync(
+      const GURL& url,
+      const net::CookieOptions& options,
+      const GetCookieListCallback& callback) override;
+  void GetAllCookiesAsync(const GetCookieListCallback& callback) override;
+  void DeleteCookieAsync(const GURL& url,
+                         const std::string& cookie_name,
+                         const base::Closure& callback) override;
+  void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+                                  const DeleteCallback& callback) override;
+  void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
+                                    const base::Time& delete_end,
+                                    const DeleteCallback& callback) override;
+  void DeleteAllCreatedBetweenWithPredicateAsync(
+      const base::Time& delete_begin,
+      const base::Time& delete_end,
+      const CookiePredicate& predicate,
+      const DeleteCallback& callback) override;
+  void DeleteSessionCookiesAsync(const DeleteCallback& callback) override;
+
+ private:
+  // No-op functions for this class.
+  void WriteToCookieMonster(NSArray* system_cookies) override;
+  void OnSystemCookiesChanged() override;
+
+  DISALLOW_COPY_AND_ASSIGN(CookieStoreIOSPersistent);
+};
+
+}  // namespace net
+
+#endif  // IOS_NET_COOKIES_COOKIE_STORE_IOS_PERSISTENT_H_
diff --git a/ios/net/cookies/cookie_store_ios_persistent.mm b/ios/net/cookies/cookie_store_ios_persistent.mm
new file mode 100644
index 0000000..a0ed1ada
--- /dev/null
+++ b/ios/net/cookies/cookie_store_ios_persistent.mm
@@ -0,0 +1,141 @@
+// Copyright (c) 2017 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/net/cookies/cookie_store_ios_persistent.h"
+
+#import <Foundation/Foundation.h>
+
+#include "ios/net/cookies/system_cookie_util.h"
+#include "net/cookies/cookie_monster.h"
+
+namespace net {
+
+#pragma mark -
+#pragma mark CookieStoreIOSPersistent
+
+CookieStoreIOSPersistent::CookieStoreIOSPersistent(
+    net::CookieMonster::PersistentCookieStore* persistent_store)
+    : CookieStoreIOS(persistent_store,
+                     [NSHTTPCookieStorage sharedHTTPCookieStorage]) {}
+
+CookieStoreIOSPersistent::~CookieStoreIOSPersistent() {}
+
+#pragma mark -
+#pragma mark CookieStoreIOSPersistent methods
+
+void CookieStoreIOSPersistent::SetCookieWithOptionsAsync(
+    const GURL& url,
+    const std::string& cookie_line,
+    const net::CookieOptions& options,
+    const SetCookiesCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+
+  cookie_monster()->SetCookieWithOptionsAsync(url, cookie_line, options,
+                                              WrapSetCallback(callback));
+}
+
+void CookieStoreIOSPersistent::SetCookieWithDetailsAsync(
+    const GURL& url,
+    const std::string& name,
+    const std::string& value,
+    const std::string& domain,
+    const std::string& path,
+    base::Time creation_time,
+    base::Time expiration_time,
+    base::Time last_access_time,
+    bool secure,
+    bool http_only,
+    CookieSameSite same_site,
+    CookiePriority priority,
+    const SetCookiesCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+
+  cookie_monster()->SetCookieWithDetailsAsync(
+      url, name, value, domain, path, creation_time, expiration_time,
+      last_access_time, secure, http_only, same_site, priority,
+      WrapSetCallback(callback));
+}
+
+void CookieStoreIOSPersistent::GetCookiesWithOptionsAsync(
+    const GURL& url,
+    const net::CookieOptions& options,
+    const GetCookiesCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+  cookie_monster()->GetCookiesWithOptionsAsync(url, options, callback);
+}
+
+void CookieStoreIOSPersistent::GetCookieListWithOptionsAsync(
+    const GURL& url,
+    const net::CookieOptions& options,
+    const GetCookieListCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+
+  cookie_monster()->GetCookieListWithOptionsAsync(url, options, callback);
+}
+
+void CookieStoreIOSPersistent::GetAllCookiesAsync(
+    const GetCookieListCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+  cookie_monster()->GetAllCookiesAsync(callback);
+}
+
+void CookieStoreIOSPersistent::DeleteCookieAsync(
+    const GURL& url,
+    const std::string& cookie_name,
+    const base::Closure& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+  cookie_monster()->DeleteCookieAsync(url, cookie_name, WrapClosure(callback));
+}
+
+void CookieStoreIOSPersistent::DeleteCanonicalCookieAsync(
+    const CanonicalCookie& cookie,
+    const DeleteCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+  cookie_monster()->DeleteCanonicalCookieAsync(cookie,
+                                               WrapDeleteCallback(callback));
+}
+
+void CookieStoreIOSPersistent::DeleteAllCreatedBetweenAsync(
+    const base::Time& delete_begin,
+    const base::Time& delete_end,
+    const DeleteCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+  if (metrics_enabled())
+    ResetCookieCountMetrics();
+
+  cookie_monster()->DeleteAllCreatedBetweenAsync(delete_begin, delete_end,
+                                                 WrapDeleteCallback(callback));
+}
+
+void CookieStoreIOSPersistent::DeleteAllCreatedBetweenWithPredicateAsync(
+    const base::Time& delete_begin,
+    const base::Time& delete_end,
+    const CookiePredicate& predicate,
+    const DeleteCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+
+  if (metrics_enabled())
+    ResetCookieCountMetrics();
+
+  cookie_monster()->DeleteAllCreatedBetweenWithPredicateAsync(
+      delete_begin, delete_end, predicate, WrapDeleteCallback(callback));
+}
+
+void CookieStoreIOSPersistent::DeleteSessionCookiesAsync(
+    const DeleteCallback& callback) {
+  DCHECK(thread_checker().CalledOnValidThread());
+  if (metrics_enabled())
+    ResetCookieCountMetrics();
+
+  cookie_monster()->DeleteSessionCookiesAsync(WrapDeleteCallback(callback));
+}
+
+#pragma mark -
+#pragma mark Private methods
+
+void CookieStoreIOSPersistent::WriteToCookieMonster(NSArray* system_cookies) {}
+
+void CookieStoreIOSPersistent::OnSystemCookiesChanged() {}
+
+}  // namespace net
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm
index 6bc192bf..fb4554e 100644
--- a/ios/net/cookies/cookie_store_ios_unittest.mm
+++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -14,6 +14,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
+#import "ios/net/cookies/cookie_store_ios_persistent.h"
 #import "net/base/mac/url_conversions.h"
 #include "net/cookies/cookie_store_unittest.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -35,9 +36,8 @@
 struct CookieStoreIOSTestTraits {
   static std::unique_ptr<net::CookieStore> Create() {
     ClearCookies();
-    std::unique_ptr<CookieStoreIOS> store(new CookieStoreIOS(nullptr));
-    store->synchronization_state_ = CookieStoreIOS::SYNCHRONIZED;
-    return std::move(store);
+    return base::MakeUnique<CookieStoreIOS>(
+        [NSHTTPCookieStorage sharedHTTPCookieStorage]);
   }
 
   static const bool supports_http_only = false;
@@ -52,7 +52,7 @@
 
 struct InactiveCookieStoreIOSTestTraits {
   static std::unique_ptr<net::CookieStore> Create() {
-    return base::MakeUnique<CookieStoreIOS>(nullptr);
+    return base::MakeUnique<CookieStoreIOSPersistent>(nullptr);
   }
 
   static const bool is_cookie_monster = false;
@@ -230,7 +230,8 @@
   NotSynchronizedCookieStoreIOSWithBackend()
       : kTestCookieURL("http://foo.google.com/bar"),
         backend_(new TestPersistentCookieStore),
-        store_(new net::CookieStoreIOS(backend_.get())) {
+        store_(base::MakeUnique<net::CookieStoreIOSPersistent>(backend_.get()))
+  {
     cookie_changed_callback_ = store_->AddCallbackForCookie(
         kTestCookieURL, "abc",
         base::Bind(&RecordCookieChanges, &cookies_changed_, &cookies_removed_));
@@ -273,8 +274,8 @@
         kTestCookieURL3("http://foo.google.com"),
         kTestCookieURL4("http://bar.google.com/bar"),
         backend_(new TestPersistentCookieStore),
-        store_(net::CookieStoreIOS::CreateCookieStore(
-            [NSHTTPCookieStorage sharedHTTPCookieStorage])) {
+        store_(base::MakeUnique<net::CookieStoreIOS>(
+                [NSHTTPCookieStorage sharedHTTPCookieStorage])) {
     cookie_changed_callback_ = store_->AddCallbackForCookie(
         kTestCookieURL, "abc",
         base::Bind(&RecordCookieChanges, &cookies_changed_, &cookies_removed_));
@@ -417,9 +418,9 @@
   base::MessageLoop loop;
   const GURL kTestCookieURL("http://foo.google.com/bar");
   ClearCookies();
-  std::unique_ptr<CookieStoreIOS> cookie_store(
-      CookieStoreIOS::CreateCookieStore(
-          [NSHTTPCookieStorage sharedHTTPCookieStorage]));
+  std::unique_ptr<CookieStoreIOS> cookie_store(base::MakeUnique<CookieStoreIOS>(
+      [NSHTTPCookieStorage sharedHTTPCookieStorage]));
+
   // Add a cookie.
   net::CookieOptions options;
   options.set_include_httponly();
diff --git a/ios/public/provider/chrome/browser/spotlight/BUILD.gn b/ios/public/provider/chrome/browser/spotlight/BUILD.gn
index dda4cba..b98eae4e 100644
--- a/ios/public/provider/chrome/browser/spotlight/BUILD.gn
+++ b/ios/public/provider/chrome/browser/spotlight/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 source_set("spotlight") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "spotlight_provider.h",
     "spotlight_provider.mm",
diff --git a/ios/public/provider/chrome/browser/spotlight/spotlight_provider.mm b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.mm
index 2a9c2da..4350cb7 100644
--- a/ios/public/provider/chrome/browser/spotlight/spotlight_provider.mm
+++ b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.mm
@@ -4,6 +4,10 @@
 
 #import "ios/public/provider/chrome/browser/spotlight/spotlight_provider.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 bool SpotlightProvider::IsSpotlightEnabled() {
   return false;
 }
diff --git a/ios/public/provider/chrome/browser/ui/BUILD.gn b/ios/public/provider/chrome/browser/ui/BUILD.gn
index 56d77e5..2b9e049 100644
--- a/ios/public/provider/chrome/browser/ui/BUILD.gn
+++ b/ios/public/provider/chrome/browser/ui/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 source_set("ui") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "app_rating_prompt.h",
     "default_ios_web_view_factory.h",
diff --git a/ios/public/provider/chrome/browser/ui/default_ios_web_view_factory.mm b/ios/public/provider/chrome/browser/ui/default_ios_web_view_factory.mm
index ad97ae0..203f9fd4 100644
--- a/ios/public/provider/chrome/browser/ui/default_ios_web_view_factory.mm
+++ b/ios/public/provider/chrome/browser/ui/default_ios_web_view_factory.mm
@@ -6,6 +6,10 @@
 
 #include "base/logging.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 Class g_registered_factory_class = nil;
 }  // namespace
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm
index 7fa966c..d28a0b4 100644
--- a/ios/web/shell/shell_url_request_context_getter.mm
+++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -13,7 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/threading/worker_pool.h"
-#import "ios/net/cookies/cookie_store_ios.h"
+#import "ios/net/cookies/cookie_store_ios_persistent.h"
 #import "ios/web/public/web_client.h"
 #include "ios/web/public/web_thread.h"
 #include "ios/web/shell/shell_network_delegate.h"
@@ -85,7 +85,7 @@
                 web::WebThread::GetBlockingPool()->GetSequenceToken()),
             true, nullptr);
     std::unique_ptr<net::CookieStoreIOS> cookie_store(
-        new net::CookieStoreIOS(persistent_store.get()));
+        new net::CookieStoreIOSPersistent(persistent_store.get()));
     storage_->set_cookie_store(std::move(cookie_store));
 
     std::string user_agent = web::GetWebClient()->GetUserAgent(false);
diff --git a/ios/web/web_state/ui/crw_wk_script_message_router.h b/ios/web/web_state/ui/crw_wk_script_message_router.h
index bb6b2a2d..6dfc20b 100644
--- a/ios/web/web_state/ui/crw_wk_script_message_router.h
+++ b/ios/web/web_state/ui/crw_wk_script_message_router.h
@@ -9,7 +9,7 @@
 
 // WKUserContentController wrapper that allows adding multiple message handlers
 // for the same message name. CRWWKScriptMessageRouter will route the messages
-// from the underlying user content controller to a designated reciever by
+// from the underlying user content controller to a designated receiver by
 // matching the message's name and webView.
 @interface CRWWKScriptMessageRouter : NSObject
 
diff --git a/ios/web_view/internal/criwv_url_request_context_getter.mm b/ios/web_view/internal/criwv_url_request_context_getter.mm
index f26690a..f34be3d 100644
--- a/ios/web_view/internal/criwv_url_request_context_getter.mm
+++ b/ios/web_view/internal/criwv_url_request_context_getter.mm
@@ -12,7 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/threading/worker_pool.h"
-#import "ios/net/cookies/cookie_store_ios.h"
+#import "ios/net/cookies/cookie_store_ios_persistent.h"
 #import "ios/web/public/web_client.h"
 #include "ios/web/public/web_thread.h"
 #include "ios/web_view/internal/criwv_network_delegate.h"
@@ -78,7 +78,7 @@
                 web::WebThread::GetBlockingPool()->GetSequenceToken()),
             true, nullptr);
     std::unique_ptr<net::CookieStoreIOS> cookie_store(
-        new net::CookieStoreIOS(persistent_store.get()));
+        new net::CookieStoreIOSPersistent(persistent_store.get()));
     storage_->set_cookie_store(std::move(cookie_store));
 
     std::string user_agent = web::GetWebClient()->GetUserAgent(false);
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc
index 4833288..33450a3 100644
--- a/media/audio/win/audio_low_latency_output_win.cc
+++ b/media/audio/win/audio_low_latency_output_win.cc
@@ -38,26 +38,6 @@
   return AUDCLNT_SHAREMODE_SHARED;
 }
 
-// static
-int WASAPIAudioOutputStream::HardwareSampleRate(const std::string& device_id) {
-  WAVEFORMATPCMEX format;
-  ScopedComPtr<IAudioClient> client;
-  if (device_id.empty()) {
-    client = CoreAudioUtil::CreateDefaultClient(eRender, eConsole);
-  } else {
-    ScopedComPtr<IMMDevice> device(CoreAudioUtil::CreateDevice(device_id));
-    if (!device.get())
-      return 0;
-    client = CoreAudioUtil::CreateClient(device.get());
-  }
-
-  if (!client.get() ||
-      FAILED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format)))
-    return 0;
-
-  return static_cast<int>(format.Format.nSamplesPerSec);
-}
-
 WASAPIAudioOutputStream::WASAPIAudioOutputStream(AudioManagerWin* manager,
                                                  const std::string& device_id,
                                                  const AudioParameters& params,
diff --git a/media/audio/win/audio_low_latency_output_win.h b/media/audio/win/audio_low_latency_output_win.h
index 97d81b9..e087328 100644
--- a/media/audio/win/audio_low_latency_output_win.h
+++ b/media/audio/win/audio_low_latency_output_win.h
@@ -33,9 +33,8 @@
 //    o Construction and destruction must take place from the same thread.
 //    o All APIs must be called from the creating thread as well.
 // - It is required to first acquire the native audio parameters of the default
-//   output device and then use the same rate when creating this object. Use
-//   e.g. WASAPIAudioOutputStream::HardwareSampleRate() to retrieve the sample
-//   rate. Open() will fail unless "perfect" audio parameters are utilized.
+//   output device and then use the same rate when creating this object.
+//   Open() will fail unless "perfect" audio parameters are utilized.
 // - Calling Close() also leads to self destruction.
 // - Support for 8-bit audio has not yet been verified and tested.
 //
@@ -87,7 +86,8 @@
 //   the lowest possible latencies we can achieve on this machine are:
 //     o ~3.3333ms @ 48kHz <=> 160 audio frames per buffer.
 //     o ~3.6281ms @ 44.1kHz <=> 160 audio frames per buffer.
-// - See http://msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.85).aspx
+// - See
+// http://msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.85).aspx
 //   for more details.
 
 #ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_
@@ -141,11 +141,6 @@
   void SetVolume(double volume) override;
   void GetVolume(double* volume) override;
 
-  // Retrieves the sample rate the audio engine uses for its internal
-  // processing/mixing of shared-mode streams.  To fetch the settings for the
-  // default device, pass an empty string as the |device_id|.
-  static int HardwareSampleRate(const std::string& device_id);
-
   // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used
   // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default).
   static AUDCLNT_SHAREMODE GetShareMode();
diff --git a/media/audio/win/audio_low_latency_output_win_unittest.cc b/media/audio/win/audio_low_latency_output_win_unittest.cc
index 656cda74..024580c 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -248,23 +248,6 @@
   ScopedAudioManagerPtr audio_manager_;
 };
 
-// Verify that we can retrieve the current hardware/mixing sample rate
-// for the default audio device.
-// TODO(henrika): modify this test when we support full device enumeration.
-TEST_F(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
-  // Skip this test in exclusive mode since the resulting rate is only utilized
-  // for shared mode streams.
-  if (ExclusiveModeIsEnabled())
-    return;
-  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
-
-  // Default device intended for games, system notification sounds,
-  // and voice commands.
-  int fs = static_cast<int>(
-      WASAPIAudioOutputStream::HardwareSampleRate(std::string()));
-  EXPECT_GE(fs, 0);
-}
-
 // Test Create(), Close() calling sequence.
 TEST_F(WASAPIAudioOutputStreamTest, CreateAndClose) {
   ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
index fd5caf3c..e514fe0 100644
--- a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
+++ b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
@@ -7,7 +7,7 @@
       try {
         callback(args);
       } catch(e) {
-        reject_func();
+        reject_func(e);
       }
     }
   }
@@ -374,9 +374,9 @@
       return new Promise((resolve, reject) => { setTimeout(resolve, 0); });
     };
 
-    let onFailure = () => {
+    let onFailure = error => {
       sensor.mockSensorProvider.reset();
-      return new Promise((resolve, reject) => { setTimeout(reject, 0); });
+      return new Promise((resolve, reject) => { setTimeout(() => {reject(error);}, 0); });
     };
 
     return Promise.resolve(func(sensor)).then(onSuccess, onFailure);