diff --git a/AUTHORS b/AUTHORS
index 7998ace..698d31e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -721,6 +721,7 @@
 Xiang Long <xiang.long@intel.com>
 Xiangze Zhang <xiangze.zhang@intel.com>
 Xiaolei Yu <dreifachstein@gmail.com>
+Xiaoyin Liu <xiaoyin.l@outlook.com>
 Xinchao He <hexinchao@gmail.com>
 Xing Zhang <xzhang@adobe.com>
 Xinghua Cao <xinghua.cao@intel.com>
diff --git a/DEPS b/DEPS
index 2e832d9b..1e576d29 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'd87fbee77524f83f0eccb7860516d1696e318a96',
+  'skia_revision': '8b4b56ac2927bbb31c634f840916f4ce948d2f53',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 5fa3865..1546ad5 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -593,6 +593,10 @@
         // On top of the explanation message, first show a "Payment not secure"
         // message.
         if (IsCreditCardAutofillHttpWarningEnabled()) {
+#if !defined(OS_ANDROID)
+          suggestions.insert(suggestions.begin(), Suggestion());
+          suggestions.front().frontend_id = POPUP_ITEM_ID_SEPARATOR;
+#endif
           suggestions.insert(suggestions.begin(),
                              CreateHttpWarningMessageSuggestionItem(
                                  form_structure->source_url()));
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 5e5defcd..5000161 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -1631,6 +1631,9 @@
                      IDS_AUTOFILL_CREDIT_CARD_HTTP_WARNING_MESSAGE),
                  l10n_util::GetStringUTF8(IDS_AUTOFILL_HTTP_WARNING_LEARN_MORE),
                  "httpWarning", POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE),
+#if !defined(OS_ANDROID)
+      Suggestion("", "", "", POPUP_ITEM_ID_SEPARATOR),
+#endif
       Suggestion(
           l10n_util::GetStringUTF8(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION),
           "", "", POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE));
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc
index b0a14d5f..1c0b1bf 100644
--- a/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -232,6 +232,10 @@
           l10n_util::GetStringUTF8(IDS_AUTOFILL_PASSWORD_HTTP_WARNING_MESSAGE),
           l10n_util::GetStringUTF8(IDS_AUTOFILL_HTTP_WARNING_LEARN_MORE),
           icon_str, autofill::POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE);
+#if !defined(OS_ANDROID)
+      suggestions.insert(suggestions.begin(), autofill::Suggestion());
+      suggestions.front().frontend_id = autofill::POPUP_ITEM_ID_SEPARATOR;
+#endif
       suggestions.insert(suggestions.begin(),
                          password_field_http_warning_suggestion);
     }
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
index c63d781..617c5ca 100644
--- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -619,13 +619,17 @@
           kMarkHttpWithPasswordsOrCcWithChipAndFormWarning);
 
   // Http warning message shows for non-secure context and switch flag on, so
-  // there are 3 suggestions in total, and the message comes first among
-  // suggestions.
+  // there are 3 suggestions (+ 1 separator on desktop) in total, and the
+  // message comes first among suggestions.
+  auto elements = testing::ElementsAre(warning_message,
+#if !defined(OS_ANDROID)
+                                       base::string16(),
+#endif
+                                       title, test_username_);
+
   EXPECT_CALL(*autofill_client,
               ShowAutofillPopup(element_bounds, _,
-                                SuggestionVectorValuesAre(testing::ElementsAre(
-                                    warning_message, title, test_username_)),
-                                _));
+                                SuggestionVectorValuesAre(elements), _));
   password_autofill_manager_->OnShowPasswordSuggestions(
       dummy_key, base::i18n::RIGHT_TO_LEFT, test_username_,
       autofill::IS_PASSWORD_FIELD, element_bounds);
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index dfe1b58a..451e6f0 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -121,7 +121,7 @@
   RDH_INVALID_URL = 97,
   BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED = 98,
   RFH_OWNER_PROPERTY = 99,
-  BDH_EMPTY_OR_INVALID_FILTERS = 100,
+  BDH_EMPTY_OR_INVALID_FILTERS = 100,  // obsolete; no longer used
   WC_CONTENT_WITH_CERT_ERRORS_BAD_SECURITY_INFO = 101,  // obsolete; not used
   RFMF_RENDERER_FAKED_ITS_OWN_DEATH = 102,
   DWNLD_INVALID_SAVABLE_RESOURCE_LINKS_RESPONSE = 103,
@@ -179,6 +179,7 @@
   MDDH_INVALID_SUBSCRIPTION_REQUEST = 155,
   MDDH_INVALID_UNSUBSCRIPTION_REQUEST = 156,
   AOAH_NONSENSE_DEVICE_ID = 157,
+  BDH_INVALID_OPTIONS = 158,
 
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/bluetooth/bluetooth_allowed_devices_map.cc b/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
index a0173a5e..767ea238 100644
--- a/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
+++ b/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
@@ -166,15 +166,18 @@
     const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options,
     std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash>*
         unionOfServices) {
-  for (const auto& filter : options->filters) {
-    if (!filter->services) {
-      continue;
-    }
+  if (options->filters) {
+    for (const auto& filter : options->filters.value()) {
+      if (!filter->services) {
+        continue;
+      }
 
-    for (const BluetoothUUID& uuid : filter->services.value()) {
-      unionOfServices->insert(uuid);
+      for (const BluetoothUUID& uuid : filter->services.value()) {
+        unionOfServices->insert(uuid);
+      }
     }
   }
+
   for (const BluetoothUUID& uuid : options->optional_services) {
     unionOfServices->insert(uuid);
   }
diff --git a/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc b/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
index f13a02be..c5e4632 100644
--- a/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
+++ b/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
@@ -191,7 +191,8 @@
       blink::mojom::WebBluetoothScanFilter::New();
 
   scan_filter->name = kDeviceName;
-  options->filters.push_back(scan_filter.Clone());
+  options->filters.emplace();
+  options->filters->push_back({scan_filter.Clone()});
 
   // Add to map.
   const WebBluetoothDeviceId device_id =
@@ -217,11 +218,12 @@
 
   scan_filter1->services.emplace();
   scan_filter1->services->push_back(kGlucoseUUID);
-  options->filters.push_back(scan_filter1.Clone());
+  options->filters.emplace();
+  options->filters->push_back(scan_filter1.Clone());
 
   scan_filter2->services.emplace();
   scan_filter2->services->push_back(kHeartRateUUID);
-  options->filters.push_back(scan_filter2.Clone());
+  options->filters->push_back(scan_filter2.Clone());
 
   options->optional_services.push_back(kBatteryServiceUUID);
   options->optional_services.push_back(kHeartRateUUID);
@@ -260,8 +262,9 @@
   blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
       blink::mojom::WebBluetoothRequestDeviceOptions::New();
 
-  options2->filters.push_back(scan_filter1.Clone());
-  options2->filters.push_back(scan_filter2.Clone());
+  options2->filters.emplace();
+  options2->filters->push_back(scan_filter1.Clone());
+  options2->filters->push_back(scan_filter2.Clone());
 
   const WebBluetoothDeviceId device_id2 =
       allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options2);
@@ -298,7 +301,8 @@
 
   scan_filter1->services.emplace();
   scan_filter1->services->push_back(kGlucoseUUID);
-  options1->filters.push_back(std::move(scan_filter1));
+  options1->filters.emplace();
+  options1->filters->push_back(std::move(scan_filter1));
 
   options1->optional_services.push_back(kHeartRateUUID);
 
@@ -310,7 +314,8 @@
 
   scan_filter2->services.emplace();
   scan_filter2->services->push_back(kBatteryServiceUUID);
-  options2->filters.push_back(std::move(scan_filter2));
+  options2->filters.emplace();
+  options2->filters->push_back(std::move(scan_filter2));
 
   options2->optional_services.push_back(kBloodPressureUUID);
 
@@ -361,7 +366,8 @@
 
   scan_filter1->services.emplace();
   scan_filter1->services->push_back(kGlucoseUUID);
-  options1->filters.push_back(std::move(scan_filter1));
+  options1->filters.emplace();
+  options1->filters->push_back(std::move(scan_filter1));
 
   options1->optional_services.push_back(kHeartRateUUID);
 
@@ -373,7 +379,8 @@
 
   scan_filter2->services.emplace();
   scan_filter2->services->push_back(kBatteryServiceUUID);
-  options2->filters.push_back(std::move(scan_filter2));
+  options2->filters.emplace();
+  options2->filters->push_back(std::move(scan_filter2));
 
   options2->optional_services.push_back(kBloodPressureUUID);
 
@@ -443,7 +450,8 @@
 
   scan_filter1->services.emplace();
   scan_filter1->services->push_back(kGlucoseUUID);
-  options1->filters.push_back(std::move(scan_filter1));
+  options1->filters.emplace();
+  options1->filters->push_back(std::move(scan_filter1));
 
   options1->optional_services.push_back(kBatteryServiceUUID);
 
@@ -459,7 +467,8 @@
 
   scan_filter2->services.emplace();
   scan_filter2->services->push_back(kHeartRateUUID);
-  options2->filters.push_back(std::move(scan_filter2));
+  options2->filters.emplace();
+  options2->filters->push_back(std::move(scan_filter2));
 
   options2->optional_services.push_back(kBloodPressureUUID);
 
@@ -499,7 +508,8 @@
   blink::mojom::WebBluetoothScanFilterPtr scan_filter =
       blink::mojom::WebBluetoothScanFilter::New();
 
-  options->filters.push_back(std::move(scan_filter));
+  options->filters.emplace();
+  options->filters->push_back(std::move(scan_filter));
 
   // Add to map.
   const WebBluetoothDeviceId device_id =
diff --git a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
index b6d7721e..5d444c8 100644
--- a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
+++ b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -61,8 +61,13 @@
 void LogRequestDeviceOptions(
     const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
   VLOG(1) << "requestDevice called with the following filters: ";
+  VLOG(1) << "acceptAllDevices: " << options->accept_all_devices;
+
+  if (!options->filters)
+    return;
+
   int i = 0;
-  for (const auto& filter : options->filters) {
+  for (const auto& filter : options->filters.value()) {
     VLOG(1) << "Filter #" << ++i;
     if (filter->name)
       VLOG(1) << "Name: " << filter->name.value();
@@ -100,11 +105,25 @@
 }
 
 bool HasEmptyOrInvalidFilter(
-    const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
-  return filters.empty()
+    const base::Optional<std::vector<blink::mojom::WebBluetoothScanFilterPtr>>&
+        filters) {
+  if (!filters) {
+    return true;
+  }
+
+  return filters->empty()
              ? true
-             : filters.end() != std::find_if(filters.begin(), filters.end(),
-                                             IsEmptyOrInvalidFilter);
+             : filters->end() != std::find_if(filters->begin(), filters->end(),
+                                              IsEmptyOrInvalidFilter);
+}
+
+bool IsOptionsInvalid(
+    const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
+  if (options->accept_all_devices) {
+    return options->filters.has_value();
+  } else {
+    return HasEmptyOrInvalidFilter(options->filters);
+  }
 }
 
 bool MatchesFilter(const std::string* device_name,
@@ -139,9 +158,10 @@
 bool MatchesFilters(
     const std::string* device_name,
     const UUIDSet& device_uuids,
-    const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+    const base::Optional<std::vector<blink::mojom::WebBluetoothScanFilterPtr>>&
+        filters) {
   DCHECK(!HasEmptyOrInvalidFilter(filters));
-  for (const auto& filter : filters) {
+  for (const auto& filter : filters.value()) {
     if (MatchesFilter(device_name, device_uuids, filter)) {
       return true;
     }
@@ -150,16 +170,21 @@
 }
 
 std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter(
-    const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+    const base::Optional<std::vector<blink::mojom::WebBluetoothScanFilterPtr>>&
+        filters) {
   std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash> services;
-  for (const auto& filter : filters) {
-    if (!filter->services) {
-      continue;
-    }
-    for (const auto& service : filter->services.value()) {
-      services.insert(service);
+
+  if (filters) {
+    for (const auto& filter : filters.value()) {
+      if (!filter->services) {
+        continue;
+      }
+      for (const auto& service : filter->services.value()) {
+        services.insert(service);
+      }
     }
   }
+
   // There isn't much support for GATT over BR/EDR from neither platforms nor
   // devices so performing a Dual scan will find devices that the API is not
   // able to interact with. To avoid wasting power and confusing users with
@@ -261,17 +286,18 @@
   success_callback_ = success_callback;
   error_callback_ = error_callback;
 
-  // The renderer should never send empty filters.
-  if (HasEmptyOrInvalidFilter(options->filters)) {
+  // The renderer should never send invalid options.
+  if (IsOptionsInvalid(options)) {
     web_bluetooth_service_->CrashRendererAndClosePipe(
-        bad_message::BDH_EMPTY_OR_INVALID_FILTERS);
+        bad_message::BDH_INVALID_OPTIONS);
     return;
   }
   options_ = std::move(options);
   LogRequestDeviceOptions(options_);
 
   // Check blocklist to reject invalid filters and adjust optional_services.
-  if (BluetoothBlocklist::Get().IsExcluded(options_->filters)) {
+  if (options_->filters &&
+      BluetoothBlocklist::Get().IsExcluded(options_->filters.value())) {
     RecordRequestDeviceOutcome(
         UMARequestDeviceOutcome::BLOCKLISTED_SERVICE_IN_FILTER);
     PostErrorCallback(
@@ -372,15 +398,17 @@
 void BluetoothDeviceChooserController::AddFilteredDevice(
     const device::BluetoothDevice& device) {
   base::Optional<std::string> device_name = device.GetName();
-  if (chooser_.get() &&
-      MatchesFilters(device_name ? &device_name.value() : nullptr,
-                     device.GetUUIDs(), options_->filters)) {
-    base::Optional<int8_t> rssi = device.GetInquiryRSSI();
-    chooser_->AddOrUpdateDevice(
-        device.GetAddress(), !!device.GetName() /* should_update_name */,
-        device.GetNameForDisplay(), device.IsGattConnected(),
-        web_bluetooth_service_->IsDevicePaired(device.GetAddress()),
-        rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1);
+  if (chooser_.get()) {
+    if (options_->accept_all_devices ||
+        MatchesFilters(device_name ? &device_name.value() : nullptr,
+                       device.GetUUIDs(), options_->filters)) {
+      base::Optional<int8_t> rssi = device.GetInquiryRSSI();
+      chooser_->AddOrUpdateDevice(
+          device.GetAddress(), !!device.GetName() /* should_update_name */,
+          device.GetNameForDisplay(), device.IsGattConnected(),
+          web_bluetooth_service_->IsDevicePaired(device.GetAddress()),
+          rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1);
+    }
   }
 }
 
diff --git a/content/browser/bluetooth/bluetooth_metrics.cc b/content/browser/bluetooth/bluetooth_metrics.cc
index dcbc576f..7a0b4722 100644
--- a/content/browser/bluetooth/bluetooth_metrics.cc
+++ b/content/browser/bluetooth/bluetooth_metrics.cc
@@ -101,12 +101,14 @@
     union_of_services.insert(service.canonical_value());
   }
 
-  for (const auto& filter : options->filters) {
-    if (!filter->services) {
-      continue;
-    }
-    for (const BluetoothUUID& service : filter->services.value()) {
-      union_of_services.insert(service.canonical_value());
+  if (options->filters) {
+    for (const auto& filter : options->filters.value()) {
+      if (!filter->services) {
+        continue;
+      }
+      for (const BluetoothUUID& service : filter->services.value()) {
+        union_of_services.insert(service.canonical_value());
+      }
     }
   }
 
@@ -124,7 +126,13 @@
 
 void RecordRequestDeviceOptions(
     const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
-  RecordRequestDeviceFilters(options->filters);
+  UMA_HISTOGRAM_BOOLEAN("Bluetooth.Web.RequestDevice.Options.AcceptAllDevices",
+                        options->accept_all_devices);
+
+  if (options->filters) {
+    RecordRequestDeviceFilters(options->filters.value());
+  }
+
   RecordRequestDeviceOptionalServices(options->optional_services);
   RecordUnionOfServices(options);
 }
diff --git a/content/renderer/bluetooth/bluetooth_type_converters.cc b/content/renderer/bluetooth/bluetooth_type_converters.cc
index 5055d7c..55a0d8bd 100644
--- a/content/renderer/bluetooth/bluetooth_type_converters.cc
+++ b/content/renderer/bluetooth/bluetooth_type_converters.cc
@@ -40,14 +40,21 @@
   blink::mojom::WebBluetoothRequestDeviceOptionsPtr options =
       blink::mojom::WebBluetoothRequestDeviceOptions::New();
 
-  for (const auto& filter : web_options.filters) {
-    options->filters.push_back(blink::mojom::WebBluetoothScanFilter::From<
-                               blink::WebBluetoothScanFilter>(filter));
+  options->accept_all_devices = web_options.acceptAllDevices;
+
+  if (web_options.hasFilters) {
+    options->filters.emplace();
+    for (const auto& filter : web_options.filters) {
+      options->filters->push_back(blink::mojom::WebBluetoothScanFilter::From<
+                                  blink::WebBluetoothScanFilter>(filter));
+    }
   }
+
   for (const auto& optional_service : web_options.optionalServices) {
     options->optional_services.push_back(
         device::BluetoothUUID(optional_service.utf8()));
   }
+
   return options;
 }
 
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
index 738685a..16b3c54 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -188,6 +188,10 @@
     return GetMissingCharacteristicHeartRateAdapter();
   if (fake_adapter_name == "HeartRateAdapter")
     return GetHeartRateAdapter();
+  if (fake_adapter_name == "EmptyNameDeviceAdapter")
+    return GetEmptyNameDeviceAdapter();
+  if (fake_adapter_name == "NoNameDeviceAdapter")
+    return GetNoNameDeviceAdapter();
   if (fake_adapter_name == "EmptyNameHeartRateAdapter")
     return GetEmptyNameHeartRateAdapter();
   if (fake_adapter_name == "NoNameHeartRateAdapter")
@@ -715,6 +719,28 @@
 
 // static
 scoped_refptr<NiceMockBluetoothAdapter>
+LayoutTestBluetoothAdapterProvider::GetEmptyNameDeviceAdapter() {
+  scoped_refptr<NiceMockBluetoothAdapter> adapter(GetEmptyAdapter());
+  std::unique_ptr<NiceMockBluetoothDevice> device(
+      GetConnectableDevice(adapter.get(), "" /* device_name */));
+
+  adapter->AddMockDevice(std::move(device));
+  return adapter;
+}
+
+// static
+scoped_refptr<NiceMockBluetoothAdapter>
+LayoutTestBluetoothAdapterProvider::GetNoNameDeviceAdapter() {
+  scoped_refptr<NiceMockBluetoothAdapter> adapter(GetEmptyAdapter());
+  std::unique_ptr<NiceMockBluetoothDevice> device(
+      GetConnectableDevice(adapter.get(), nullptr /* device_name */));
+
+  adapter->AddMockDevice(std::move(device));
+  return adapter;
+}
+
+// static
+scoped_refptr<NiceMockBluetoothAdapter>
 LayoutTestBluetoothAdapterProvider::GetEmptyNameHeartRateAdapter() {
   scoped_refptr<NiceMockBluetoothAdapter> adapter(GetEmptyAdapter());
   std::unique_ptr<NiceMockBluetoothDevice> device(
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
index 6c9fb9ee..114de82 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -233,6 +233,18 @@
   static scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>>
   GetHeartRateAdapter();
 
+  // |GetEmptyNameDeviceAdapter|
+  // Inherits from |EmptyAdapter|
+  // Contains a single device with an empty name and no UUIDs.
+  static scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>>
+  GetEmptyNameDeviceAdapter();
+
+  // |GetNoNameDeviceAdapter|
+  // Inherits from |EmptyAdapter|
+  // Contains a single device with no name and no UUIDs.
+  static scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>>
+  GetNoNameDeviceAdapter();
+
   // |GetEmptyNameHeartRateAdapter|
   // Inherits from |EmptyAdapter|
   // Internal Structure:
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 7dcf1fb4..719c6b1b 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -564,6 +564,10 @@
 
     self.Fail('conformance2/textures/misc/tex-mipmap-levels.html',
        ['linux', 'intel'], bug=666384)
+
+    self.Fail('conformance2/textures/misc/tex-subimage3d-pixel-buffer-bug.html',
+       ['linux', 'intel'], bug=662644) # WebGL 2.0.1
+
     self.Fail('deqp/functional/gles3/shadertexturefunction/texturesize.html',
        ['linux', 'intel'], bug=666384)
 
diff --git a/docs/windows_build_instructions.md b/docs/windows_build_instructions.md
index f255027..3d41e82 100644
--- a/docs/windows_build_instructions.md
+++ b/docs/windows_build_instructions.md
@@ -99,7 +99,7 @@
 dependencies.
 
 ```shell
-$ fetch ios
+$ fetch chromium
 ```
 
 If you don't want the full repo history, you can save a lot of time by
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 56f6358..6a54c4ae 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -385,6 +385,7 @@
 crbug.com/563265 editing/spelling/spellcheck-editable-on-focus-sync.html [ Skip ]
 
 crbug.com/657946 [ Mac ] virtual/color_space/fast/canvas/color-space/display_linear-rgb.html [ Failure ]
+crbug.com/671048 [ Win ] virtual/color_space/fast/canvas/color-space/display_linear-rgb.html [ Failure ]
 
 crbug.com/538697 [ Win7 Debug ] virtual/threaded/printing/webgl-oversized-printing.html [ Failure Crash ]
 crbug.com/538697 [ Win7 Debug ] printing/webgl-oversized-printing.html [ Failure Crash ]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-empty-name.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-empty-name.html
new file mode 100644
index 0000000..d64507d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-empty-name.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script>
+'use strict';
+promise_test(() => {
+  return setBluetoothFakeAdapter('EmptyNameDeviceAdapter')
+    .then(() => requestDeviceWithKeyDown({acceptAllDevices: true}))
+    .then(device => {
+      assert_equals(device.name, '');
+    });
+}, 'Device with empty name and no UUIDs nearby. Should be found if ' +
+   'acceptAllDevices is true.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-name.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-name.html
new file mode 100644
index 0000000..f1241544
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-name.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script>
+promise_test(() => {
+  // The UnicodeDevice's name is '❤❤❤❤❤❤❤❤❤'. ❤ = \u2764
+  let device_name = generate_string(9, '\u2764');
+  return setBluetoothFakeAdapter('UnicodeDeviceAdapter')
+    .then(() => requestDeviceWithKeyDown({acceptAllDevices: true}))
+    .then(device => {
+      assert_equals(device.name, device_name);
+    });
+}, 'A device with name and no UUIDs nearby. Should be found if ' +
+   'acceptAllDevices is true.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.html
new file mode 100644
index 0000000..9cb42a77
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script>
+'use strict';
+promise_test(() => {
+  return setBluetoothFakeAdapter('NoNameDeviceAdapter')
+    .then(() => requestDeviceWithKeyDown({acceptAllDevices: true}))
+    .then(device => {
+      assert_true(device.name === null);
+    });
+}, 'Device with no name or UUIDs nearby. Should be found if ' +
+   'acceptAllDevices is true.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.html
new file mode 100644
index 0000000..8bca279
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script>
+'use strict';
+promise_test(() => {
+  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
+    .then(() => requestDeviceWithKeyDown({acceptAllDevices: true}))
+    .then(device => {
+      assert_true(device.name === null);
+    });
+}, 'Device with only UUIDs nearby. Should be found if ' +
+   'acceptAllDevices is true.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html
new file mode 100644
index 0000000..f1c028f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script>
+'use strict';
+promise_test(() => {
+  return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter')
+    .then(() => requestDeviceWithKeyDown({acceptAllDevices: true}))
+    .then(device => device.gatt.connect())
+    .then(gattServer => assert_promise_rejects_with_message(
+      gattServer.getPrimaryServices(),
+      new DOMException(
+        'Origin is not allowed to access any service. ' +
+        'Tip: Add the service UUID to \'optionalServices\' in ' +
+        'requestDevice() options. https://goo.gl/HxfxSQ',
+        'SecurityError')));
+}, 'requestDevice called with acceptAllDevices: true and with no ' +
+   'optionalServices. Should not get access to any services.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-present.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-present.html
new file mode 100644
index 0000000..96a7d46
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-present.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script>
+'use strict';
+promise_test(() => {
+  return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter')
+    .then(() => requestDeviceWithKeyDown({
+      acceptAllDevices: true,
+      optionalServices: ['heart_rate']
+    }))
+    .then(device => device.gatt.connect())
+    .then(gattServer => gattServer.getPrimaryServices())
+    .then(services => {
+      assert_equals(services.length, 2);
+      services.forEach(service => {
+        assert_equals(service.uuid, BluetoothUUID.getService('heart_rate'));
+      });
+    })
+}, 'requestDevice called with acceptAllDevices: true and with ' +
+   'optionalServices. Should get access to services.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/canonicalizeFilter/filters-xor-acceptAllDevices.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/canonicalizeFilter/filters-xor-acceptAllDevices.html
new file mode 100644
index 0000000..fc817ee
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/canonicalizeFilter/filters-xor-acceptAllDevices.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script>
+'use strict';
+let test_specs = [
+  {},
+  {optionalServices: ['heart_rate']},
+  {filters: [], acceptAllDevices: true},
+  {filters: [], acceptAllDevices: true, optionalServices: ['heart_rate']}
+];
+
+promise_test(t => {
+  let test_promises = Promise.resolve();
+  test_specs.forEach(args => {
+    test_promises = test_promises
+      .then(() => assert_promise_rejects_with_message(
+        requestDeviceWithKeyDown(args),
+        new TypeError(
+          'Failed to execute \'requestDevice\' on \'Bluetooth\': ' +
+          'Either \'filters\' should be present or ' +
+          '\'acceptAllDevices\' should be true, but not both.')));
+  });
+  return test_promises;
+}, 'RequestDeviceOptions should have exactly one of \'filters\' or ' +
+   '\'acceptAllDevices:true\'. Reject with TypeError if not.')
+</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/canonicalizeFilter/no-filters-member.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/canonicalizeFilter/no-filters-member.html
deleted file mode 100644
index 5108cba..0000000
--- a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/canonicalizeFilter/no-filters-member.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
-<script>
-'use strict';
-
-let test_specs = [
-  {}, {
-  optionalServices: ['wrong_service']
-}];
-
-promise_test(t => {
-  let test_promises = Promise.resolve();
-  test_specs.forEach(args => {
-  test_promises = test_promises.then(() => promise_rejects(
-    t, new TypeError(), requestDeviceWithKeyDown(args)));
-  });
-  return test_promises;
-}, 'RequestDeviceOptions requires a |filters| member.');
-</script>
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 74ef4383..02d27786 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -1809,6 +1809,8 @@
                        previousBlockFlow->lowestFloatLogicalBottom();
     if (lowestFloat > logicalTop)
       addOverhangingFloats(previousBlockFlow, false);
+    else
+      break;
     LayoutObject* prev = previousBlockFlow->previousSibling();
     if (prev && prev->isLayoutBlockFlow())
       previousBlockFlow = toLayoutBlockFlow(prev);
diff --git a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
index c89a794..bcf62af 100644
--- a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
@@ -100,27 +100,38 @@
 static void convertRequestDeviceOptions(const RequestDeviceOptions& options,
                                         WebRequestDeviceOptions& result,
                                         ExceptionState& exceptionState) {
-  ASSERT(options.hasFilters());
-
-  if (options.filters().isEmpty()) {
+  if (!(options.hasFilters() ^ options.acceptAllDevices())) {
     exceptionState.throwTypeError(
-        "'filters' member must be non-empty to find any devices.");
+        "Either 'filters' should be present or 'acceptAllDevices' should be "
+        "true, but not both.");
+    return;
   }
 
-  Vector<WebBluetoothScanFilter> filters;
-  for (const BluetoothScanFilterInit& filter : options.filters()) {
-    WebBluetoothScanFilter canonicalizedFilter = WebBluetoothScanFilter();
+  result.acceptAllDevices = options.acceptAllDevices();
 
-    canonicalizeFilter(filter, canonicalizedFilter, exceptionState);
-
-    if (exceptionState.hadException())
+  result.hasFilters = options.hasFilters();
+  if (result.hasFilters) {
+    if (options.filters().isEmpty()) {
+      exceptionState.throwTypeError(
+          "'filters' member must be non-empty to find any devices.");
       return;
+    }
 
-    filters.append(canonicalizedFilter);
+    Vector<WebBluetoothScanFilter> filters;
+    for (const BluetoothScanFilterInit& filter : options.filters()) {
+      WebBluetoothScanFilter canonicalizedFilter = WebBluetoothScanFilter();
+
+      canonicalizeFilter(filter, canonicalizedFilter, exceptionState);
+
+      if (exceptionState.hadException())
+        return;
+
+      filters.append(canonicalizedFilter);
+    }
+
+    result.filters.assign(filters);
   }
 
-  result.filters.assign(filters);
-
   if (options.hasOptionalServices()) {
     Vector<WebString> optionalServices;
     for (const StringOrUnsignedLong& optionalService :
@@ -172,16 +183,16 @@
                                        ExceptionState& exceptionState) {
   ExecutionContext* context = scriptState->getExecutionContext();
 
-  // 1. If the incumbent settings object is not a secure context, reject promise
-  //    with a SecurityError and abort these steps.
+  // If the incumbent settings object is not a secure context, reject promise
+  // with a SecurityError and abort these steps.
   String errorMessage;
   if (!context->isSecureContext(errorMessage)) {
     return ScriptPromise::rejectWithDOMException(
         scriptState, DOMException::create(SecurityError, errorMessage));
   }
 
-  // 2. If the algorithm is not allowed to show a popup, reject promise with a
-  //    SecurityError and abort these steps.
+  // If the algorithm is not allowed to show a popup, reject promise with a
+  // SecurityError and abort these steps.
   if (!UserGestureIndicator::consumeUserGesture()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
@@ -196,8 +207,8 @@
     return ScriptPromise::rejectWithDOMException(
         scriptState, DOMException::create(NotSupportedError));
 
-  // 3. In order to convert the arguments from service names and aliases to just
-  //    UUIDs, do the following substeps:
+  // In order to convert the arguments from service names and aliases to just
+  // UUIDs, do the following substeps:
   WebRequestDeviceOptions webOptions;
   convertRequestDeviceOptions(options, webOptions, exceptionState);
   if (exceptionState.hadException())
diff --git a/third_party/WebKit/Source/modules/bluetooth/RequestDeviceOptions.idl b/third_party/WebKit/Source/modules/bluetooth/RequestDeviceOptions.idl
index e231923..8bef76b6 100644
--- a/third_party/WebKit/Source/modules/bluetooth/RequestDeviceOptions.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/RequestDeviceOptions.idl
@@ -5,6 +5,7 @@
 // https://webbluetoothcg.github.io/web-bluetooth/#dictdef-requestdeviceoptions
 
 dictionary RequestDeviceOptions {
-    required sequence<BluetoothScanFilterInit>  filters;
+    sequence<BluetoothScanFilterInit>  filters;
     sequence<BluetoothServiceUUID> optionalServices = [];
+    boolean acceptAllDevices = false;
 };
diff --git a/third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h b/third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h
index 27cf9aa..c7a96d3c 100644
--- a/third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h
+++ b/third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h
@@ -30,7 +30,9 @@
   WebRequestDeviceOptions() {}
 
   WebVector<WebBluetoothScanFilter> filters;
+  bool hasFilters;
   WebVector<WebString> optionalServices;
+  bool acceptAllDevices;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom b/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom
index aa6d4861..b1eca7b 100644
--- a/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom
+++ b/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom
@@ -78,8 +78,9 @@
 };
 
 struct WebBluetoothRequestDeviceOptions {
-  array<WebBluetoothScanFilter> filters;
+  array<WebBluetoothScanFilter>? filters;
   array<bluetooth.mojom.UUID> optional_services;
+  bool accept_all_devices;
 };
 
 // Indicates if the function will return a single or multiple
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3d7ff895..83a7d1c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4848,6 +4848,18 @@
   </summary>
 </histogram>
 
+<histogram name="Bluetooth.Web.RequestDevice.Options.AcceptAllDevices"
+    enum="Boolean">
+  <owner>jyasskin@chromium.org</owner>
+  <owner>ortuno@chromium.org</owner>
+  <owner>scheib@chromium.org</owner>
+  <summary>
+    Records the value of 'acceptAllDevices' in RequestDeviceOptions. These
+    results will help us better understand the uses of the API and make changes
+    according to developers' behavior.
+  </summary>
+</histogram>
+
 <histogram name="Bluetooth.Web.RequestDevice.Outcome"
     enum="WebBluetoothRequestDeviceOutcome">
   <owner>jyasskin@chromium.org</owner>
@@ -76456,6 +76468,7 @@
   <int value="155" label="MDDH_INVALID_SUBSCRIPTION_REQUEST"/>
   <int value="156" label="MDDH_INVALID_UNSUBSCRIPTION_REQUEST"/>
   <int value="157" label="AOAH_NONSENSE_DEVICE_ID"/>
+  <int value="158" label="BDH_INVALID_OPTIONS"/>
 </enum>
 
 <enum name="BadMessageReasonExtensions" type="int">
diff --git a/tools/perf/generate_perf_json.py b/tools/perf/generate_perf_json.py
index 4816c8fc..eb36487 100755
--- a/tools/perf/generate_perf_json.py
+++ b/tools/perf/generate_perf_json.py
@@ -561,7 +561,7 @@
 ]
 
 def current_benchmarks(use_whitelist):
-  benchmarks_dir = os.path.join(os.getcwd(), 'benchmarks')
+  benchmarks_dir = os.path.join(src_dir(), 'tools', 'perf', 'benchmarks')
   top_level_dir = os.path.dirname(benchmarks_dir)
 
   all_benchmarks = discover.DiscoverClasses(
@@ -588,8 +588,10 @@
   runtime_list = []
   benchmark_avgs = {}
   new_benchmarks = []
+  timing_file_path = os.path.join(src_dir(), 'tools', 'perf',
+      'desktop_benchmark_avg_times.json')
   # Load in the avg times as calculated on Nov 1st, 2016
-  with open('desktop_benchmark_avg_times.json') as f:
+  with open(timing_file_path) as f:
     benchmark_avgs = json.load(f)
 
   for benchmark in all_benchmarks:
@@ -683,19 +685,16 @@
   tests['AAAAA2 See //tools/perf/generate_perf_json.py to make changes'] = {}
   filename = '%s.json' % waterfall['name']
 
-  src_dir = os.path.dirname(os.path.dirname(os.getcwd()))
-
-  with open(os.path.join(src_dir, 'testing', 'buildbot', filename), 'w') as fp:
+  buildbot_dir = os.path.join(src_dir(), 'testing', 'buildbot')
+  with open(os.path.join(buildbot_dir, filename), 'w') as fp:
     json.dump(tests, fp, indent=2, separators=(',', ': '), sort_keys=True)
     fp.write('\n')
 
-def chdir_to_parent_directory():
-  parent_directory = os.path.dirname(os.path.abspath(__file__))
-  os.chdir(parent_directory)
+def src_dir():
+  file_path = os.path.abspath(__file__)
+  return os.path.dirname(os.path.dirname(os.path.dirname(file_path)))
 
 def main():
-  chdir_to_parent_directory()
-
   waterfall = get_waterfall_config()
   waterfall['name'] = 'chromium.perf'
   fyi_waterfall = get_fyi_waterfall_config()