diff --git a/DEPS b/DEPS
index d96feba..0a0b968 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,11 @@
   # 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': '844a0b425741f07cb233332405143931586bbb7d',
+  'skia_revision': '6950de6c4166fabb35e6c756fc009e0cf1c47819',
   # 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': '23533853f416feadfc1b39db7501837d4bf5f7fa',
+  'v8_revision': '935b8785b9c5c7e29732c0a4830704e4be4d13f5',
   # 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.
@@ -187,7 +187,7 @@
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/libvpx_new/source/libvpx':
-   Var('chromium_git') + '/webm/libvpx.git' + '@' +  'c6641709a707ccb98cbdf785428659e44d4f2c8b',
+   Var('chromium_git') + '/webm/libvpx.git' + '@' +  'eba14ddbe7e7b69803dab770ba25ae2ba75c65e2',
 
   'src/third_party/ffmpeg':
    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'd2733b2c43f65f0e779d5d014777fb8ea1e89873',
@@ -280,7 +280,7 @@
 
   'src/third_party/catapult':
     Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' +
-    'e2c6869c72944a7a7a729c7ccc9fdc1f8f90de8e',
+    '53ddd9ffa0a29872a62b8288a4adefb7ec3f590d',
 }
 
 
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn
index 862b450..70ebeaa 100644
--- a/base/trace_event/BUILD.gn
+++ b/base/trace_event/BUILD.gn
@@ -71,14 +71,17 @@
     ]
   }
 
-  if (is_linux || is_android) {
+  if (is_linux || is_android || is_mac) {
     sources += [
       "malloc_dump_provider.cc",
       "malloc_dump_provider.h",
-      "process_memory_maps_dump_provider.cc",
     ]
   }
 
+  if (is_linux || is_android) {
+    sources += [ "process_memory_maps_dump_provider.cc" ]
+  }
+
   configs += [ "//base:base_implementation" ]
 
   deps = [
diff --git a/base/trace_event/malloc_dump_provider.cc b/base/trace_event/malloc_dump_provider.cc
index 914c684..5279ab0c 100644
--- a/base/trace_event/malloc_dump_provider.cc
+++ b/base/trace_event/malloc_dump_provider.cc
@@ -4,7 +4,11 @@
 
 #include "base/trace_event/malloc_dump_provider.h"
 
+#if defined(OS_MACOSX)
+#include <malloc/malloc.h>
+#else
 #include <malloc.h>
+#endif
 
 #include "base/allocator/allocator_extension_thunks.h"
 #include "base/trace_event/process_memory_dump.h"
@@ -21,11 +25,9 @@
                    LeakySingletonTraits<MallocDumpProvider>>::get();
 }
 
-MallocDumpProvider::MallocDumpProvider() {
-}
+MallocDumpProvider::MallocDumpProvider() {}
 
-MallocDumpProvider::~MallocDumpProvider() {
-}
+MallocDumpProvider::~MallocDumpProvider() {}
 
 // Called at trace dump point time. Creates a snapshot the memory counters for
 // the current process.
@@ -34,7 +36,13 @@
   size_t total_virtual_size = 0;
   size_t resident_size = 0;
   size_t allocated_objects_size = 0;
-
+#if defined(OS_MACOSX) || defined(OS_IOS)
+  malloc_statistics_t stats = {0};
+  malloc_zone_statistics(nullptr, &stats);
+  total_virtual_size = stats.size_allocated;
+  resident_size = stats.size_in_use;
+  allocated_objects_size = stats.size_in_use;
+#else
   allocator::thunks::GetNumericPropertyFunction get_property_function =
       allocator::thunks::GetGetNumericPropertyFunction();
   if (get_property_function) {
@@ -58,6 +66,7 @@
     resident_size = info.uordblks;
     allocated_objects_size = info.uordblks;
   }
+#endif
 
   MemoryAllocatorDump* outer_dump = pmd->CreateAllocatorDump("malloc");
   outer_dump->AddScalar("virtual_size", MemoryAllocatorDump::kUnitsBytes,
diff --git a/base/trace_event/malloc_dump_provider.h b/base/trace_event/malloc_dump_provider.h
index f351999..f463d0a6 100644
--- a/base/trace_event/malloc_dump_provider.h
+++ b/base/trace_event/malloc_dump_provider.h
@@ -7,8 +7,15 @@
 
 #include <istream>
 
+#include "base/macros.h"
 #include "base/memory/singleton.h"
 #include "base/trace_event/memory_dump_provider.h"
+#include "build/build_config.h"
+
+#if defined(OS_LINUX) || defined(OS_ANDROID) || \
+    (defined(OS_MACOXS) && !defined(OS_IOS))
+#define SUPPORTS_MALLOC_MEMORY_TRACING
+#endif
 
 namespace base {
 namespace trace_event {
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index eec2ff39..43c784b 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -12,6 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/threading/thread.h"
+#include "base/trace_event/malloc_dump_provider.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "base/trace_event/memory_dump_session_state.h"
 #include "base/trace_event/memory_profiler_allocation_context.h"
@@ -24,7 +25,6 @@
 #endif
 
 #if defined(OS_LINUX) || defined(OS_ANDROID)
-#include "base/trace_event/malloc_dump_provider.h"
 #include "base/trace_event/process_memory_maps_dump_provider.h"
 #endif
 
@@ -96,7 +96,7 @@
 
 // static
 const char* const MemoryDumpManager::kSystemAllocatorPoolName =
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(SUPPORTS_MALLOC_MEMORY_TRACING)
     MallocDumpProvider::kAllocatedObjects;
 #elif defined(OS_WIN)
     WinHeapDumpProvider::kAllocatedObjects;
@@ -155,10 +155,13 @@
                        "ProcessMemoryTotals", nullptr);
 #endif
 
+#if defined(SUPPORTS_MALLOC_MEMORY_TRACING)
+  RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr);
+#endif
+
 #if defined(OS_LINUX) || defined(OS_ANDROID)
   RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance(),
                        "ProcessMemoryMaps", nullptr);
-  RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr);
 #endif
 
 #if defined(OS_ANDROID)
diff --git a/base/trace_event/process_memory_totals.cc b/base/trace_event/process_memory_totals.cc
index 1270924f..de27ab3d 100644
--- a/base/trace_event/process_memory_totals.cc
+++ b/base/trace_event/process_memory_totals.cc
@@ -17,6 +17,8 @@
       is_peak_rss_resetable_(false) {
 }
 
+ProcessMemoryTotals::~ProcessMemoryTotals() {}
+
 void ProcessMemoryTotals::AsValueInto(TracedValue* value) const {
   value->SetString("resident_set_bytes",
                    StringPrintf("%" PRIx64, resident_set_bytes_));
@@ -25,11 +27,21 @@
                      StringPrintf("%" PRIx64, peak_resident_set_bytes_));
     value->SetBoolean("is_peak_rss_resetable", is_peak_rss_resetable_);
   }
+
+  for (const auto it : extra_fields_) {
+    value->SetString(it.first, StringPrintf("%" PRIx64, it.second));
+  }
 }
 
 void ProcessMemoryTotals::Clear() {
   resident_set_bytes_ = 0;
 }
 
+void ProcessMemoryTotals::SetExtraFieldInBytes(const char* name,
+                                               uint64_t value) {
+  DCHECK_EQ(0u, extra_fields_.count(name));
+  extra_fields_[name] = value;
+}
+
 }  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/process_memory_totals.h b/base/trace_event/process_memory_totals.h
index 1bf8bdc..eb7757c9 100644
--- a/base/trace_event/process_memory_totals.h
+++ b/base/trace_event/process_memory_totals.h
@@ -5,6 +5,8 @@
 #ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_TOTALS_H_
 #define BASE_TRACE_EVENT_PROCESS_MEMORY_TOTALS_H_
 
+#include <map>
+
 #include "base/base_export.h"
 #include "base/basictypes.h"
 
@@ -17,6 +19,7 @@
 class BASE_EXPORT ProcessMemoryTotals {
  public:
   ProcessMemoryTotals();
+  ~ProcessMemoryTotals();
 
   // Called at trace generation time to populate the TracedValue.
   void AsValueInto(TracedValue* value) const;
@@ -24,11 +27,11 @@
   // Clears up all the data collected.
   void Clear();
 
-  uint64 resident_set_bytes() const { return resident_set_bytes_; }
-  void set_resident_set_bytes(uint64 value) { resident_set_bytes_ = value; }
+  uint64_t resident_set_bytes() const { return resident_set_bytes_; }
+  void set_resident_set_bytes(uint64_t value) { resident_set_bytes_ = value; }
 
-  uint64 peak_resident_set_bytes() const { return peak_resident_set_bytes_; }
-  void set_peak_resident_set_bytes(uint64 value) {
+  uint64_t peak_resident_set_bytes() const { return peak_resident_set_bytes_; }
+  void set_peak_resident_set_bytes(uint64_t value) {
     peak_resident_set_bytes_ = value;
   }
 
@@ -39,11 +42,16 @@
   bool is_peak_rss_resetable() const { return is_peak_rss_resetable_; }
   void set_is_peak_rss_resetable(bool value) { is_peak_rss_resetable_ = value; }
 
+  void SetExtraFieldInBytes(const char* name, uint64_t value);
+
  private:
-  uint64 resident_set_bytes_;
-  uint64 peak_resident_set_bytes_;
+  uint64_t resident_set_bytes_;
+  uint64_t peak_resident_set_bytes_;
   bool is_peak_rss_resetable_;
 
+  // Extra metrics for OS-specific statistics.
+  std::map<const char*, uint64_t> extra_fields_;
+
   DISALLOW_COPY_AND_ASSIGN(ProcessMemoryTotals);
 };
 
diff --git a/base/trace_event/process_memory_totals_dump_provider.cc b/base/trace_event/process_memory_totals_dump_provider.cc
index a861720..c057deb 100644
--- a/base/trace_event/process_memory_totals_dump_provider.cc
+++ b/base/trace_event/process_memory_totals_dump_provider.cc
@@ -77,6 +77,13 @@
     }
     close(clear_refs_fd);
   }
+#elif defined(OS_MACOSX)
+  size_t private_bytes;
+  bool res = process_metrics_->GetMemoryBytes(&private_bytes,
+                                              nullptr /* shared_bytes */);
+  if (res) {
+    pmd->process_totals()->SetExtraFieldInBytes("private_bytes", private_bytes);
+  }
 #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
 #endif  // !defined(OS_IOS)
 
diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi
index db87e4b1c..4713311 100644
--- a/base/trace_event/trace_event.gypi
+++ b/base/trace_event/trace_event.gypi
@@ -81,10 +81,14 @@
       'trace_event/winheap_dump_provider_win_unittest.cc',
     ],
     'conditions': [
+      ['OS == "linux" or OS=="android" or OS=="mac"', {
+        'trace_event_sources': [
+          'trace_event/malloc_dump_provider.cc',
+          'trace_event/malloc_dump_provider.h',
+        ],
+      }],
       ['OS == "linux" or OS == "android"', {
           'trace_event_sources': [
-            'trace_event/malloc_dump_provider.cc',
-            'trace_event/malloc_dump_provider.h',
             'trace_event/process_memory_maps_dump_provider.cc',
           ],
           'trace_event_test_sources' : [
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index 1f9ee3ef..5ed3968 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -147,6 +147,24 @@
 }
 #endif
 
+void TestPromptNotShown(const char* failure_message,
+                        content::WebContents* web_contents,
+                        content::RenderViewHost* rvh) {
+  SCOPED_TRACE(testing::Message(failure_message));
+
+  NavigationObserver observer(web_contents);
+  scoped_ptr<PromptObserver> prompt_observer(
+      PromptObserver::Create(web_contents));
+  std::string fill_and_submit =
+      "document.getElementById('username_failed').value = 'temp';"
+      "document.getElementById('password_failed').value = 'random';"
+      "document.getElementById('failed_form').submit()";
+
+  ASSERT_TRUE(content::ExecuteScript(rvh, fill_and_submit));
+  observer.Wait();
+  EXPECT_FALSE(prompt_observer->IsShowingPrompt());
+}
+
 }  // namespace
 
 namespace password_manager {
@@ -170,6 +188,25 @@
 }
 
 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
+                       NoPromptIfFormReappeared) {
+  NavigateToFile("/password/failed.html");
+  TestPromptNotShown("normal form", WebContents(), RenderViewHost());
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
+                       NoPromptIfFormReappearedWithPartsHidden) {
+  NavigateToFile("/password/failed_partly_visible.html");
+  TestPromptNotShown("partly visible form", WebContents(), RenderViewHost());
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
+                       NoPromptIfFormReappearedInputOutsideFor) {
+  NavigateToFile("/password/failed_input_outside.html");
+  TestPromptNotShown("form with input outside", WebContents(),
+                     RenderViewHost());
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
                        PromptForSubmitWithInPageNavigation) {
   NavigateToFile("/password/password_navigate_before_submit.html");
 
diff --git a/chrome/test/data/password/failed.html b/chrome/test/data/password/failed.html
index fd52805..7d12460 100644
--- a/chrome/test/data/password/failed.html
+++ b/chrome/test/data/password/failed.html
@@ -1,7 +1,7 @@
 <html>
 <body>
 Navigation complete. Below is the login form again, a sign of failure.
-<form method="POST" action="failed.html" id="to_failed">
+<form method="POST" action="failed.html" id="failed_form">
   <input type="text" id="username_failed" name="username_failed">
   <input type="password" id="password_failed" name="password_failed">
   <input type="submit" id="submit_failed" name="submit_failed">
diff --git a/chrome/test/data/password/failed_input_outside.html b/chrome/test/data/password/failed_input_outside.html
new file mode 100644
index 0000000..d23b7b46
--- /dev/null
+++ b/chrome/test/data/password/failed_input_outside.html
@@ -0,0 +1,14 @@
+<html>
+<body>
+Navigation complete. Below is the login form again, a sign of failure.
+<form method="POST" action="failed_input_outside.html" id="failed_form">
+</form>
+
+<input type="text" id="username_failed" name="username_failed"
+       form="failed_form">
+<input type="password" id="password_failed" name="password_failed"
+       form="failed_form">
+<input type="submit" id="submit_failed" name="submit_failed"
+       form="failed_form">
+</body>
+</html>
diff --git a/chrome/test/data/password/failed_partly_visible.html b/chrome/test/data/password/failed_partly_visible.html
new file mode 100644
index 0000000..c618bff8
--- /dev/null
+++ b/chrome/test/data/password/failed_partly_visible.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+  <style>
+    .absolute {
+      position: absolute;
+    }
+    .hidden {
+      display: none;
+    }
+  </style>
+</head>
+<body>
+This form comes from http://crbug.com/549149#c4.
+<form method="POST" action="failed_partly_visible.html" id="failed_form">
+  <div class="absolute">
+    <div class="hidden">
+    <input type="submit" id="hidden_submit">
+    </div>
+  </div>
+  <div class="absolute">
+    <input type="text" id="username_failed">
+    <input type="password" id="password_failed">
+  </div>
+</form>
+
+</body>
+</html>
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index d003028..f15a5806 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -615,7 +615,7 @@
 
   // Assume form submission only if the form is now gone, either invisible or
   // removed from the DOM.
-  if (form_util::IsFormVisible(last_interacted_form_))
+  if (form_util::AreFormContentsVisible(last_interacted_form_))
     return;
 
   // Could not find a visible form equal to our saved form, assume submission.
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index e6b456d..c044532 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1090,17 +1090,6 @@
 
 }  // namespace
 
-bool IsNamedElementVisible(
-    const std::vector<blink::WebFormControlElement>& control_elements,
-    const base::string16& name) {
-  for (size_t i = 0; i < control_elements.size(); ++i) {
-    if (control_elements[i].nameForAutofill() == name) {
-      return IsWebNodeVisible(control_elements[i]);
-    }
-  }
-  return false;
-}
-
 bool ExtractFormData(const WebFormElement& form_element, FormData* data) {
   return WebFormElementToFormData(
       form_element, WebFormControlElement(),
@@ -1112,10 +1101,9 @@
 bool IsFormVisible(blink::WebFrame* frame,
                    const GURL& canonical_action,
                    const GURL& canonical_origin,
-                   const FormData& form_data,
-                   const FormsPredictionsMap& form_predictions) {
+                   const FormData& form_data) {
   const GURL frame_url = GURL(frame->document().url().string().utf8());
-  blink::WebVector<blink::WebFormElement> forms;
+  blink::WebVector<WebFormElement> forms;
   frame->document().forms(forms);
 
 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
@@ -1128,9 +1116,8 @@
   // to the page URL, this method checks ALL fields of the form instead (using
   // FormData.SameFormAs). This is also true if the action was set to the page
   // URL on purpose.
-  for (size_t i = 0; i < forms.size(); ++i) {
-    const blink::WebFormElement& form = forms[i];
-    if (!IsWebNodeVisible(form))
+  for (const WebFormElement& form : forms) {
+    if (!AreFormContentsVisible(form))
       continue;
 
     GURL iter_canonical_action = GetCanonicalActionForForm(form);
@@ -1142,8 +1129,8 @@
 
     if (action_is_empty) {  // Both actions are empty, compare all fields.
       FormData extracted_form_data;
-      WebFormElementToFormData(form, blink::WebFormControlElement(),
-                               EXTRACT_NONE, &extracted_form_data, nullptr);
+      WebFormElementToFormData(form, WebFormControlElement(), EXTRACT_NONE,
+                               &extracted_form_data, nullptr);
       if (form_data.SameFormAs(extracted_form_data)) {
         return true;  // Form still exists.
       }
@@ -1162,12 +1149,19 @@
   return false;
 }
 
-bool IsFormVisible(const WebFormElement& form) {
-  FormData form_data;
-  return ExtractFormData(form, &form_data) &&
-         IsFormVisible(form.document().frame(), GetCanonicalActionForForm(form),
-                       GetCanonicalOriginForDocument(form.document()),
-                       form_data, FormsPredictionsMap());
+bool IsSomeControlElementVisible(
+    const WebVector<WebFormControlElement>& control_elements) {
+  for (const WebFormControlElement& control_element : control_elements) {
+    if (IsWebNodeVisible(control_element))
+      return true;
+  }
+  return false;
+}
+
+bool AreFormContentsVisible(const WebFormElement& form) {
+  WebVector<WebFormControlElement> control_elements;
+  form.getFormControlElements(control_elements);
+  return IsSomeControlElementVisible(control_elements);
 }
 
 GURL GetCanonicalActionForForm(const WebFormElement& form) {
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index d26ac6d..5632c66 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -56,12 +56,6 @@
 // Copied to components/autofill/ios/browser/resources/autofill_controller.js.
 extern const size_t kMaxParseableFields;
 
-// Returns true if |control_elements| contains an element named |name| and is
-// visible.
-bool IsNamedElementVisible(
-    const std::vector<blink::WebFormControlElement>& control_elements,
-    const base::string16& name);
-
 // Extract FormData from the form element and return whether the operation was
 // successful.
 bool ExtractFormData(const blink::WebFormElement& form_element, FormData* data);
@@ -76,12 +70,14 @@
 bool IsFormVisible(blink::WebFrame* frame,
                    const GURL& action,
                    const GURL& origin,
-                   const FormData& form_data,
-                   const FormsPredictionsMap& form_predictions);
+                   const FormData& form_data);
 
-// Returns whether |form| is still visible in the frame. Ends up calling
-// isFormVisible() above, deriving arguments from |form|.
-bool IsFormVisible(const blink::WebFormElement& form);
+// Returns true if at least one element from |control_elements| is visible.
+bool IsSomeControlElementVisible(
+    const blink::WebVector<blink::WebFormControlElement>& control_elements);
+
+// Returns true if some control elements of |form| are visible.
+bool AreFormContentsVisible(const blink::WebFormElement& form);
 
 // Helper functions to assist in getting the canonical form of the action and
 // origin. The action will proplerly take into account <BASE>, and both will
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 69b27bc1..3814746 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -126,28 +126,23 @@
   scoped_ptr<PasswordForm> unowned_password_form(
       CreatePasswordFormFromUnownedInputElements(*frame, nullptr,
                                                  &form_predictions));
+  if (!unowned_password_form)
+    return false;
   std::vector<blink::WebFormControlElement> control_elements =
       form_util::GetUnownedAutofillableFormFieldElements(
           frame->document().all(), nullptr);
-  if (unowned_password_form &&
-      form_util::IsNamedElementVisible(
-          control_elements, unowned_password_form->username_element) &&
-      form_util::IsNamedElementVisible(
-          control_elements, unowned_password_form->password_element)) {
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
-    const bool action_is_empty = action == origin;
-    bool forms_are_same =
-        action_is_empty ? form_data.SameFormAs(unowned_password_form->form_data)
-                        : action == unowned_password_form->action;
-    if (forms_are_same)
-      return true;  // Form still exists.
-#else               // OS_MACOSX or OS_ANDROID
-    if (action == unowned_password_form->action)
-      return true;  // Form still exists.
-#endif
-  }
+  if (!form_util::IsSomeControlElementVisible(control_elements))
+    return false;
 
-  return false;
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+  const bool action_is_empty = action == origin;
+  bool forms_are_same =
+      action_is_empty ? form_data.SameFormAs(unowned_password_form->form_data)
+                      : action == unowned_password_form->action;
+  return forms_are_same;
+#else  // OS_MACOSX or OS_ANDROID
+  return action == unowned_password_form->action;
+#endif
 }
 
 // Utility function to find the unique entry of |control_elements| for the
@@ -946,8 +941,7 @@
   blink::WebFrame* frame = render_frame()->GetWebFrame();
   if (form_util::IsFormVisible(frame, provisionally_saved_form_->action,
                                provisionally_saved_form_->origin,
-                               provisionally_saved_form_->form_data,
-                               form_predictions_) ||
+                               provisionally_saved_form_->form_data) ||
       IsUnownedPasswordFormVisible(frame, provisionally_saved_form_->action,
                                    provisionally_saved_form_->origin,
                                    provisionally_saved_form_->form_data,
@@ -1000,10 +994,9 @@
     logger->LogNumber(Logger::STRING_NUMBER_OF_ALL_FORMS, forms.size());
 
   std::vector<PasswordForm> password_forms;
-  for (size_t i = 0; i < forms.size(); ++i) {
-    const blink::WebFormElement& form = forms[i];
+  for (const blink::WebFormElement& form : forms) {
     if (only_visible) {
-      bool is_form_visible = form_util::IsWebNodeVisible(form);
+      bool is_form_visible = form_util::AreFormContentsVisible(form);
       if (logger) {
         LogHTMLForm(logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, form);
         logger->LogBoolean(Logger::STRING_FORM_IS_VISIBLE, is_form_visible);
@@ -1028,16 +1021,29 @@
 
   // See if there are any unattached input elements that could be used for
   // password submission.
-  scoped_ptr<PasswordForm> password_form(
-      CreatePasswordFormFromUnownedInputElements(*frame,
-                                                 nullptr,
-                                                 &form_predictions_));
-  if (password_form) {
+  bool add_unowned_inputs = true;
+  if (only_visible) {
+    std::vector<blink::WebFormControlElement> control_elements =
+        form_util::GetUnownedAutofillableFormFieldElements(
+            frame->document().all(), nullptr);
+    add_unowned_inputs =
+        form_util::IsSomeControlElementVisible(control_elements);
     if (logger) {
-      logger->LogPasswordForm(Logger::STRING_FORM_IS_PASSWORD,
-                              *password_form);
+      logger->LogBoolean(Logger::STRING_UNOWNED_INPUTS_VISIBLE,
+                         add_unowned_inputs);
     }
-    password_forms.push_back(*password_form);
+  }
+  if (add_unowned_inputs) {
+    scoped_ptr<PasswordForm> password_form(
+        CreatePasswordFormFromUnownedInputElements(*frame, nullptr,
+                                                   &form_predictions_));
+    if (password_form) {
+      if (logger) {
+        logger->LogPasswordForm(Logger::STRING_FORM_IS_PASSWORD,
+                                *password_form);
+      }
+      password_forms.push_back(*password_form);
+    }
   }
 
   if (password_forms.empty() && !only_visible) {
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc
index b70d818..33d88753 100644
--- a/components/autofill/core/common/save_password_progress_logger.cc
+++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -354,6 +354,9 @@
       return "PasswordFormManager::state_";
     case SavePasswordProgressLogger::STRING_ADDING_SIGNATURE:
       return "Adding manager for form with this signature";
+    case SavePasswordProgressLogger::STRING_UNOWNED_INPUTS_VISIBLE:
+      return "Some control elements not associated to a form element are "
+             "visible";
     case SavePasswordProgressLogger::STRING_INVALID:
       return "INVALID";
       // Intentionally no default: clause here -- all IDs need to get covered.
diff --git a/components/autofill/core/common/save_password_progress_logger.h b/components/autofill/core/common/save_password_progress_logger.h
index 15d5e27..c68925b 100644
--- a/components/autofill/core/common/save_password_progress_logger.h
+++ b/components/autofill/core/common/save_password_progress_logger.h
@@ -127,6 +127,7 @@
     STRING_FORM_SIGNATURE,
     STRING_ADDING_SIGNATURE,
     STRING_FORM_MANAGER_STATE,
+    STRING_UNOWNED_INPUTS_VISIBLE,
     STRING_INVALID,  // Represents a string returned in a case of an error.
     STRING_MAX = STRING_INVALID
   };
diff --git a/components/mus/ws/BUILD.gn b/components/mus/ws/BUILD.gn
index bc2d0af7..7a186d6 100644
--- a/components/mus/ws/BUILD.gn
+++ b/components/mus/ws/BUILD.gn
@@ -27,6 +27,8 @@
     "focus_controller.cc",
     "focus_controller.h",
     "focus_controller_delegate.h",
+    "operation.cc",
+    "operation.h",
     "server_window.cc",
     "server_window.h",
     "server_window_delegate.h",
diff --git a/components/mus/ws/connection_manager.cc b/components/mus/ws/connection_manager.cc
index ede74e9..c7cebb1 100644
--- a/components/mus/ws/connection_manager.cc
+++ b/components/mus/ws/connection_manager.cc
@@ -8,6 +8,7 @@
 #include "base/stl_util.h"
 #include "components/mus/ws/client_connection.h"
 #include "components/mus/ws/connection_manager_delegate.h"
+#include "components/mus/ws/operation.h"
 #include "components/mus/ws/server_window.h"
 #include "components/mus/ws/window_coordinate_conversions.h"
 #include "components/mus/ws/window_tree_host_connection.h"
@@ -22,20 +23,6 @@
 
 namespace ws {
 
-ConnectionManager::ScopedChange::ScopedChange(
-    WindowTreeImpl* connection,
-    ConnectionManager* connection_manager,
-    bool is_delete_window)
-    : connection_manager_(connection_manager),
-      connection_id_(connection->id()),
-      is_delete_window_(is_delete_window) {
-  connection_manager_->PrepareForChange(this);
-}
-
-ConnectionManager::ScopedChange::~ScopedChange() {
-  connection_manager_->FinishChange();
-}
-
 ConnectionManager::ConnectionManager(
     ConnectionManagerDelegate* delegate,
     const scoped_refptr<mus::SurfacesState>& surfaces_state)
@@ -43,7 +30,7 @@
       surfaces_state_(surfaces_state),
       next_connection_id_(1),
       next_host_id_(0),
-      current_change_(nullptr),
+      current_operation_(nullptr),
       in_destructor_(false) {}
 
 ConnectionManager::~ConnectionManager() {
@@ -179,13 +166,13 @@
 }
 
 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
-  if (current_change_)
-    current_change_->MarkConnectionAsMessaged(id);
+  if (current_operation_)
+    current_operation_->MarkConnectionAsMessaged(id);
 }
 
 bool ConnectionManager::DidConnectionMessageClient(
     ConnectionSpecificId id) const {
-  return current_change_ && current_change_->DidMessageConnection(id);
+  return current_operation_ && current_operation_->DidMessageConnection(id);
 }
 
 mojom::ViewportMetricsPtr ConnectionManager::GetViewportMetricsForWindow(
@@ -249,7 +236,7 @@
     const gfx::Rect& new_bounds) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessWindowBoundsChanged(
-        window, old_bounds, new_bounds, IsChangeSource(pair.first));
+        window, old_bounds, new_bounds, IsOperationSource(pair.first));
   }
 }
 
@@ -259,7 +246,8 @@
     const gfx::Insets& new_client_area) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessClientAreaChanged(
-        window, old_client_area, new_client_area, IsChangeSource(pair.first));
+        window, old_client_area, new_client_area,
+        IsOperationSource(pair.first));
   }
 }
 
@@ -269,7 +257,7 @@
     const ServerWindow* old_parent) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessWillChangeWindowHierarchy(
-        window, new_parent, old_parent, IsChangeSource(pair.first));
+        window, new_parent, old_parent, IsOperationSource(pair.first));
   }
 }
 
@@ -279,7 +267,7 @@
     const ServerWindow* old_parent) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessWindowHierarchyChanged(
-        window, new_parent, old_parent, IsChangeSource(pair.first));
+        window, new_parent, old_parent, IsOperationSource(pair.first));
   }
 }
 
@@ -289,14 +277,14 @@
     const mojom::OrderDirection direction) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessWindowReorder(
-        window, relative_window, direction, IsChangeSource(pair.first));
+        window, relative_window, direction, IsOperationSource(pair.first));
   }
 }
 
 void ConnectionManager::ProcessWindowDeleted(const WindowId& window) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessWindowDeleted(window,
-                                                 IsChangeSource(pair.first));
+                                                 IsOperationSource(pair.first));
   }
 }
 
@@ -305,20 +293,20 @@
     const mojom::ViewportMetrics& new_metrics) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessViewportMetricsChanged(
-        old_metrics, new_metrics, IsChangeSource(pair.first));
+        old_metrics, new_metrics, IsOperationSource(pair.first));
   }
 }
 
-void ConnectionManager::PrepareForChange(ScopedChange* change) {
+void ConnectionManager::PrepareForOperation(Operation* op) {
   // Should only ever have one change in flight.
-  CHECK(!current_change_);
-  current_change_ = change;
+  CHECK(!current_operation_);
+  current_operation_ = op;
 }
 
-void ConnectionManager::FinishChange() {
-  // PrepareForChange/FinishChange should be balanced.
-  CHECK(current_change_);
-  current_change_ = NULL;
+void ConnectionManager::FinishOperation() {
+  // PrepareForOperation/FinishOperation should be balanced.
+  CHECK(current_operation_);
+  current_operation_ = nullptr;
 }
 
 void ConnectionManager::AddConnection(ClientConnection* connection) {
@@ -416,7 +404,7 @@
 
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessWillChangeWindowVisibility(
-        window, IsChangeSource(pair.first));
+        window, IsOperationSource(pair.first));
   }
 }
 
@@ -426,7 +414,7 @@
     const std::vector<uint8_t>* new_data) {
   for (auto& pair : connection_map_) {
     pair.second->service()->ProcessWindowPropertyChanged(
-        window, name, new_data, IsChangeSource(pair.first));
+        window, name, new_data, IsOperationSource(pair.first));
   }
 }
 
diff --git a/components/mus/ws/connection_manager.h b/components/mus/ws/connection_manager.h
index 4fca836e..e16b44a 100644
--- a/components/mus/ws/connection_manager.h
+++ b/components/mus/ws/connection_manager.h
@@ -16,6 +16,7 @@
 #include "components/mus/surfaces/surfaces_state.h"
 #include "components/mus/ws/focus_controller_delegate.h"
 #include "components/mus/ws/ids.h"
+#include "components/mus/ws/operation.h"
 #include "components/mus/ws/server_window_delegate.h"
 #include "components/mus/ws/server_window_observer.h"
 #include "components/mus/ws/window_tree_host_impl.h"
@@ -38,39 +39,6 @@
 class ConnectionManager : public ServerWindowDelegate,
                           public ServerWindowObserver {
  public:
-  // Create when a WindowTreeImpl is about to make a change. Ensures clients are
-  // notified correctly.
-  class ScopedChange {
-   public:
-    ScopedChange(WindowTreeImpl* connection,
-                 ConnectionManager* connection_manager,
-                 bool is_delete_window);
-    ~ScopedChange();
-
-    ConnectionSpecificId connection_id() const { return connection_id_; }
-    bool is_delete_window() const { return is_delete_window_; }
-
-    // Marks the connection with the specified id as having seen a message.
-    void MarkConnectionAsMessaged(ConnectionSpecificId connection_id) {
-      message_ids_.insert(connection_id);
-    }
-
-    // Returns true if MarkConnectionAsMessaged(connection_id) was invoked.
-    bool DidMessageConnection(ConnectionSpecificId connection_id) const {
-      return message_ids_.count(connection_id) > 0;
-    }
-
-   private:
-    ConnectionManager* connection_manager_;
-    const ConnectionSpecificId connection_id_;
-    const bool is_delete_window_;
-
-    // See description of MarkConnectionAsMessaged/DidMessageConnection.
-    std::set<ConnectionSpecificId> message_ids_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedChange);
-  };
-
   ConnectionManager(ConnectionManagerDelegate* delegate,
                     const scoped_refptr<mus::SurfacesState>& surfaces_state);
   ~ConnectionManager() override;
@@ -115,10 +83,9 @@
   // Schedules a paint for the specified region in the coordinates of |window|.
   void SchedulePaint(const ServerWindow* window, const gfx::Rect& bounds);
 
-  bool IsProcessingChange() const { return current_change_ != nullptr; }
-
-  bool is_processing_delete_window() const {
-    return current_change_ && current_change_->is_delete_window();
+  OperationType current_operation_type() const {
+    return current_operation_ ? current_operation_->type()
+                              : OperationType::NONE;
   }
 
   // Invoked when the WindowTreeHostImpl's display is closed.
@@ -176,24 +143,27 @@
   void ProcessWindowDeleted(const WindowId& window);
 
  private:
+  friend class Operation;
+
   using ConnectionMap = std::map<ConnectionSpecificId, ClientConnection*>;
   using HostConnectionMap =
       std::map<WindowTreeHostImpl*, WindowTreeHostConnection*>;
 
-  // Invoked when a connection is about to make a change. Subsequently followed
-  // by FinishChange() once the change is done.
+  // Invoked when a connection is about to execute a window server operation.
+  // Subsequently followed by FinishOperation() once the change is done.
   //
-  // Changes should never nest, meaning each PrepareForChange() must be
-  // balanced with a call to FinishChange() with no PrepareForChange()
+  // Changes should never nest, meaning each PrepareForOperation() must be
+  // balanced with a call to FinishOperation() with no PrepareForOperation()
   // in between.
-  void PrepareForChange(ScopedChange* change);
+  void PrepareForOperation(Operation* op);
 
-  // Balances a call to PrepareForChange().
-  void FinishChange();
+  // Balances a call to PrepareForOperation().
+  void FinishOperation();
 
-  // Returns true if the specified connection originated the current change.
-  bool IsChangeSource(ConnectionSpecificId connection_id) const {
-    return current_change_ && current_change_->connection_id() == connection_id;
+  // Returns true if the specified connection issued the current operation.
+  bool IsOperationSource(ConnectionSpecificId connection_id) const {
+    return current_operation_ &&
+           current_operation_->source_connection_id() == connection_id;
   }
 
   // Adds |connection| to internal maps.
@@ -246,9 +216,9 @@
   // Set of WindowTreeHostImpls.
   HostConnectionMap host_connection_map_;
 
-  // If non-null we're processing a change. The ScopedChange is not owned by us
-  // (it's created on the stack by WindowTreeImpl).
-  ScopedChange* current_change_;
+  // If non-null then we're processing a client operation. The Operation is
+  // not owned by us (it's created on the stack by WindowTreeImpl).
+  Operation* current_operation_;
 
   bool in_destructor_;
 
diff --git a/components/mus/ws/operation.cc b/components/mus/ws/operation.cc
new file mode 100644
index 0000000..f302f26
--- /dev/null
+++ b/components/mus/ws/operation.cc
@@ -0,0 +1,31 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/mus/ws/operation.h"
+
+#include "components/mus/ws/connection_manager.h"
+#include "components/mus/ws/window_tree_impl.h"
+
+namespace mus {
+namespace ws {
+
+Operation::Operation(WindowTreeImpl* connection,
+                     ConnectionManager* connection_manager,
+                     OperationType operation_type)
+    : connection_manager_(connection_manager),
+      source_connection_id_(connection->id()),
+      operation_type_(operation_type) {
+  DCHECK(operation_type != OperationType::NONE);
+  // Tell the connection manager about the operation currently in flight.
+  // The connection manager uses this information to suppress certain calls
+  // out to clients.
+  connection_manager_->PrepareForOperation(this);
+}
+
+Operation::~Operation() {
+  connection_manager_->FinishOperation();
+}
+
+}  // namespace ws
+}  // namespace mus
diff --git a/components/mus/ws/operation.h b/components/mus/ws/operation.h
new file mode 100644
index 0000000..615287e
--- /dev/null
+++ b/components/mus/ws/operation.h
@@ -0,0 +1,73 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MUS_WS_OPERATION_H_
+#define COMPONENTS_MUS_WS_OPERATION_H_
+
+#include <set>
+
+#include "base/macros.h"
+#include "components/mus/public/cpp/types.h"
+
+namespace mus {
+namespace ws {
+
+class ConnectionManager;
+class WindowTreeImpl;
+
+enum class OperationType {
+  NONE,
+  ADD_WINDOW,
+  DELETE_WINDOW,
+  EMBED,
+  REMOVE_WINDOW_FROM_PARENT,
+  REORDER_WINDOW,
+  SET_FOCUS,
+  SET_WINDOW_BOUNDS,
+  SET_WINDOW_PROPERTY,
+  SET_WINDOW_VISIBILITY,
+};
+
+// This class tracks the currently pending client-initiated operation.
+// This is typically used to suppress superfluous notifications generated
+// by suboperations in the window server.
+class Operation {
+ public:
+  Operation(WindowTreeImpl* connection,
+            ConnectionManager* connection_manager,
+            OperationType operation_type);
+  ~Operation();
+
+  ConnectionSpecificId source_connection_id() const {
+    return source_connection_id_;
+  }
+
+  const OperationType& type() const { return operation_type_; }
+
+  // Marks the connection with the specified id as having been sent a message
+  // during the course of |this| operation.
+  void MarkConnectionAsMessaged(ConnectionSpecificId connection_id) {
+    message_ids_.insert(connection_id);
+  }
+
+  // Returns true if MarkConnectionAsMessaged(connection_id) was invoked.
+  bool DidMessageConnection(ConnectionSpecificId connection_id) const {
+    return message_ids_.count(connection_id) > 0;
+  }
+
+ private:
+  ConnectionManager* const connection_manager_;
+  const ConnectionSpecificId source_connection_id_;
+  const OperationType operation_type_;
+
+  // See description of MarkConnectionAsMessaged/DidMessageConnection.
+  std::set<ConnectionSpecificId> message_ids_;
+
+  DISALLOW_COPY_AND_ASSIGN(Operation);
+};
+
+}  // namespace ws
+}  // namespace mus
+
+#endif  // COMPONENTS_MUS_WS_OPERATION_H_
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc
index 85c6e50..0564c2c 100644
--- a/components/mus/ws/window_tree_impl.cc
+++ b/components/mus/ws/window_tree_impl.cc
@@ -9,6 +9,7 @@
 #include "components/mus/ws/connection_manager.h"
 #include "components/mus/ws/default_access_policy.h"
 #include "components/mus/ws/display_manager.h"
+#include "components/mus/ws/operation.h"
 #include "components/mus/ws/server_window.h"
 #include "components/mus/ws/window_manager_access_policy.h"
 #include "components/mus/ws/window_tree_host_impl.h"
@@ -133,7 +134,7 @@
   ServerWindow* child = GetWindow(child_id);
   if (parent && child && child->parent() != parent &&
       !child->Contains(parent) && access_policy_->CanAddWindow(parent, child)) {
-    ConnectionManager::ScopedChange change(this, connection_manager_, false);
+    Operation op(this, connection_manager_, OperationType::ADD_WINDOW);
     parent->Add(child);
     return true;
   }
@@ -156,7 +157,7 @@
       !access_policy_->CanChangeWindowVisibility(window)) {
     return false;
   }
-  ConnectionManager::ScopedChange change(this, connection_manager_, false);
+  Operation op(this, connection_manager_, OperationType::SET_WINDOW_VISIBILITY);
   window->SetVisible(visible);
   return true;
 }
@@ -250,7 +251,9 @@
     std::vector<const ServerWindow*> unused;
     GetUnknownWindowsFrom(window, &unused);
   }
-  if (originated_change || connection_manager_->is_processing_delete_window() ||
+  if (originated_change || (connection_manager_->current_operation_type() ==
+                            OperationType::DELETE_WINDOW) ||
+      (connection_manager_->current_operation_type() == OperationType::EMBED) ||
       connection_manager_->DidConnectionMessageClient(id_)) {
     return;
   }
@@ -394,7 +397,7 @@
                                       ServerWindow* window) {
   DCHECK(window);
   DCHECK_EQ(window->id().connection_id, id_);
-  ConnectionManager::ScopedChange change(source, connection_manager_, true);
+  Operation op(source, connection_manager_, OperationType::DELETE_WINDOW);
   delete window;
   return true;
 }
@@ -512,7 +515,7 @@
 
 void WindowTreeImpl::DestroyWindows() {
   if (!window_map_.empty()) {
-    ConnectionManager::ScopedChange change(this, connection_manager_, true);
+    Operation op(this, connection_manager_, OperationType::DELETE_WINDOW);
     // If we get here from the destructor we're not going to get
     // ProcessWindowDeleted(). Copy the map and delete from the copy so that we
     // don't have to worry about whether |window_map_| changes or not.
@@ -536,7 +539,7 @@
   WindowTreeImpl* existing_owner =
       connection_manager_->GetConnectionWithRoot(window_id);
 
-  ConnectionManager::ScopedChange change(this, connection_manager_, true);
+  Operation op(this, connection_manager_, OperationType::EMBED);
   RemoveChildrenAsPartOfEmbed(window_id);
   if (existing_owner) {
     // Never message the originating connection.
@@ -588,7 +591,8 @@
   if (window && window->parent() &&
       access_policy_->CanRemoveWindowFromParent(window)) {
     success = true;
-    ConnectionManager::ScopedChange change(this, connection_manager_, false);
+    Operation op(this, connection_manager_,
+                 OperationType::REMOVE_WINDOW_FROM_PARENT);
     window->parent()->Remove(window);
   }
   callback.Run(success);
@@ -604,7 +608,7 @@
       GetWindow(WindowIdFromTransportId(relative_window_id));
   if (CanReorderWindow(window, relative_window, direction)) {
     success = true;
-    ConnectionManager::ScopedChange change(this, connection_manager_, false);
+    Operation op(this, connection_manager_, OperationType::REORDER_WINDOW);
     window->parent()->Reorder(window, relative_window, direction);
     connection_manager_->ProcessWindowReorder(window, relative_window,
                                               direction);
@@ -633,7 +637,7 @@
   // Only the owner of the window can change the bounds.
   bool success = window && access_policy_->CanSetWindowBounds(window);
   if (success) {
-    ConnectionManager::ScopedChange change(this, connection_manager_, false);
+    Operation op(this, connection_manager_, OperationType::SET_WINDOW_BOUNDS);
     window->SetBounds(bounds.To<gfx::Rect>());
   }
   callback.Run(success);
@@ -654,7 +658,7 @@
   ServerWindow* window = GetWindow(WindowIdFromTransportId(window_id));
   const bool success = window && access_policy_->CanSetWindowProperties(window);
   if (success) {
-    ConnectionManager::ScopedChange change(this, connection_manager_, false);
+    Operation op(this, connection_manager_, OperationType::SET_WINDOW_PROPERTY);
 
     if (value.is_null()) {
       window->SetProperty(name, nullptr);
@@ -728,7 +732,7 @@
   // TODO(beng): consider shifting non-policy drawn check logic to VTH's
   //             FocusController.
   if (window && window->IsDrawn() && access_policy_->CanSetFocus(window)) {
-    ConnectionManager::ScopedChange change(this, connection_manager_, false);
+    Operation op(this, connection_manager_, OperationType::SET_FOCUS);
     WindowTreeHostImpl* host = GetHost();
     if (host)
       host->SetFocusedWindow(window);
diff --git a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
index 62e90878..934771c 100644
--- a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
+++ b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
@@ -60,7 +60,8 @@
       gpu_memory_buffer_manager_(ChildThreadImpl::current()
                                      ->gpu_memory_buffer_manager()),
       thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()) {
-  DCHECK(gpu_channel_host_.get());
+  DCHECK(main_thread_task_runner_);
+  DCHECK(gpu_channel_host_);
 }
 
 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d1ac605..5a9da31 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -455,28 +455,28 @@
   return request;
 }
 
-void UpdateFrameNavigationTiming(WebFrame* frame,
-                                 base::TimeTicks browser_navigation_start,
-                                 base::TimeTicks renderer_navigation_start) {
-  // The browser provides the navigation_start time to bootstrap the
-  // Navigation Timing information for the browser-initiated navigations. In
-  // case of cross-process navigations, this carries over the time of
-  // finishing the onbeforeunload handler of the previous page.
+// Sanitizes the navigation_start timestamp for browser-initiated navigations,
+// where the browser possibly has a better notion of start time than the
+// renderer. In the case of cross-process navigations, this carries over the
+// time of finishing the onbeforeunload handler of the previous page.
+// TimeTicks is sometimes not monotonic across processes, and because
+// |browser_navigation_start| is likely before this process existed,
+// InterProcessTimeTicksConverter won't help. The timestamp is sanitized by
+// clamping it to renderer_navigation_start, initialized earlier in the call
+// stack.
+base::TimeTicks SanitizeNavigationTiming(
+    blink::WebFrameLoadType load_type,
+    const base::TimeTicks& browser_navigation_start,
+    const base::TimeTicks& renderer_navigation_start) {
+  if (load_type != blink::WebFrameLoadType::Standard)
+    return base::TimeTicks();
   DCHECK(!browser_navigation_start.is_null());
-  if (frame->provisionalDataSource()) {
-    // |browser_navigation_start| is likely before this process existed, so we
-    // can't use InterProcessTimeTicksConverter. We need at least to ensure
-    // that the browser-side navigation start we set is not later than the one
-    // on the renderer side.
-    base::TimeTicks navigation_start = std::min(
-        browser_navigation_start, renderer_navigation_start);
-    double navigation_start_seconds =
-        (navigation_start - base::TimeTicks()).InSecondsF();
-    frame->provisionalDataSource()->setNavigationStartTime(
-        navigation_start_seconds);
-    // TODO(clamy): We need to provide additional timing values for the
-    // Navigation Timing API to work with browser-side navigations.
-  }
+  base::TimeTicks navigation_start =
+      std::min(browser_navigation_start, renderer_navigation_start);
+  // TODO(csharrison) Investigate how big a problem the cross process
+  // monotonicity really is and on what platforms. Log UMA for:
+  // |renderer_navigation_start - browser_navigation_start|
+  return navigation_start;
 }
 
 // PlzNavigate
@@ -2605,13 +2605,7 @@
 
   // The rest of RenderView assumes that a WebDataSource will always have a
   // non-null NavigationState.
-  if (content_initiated) {
-    document_state->set_navigation_state(
-        NavigationStateImpl::CreateContentInitiated());
-  } else {
-    document_state->set_navigation_state(CreateNavigationStateFromPending());
-    pending_navigation_params_.reset();
-  }
+  UpdateNavigationState(document_state);
 
   // DocumentState::referred_by_prefetcher_ is true if we are
   // navigating from a page that used prefetching using a link on that
@@ -2661,6 +2655,17 @@
     }
   }
 
+  NavigationStateImpl* navigation_state = static_cast<NavigationStateImpl*>(
+      document_state->navigation_state());
+
+  // Set the navigation start time in blink.
+  base::TimeTicks navigation_start =
+      navigation_state->common_params().navigation_start;
+  datasource->setNavigationStartTime(
+      (navigation_start - base::TimeTicks()).InSecondsF());
+  // TODO(clamy) We need to provide additional timing values for the Navigation
+  // Timing API to work with browser-side navigations.
+
   // Create the serviceworker's per-document network observing object if it
   // does not exist (When navigation happens within a page, the provider already
   // exists).
@@ -2668,9 +2673,6 @@
           DocumentState::FromDataSource(datasource)))
     return;
 
-  NavigationStateImpl* navigation_state = static_cast<NavigationStateImpl*>(
-      DocumentState::FromDataSource(datasource)->navigation_state());
-
   ServiceWorkerNetworkProvider::AttachToDocumentState(
       DocumentState::FromDataSource(datasource),
       ServiceWorkerNetworkProvider::CreateForNavigation(
@@ -3155,11 +3157,10 @@
   // ExtraData will get the new NavigationState.  Similarly, if we did not
   // initiate this navigation, then we need to take care to reset any pre-
   // existing navigation state to a content-initiated navigation state.
-  // didCreateDataSource conveniently takes care of this for us.
-  didCreateDataSource(frame, frame->dataSource());
-
+  // UpdateNavigationState conveniently takes care of this for us.
   DocumentState* document_state =
       DocumentState::FromDataSource(frame->dataSource());
+  UpdateNavigationState(document_state);
   static_cast<NavigationStateImpl*>(document_state->navigation_state())
       ->set_was_within_same_page(true);
 
@@ -4657,6 +4658,9 @@
   bool browser_side_navigation =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableBrowserSideNavigation);
+
+  // Lower bound for browser initiated navigation start time.
+  base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
   bool is_reload = IsReload(common_params.navigation_type);
   bool is_history_navigation = request_params.page_state.IsValid();
   WebURLRequest::CachePolicy cache_policy =
@@ -4687,6 +4691,14 @@
   pending_navigation_params_.reset(
       new NavigationParams(common_params, start_params, request_params));
 
+  // Unless the load is a WebFrameLoadType::Standard, this should remain
+  // uninitialized. It will be updated when the load type is determined to be
+  // Standard, or after the previous document's unload handler has been
+  // triggered. This occurs in UpdateNavigationState.
+  // TODO(csharrison) See if we can always use the browser timestamp.
+  pending_navigation_params_->common_params.navigation_start =
+      base::TimeTicks();
+
   // Create parameters for a standard navigation.
   blink::WebFrameLoadType load_type = blink::WebFrameLoadType::Standard;
   bool should_load_request = false;
@@ -4811,10 +4823,10 @@
   }
 
   if (should_load_request) {
-    // Record this before starting the load. We need a lower bound of this
-    // time to sanitize the navigationStart override set below.
-    base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
-
+    // Sanitize navigation start now that we know the load_type.
+    pending_navigation_params_->common_params.navigation_start =
+        SanitizeNavigationTiming(load_type, common_params.navigation_start,
+                                 renderer_navigation_start);
     // Perform a navigation to a data url if needed.
     if (!common_params.base_url_for_data_url.is_empty() ||
         (browser_side_navigation &&
@@ -4825,12 +4837,6 @@
       frame_->toWebLocalFrame()->load(request, load_type,
                                       item_for_history_navigation);
     }
-
-    if (load_type == blink::WebFrameLoadType::Standard) {
-      UpdateFrameNavigationTiming(frame_,
-                                  common_params.navigation_start,
-                                  renderer_navigation_start);
-    }
   }
 
   // In case LoadRequest failed before didCreateDataSource was called.
@@ -5200,6 +5206,22 @@
   return NavigationStateImpl::CreateContentInitiated();
 }
 
+void RenderFrameImpl::UpdateNavigationState(DocumentState* document_state) {
+  if (pending_navigation_params_) {
+    // If this is a browser-initiated load that doesn't override
+    // navigation_start, set it here.
+    if (pending_navigation_params_->common_params.navigation_start.is_null()) {
+      pending_navigation_params_->common_params.navigation_start =
+          base::TimeTicks::Now();
+    }
+    document_state->set_navigation_state(CreateNavigationStateFromPending());
+    pending_navigation_params_.reset();
+  } else {
+    document_state->set_navigation_state(
+        NavigationStateImpl::CreateContentInitiated());
+  }
+}
+
 #if defined(OS_ANDROID)
 WebMediaPlayer* RenderFrameImpl::CreateAndroidWebMediaPlayer(
     WebMediaPlayerClient* client,
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 7474362..e29cc90 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -870,6 +870,10 @@
   // saved in OnNavigate().
   NavigationState* CreateNavigationStateFromPending();
 
+  // Sets the NavigationState on the DocumentState based on
+  // the value of |pending_navigation_params_|.
+  void UpdateNavigationState(DocumentState* document_state);
+
 #if defined(OS_ANDROID)
   blink::WebMediaPlayer* CreateAndroidWebMediaPlayer(
       blink::WebMediaPlayerClient* client,
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index a87d8fe..804e018 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -455,6 +455,8 @@
   custom_histograms_.insert("V8.MemoryExternalFragmentationTotal");
   custom_histograms_.insert("V8.MemoryHeapSampleTotalCommitted");
   custom_histograms_.insert("V8.MemoryHeapSampleTotalUsed");
+  custom_histograms_.insert("V8.MemoryHeapUsed");
+  custom_histograms_.insert("V8.MemoryHeapCommitted");
 }
 
 RenderThreadImpl::HistogramCustomizer::~HistogramCustomizer() {}
@@ -1422,7 +1424,7 @@
         base::StringToUint(image_texture_target_string, &image_texture_target);
     DCHECK(parsed_image_texture_target);
     gpu_factories_ = RendererGpuVideoAcceleratorFactories::Create(
-        gpu_channel_host.get(), main_thread_compositor_task_runner_,
+        gpu_channel_host.get(), base::ThreadTaskRunnerHandle::Get(),
         media_task_runner, shared_context_provider,
         enable_gpu_memory_buffer_video_frames, image_texture_target,
         enable_video_accelerator);
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 3f1250f1..3783e905 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -2257,30 +2257,10 @@
   // Don't disable here to test that emulation is being shutdown properly.
 }
 
-// Sanity checks for the Navigation Timing API |navigationStart| override. We
+// Sanity check for the Navigation Timing API |navigationStart| override. We
 // are asserting only most basic constraints, as TimeTicks (passed as the
 // override) are not comparable with the wall time (returned by the Blink API).
 TEST_F(RenderViewImplTest, NavigationStartOverride) {
-  // Verify that a navigation that claims to have started at the earliest
-  // possible TimeTicks is indeed reported as one that started before
-  // OnNavigate() is called.
-  base::Time before_navigation = base::Time::Now();
-  CommonNavigationParams early_common_params;
-  StartNavigationParams early_start_params;
-  early_common_params.url = GURL("data:text/html,<div>Page</div>");
-  early_common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
-  early_common_params.transition = ui::PAGE_TRANSITION_TYPED;
-  early_common_params.navigation_start = base::TimeTicks::FromInternalValue(1);
-  early_start_params.is_post = true;
-
-  frame()->Navigate(early_common_params, early_start_params,
-                    RequestNavigationParams());
-  ProcessPendingMessages();
-
-  base::Time early_nav_reported_start =
-      base::Time::FromDoubleT(GetMainFrame()->performance().navigationStart());
-  EXPECT_LT(early_nav_reported_start, before_navigation);
-
   // Verify that a navigation that claims to have started in the future - 42
   // days from now is *not* reported as one that starts in the future; as we
   // sanitize the override allowing a maximum of ::Now().
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/avoid_delaying_onload_link_preload.html b/third_party/WebKit/LayoutTests/http/tests/preload/avoid_delaying_onload_link_preload.html
new file mode 100644
index 0000000..86a7d86
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/preload/avoid_delaying_onload_link_preload.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+    var t = async_test('Makes sure link preload preloaded resources are not delaying onload');
+</script>
+<link rel=preload href="../resources/slow-script.pl?delay=200" as=script>
+<script>
+    window.addEventListener("load", t.step_func(function() {
+        assert_equals(performance.getEntriesByType("resource").length, 2);
+        t.done();
+    }));
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery.html b/third_party/WebKit/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery.html
new file mode 100644
index 0000000..dcb1d83
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/preload/delaying_onload_link_preload_after_discovery.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+    var t = async_test('Makes sure link preload preloaded resources are delaying onload after discovery');
+</script>
+<link rel=preload href="http://127.0.0.1:8000/resources/slow-script.pl?delay=200" as=script>
+<link rel=preload href="http://127.0.0.1:8000/resources/slow-image.php?name=square.png&mimeType=image/png&sleep=400" as=image>
+<script>
+    window.addEventListener("load", t.step_func(function() {
+        assert_equals(performance.getEntriesByType("resource").length, 4);
+        t.done();
+    }));
+    document.write('<sc' + 'ript src="../resources/slow-script.pl?delay=200"></sc' + 'ript>');
+    document.write("<!--");
+    var img = new Image();
+    img.src = "http://127.0.0.1:8000/resources/slow-image.php?name=square.png&mimeType=image/png&sleep=400";
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/delaying_onload_preloader_after_discovery.html b/third_party/WebKit/LayoutTests/http/tests/preload/delaying_onload_preloader_after_discovery.html
new file mode 100644
index 0000000..cac245b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/preload/delaying_onload_preloader_after_discovery.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+    var t = async_test('Makes sure that preloader preloaded resources are delaying onload after they are discovered');
+</script>
+<script src="../resources/slow-script.pl?delay=200"></script>
+<script>
+    window.addEventListener("load", t.step_func(function() {
+        assert_equals(performance.getEntriesByType("resource").length, 4);
+        t.done();
+    }));
+</script>
+<script>
+    document.write("<!--");
+    var img = new Image();
+    img.src = "http://127.0.0.1:8000/resources/slow-image.php?name=square.png&mimeType=image/png&sleep=400";
+</script>
+<img src="http://127.0.0.1:8000/resources/slow-image.php?name=square.png&mimeType=image/png&sleep=400">
diff --git a/third_party/WebKit/Source/core/fetch/FetchRequest.cpp b/third_party/WebKit/Source/core/fetch/FetchRequest.cpp
index 417fccd..f620a4d 100644
--- a/third_party/WebKit/Source/core/fetch/FetchRequest.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchRequest.cpp
@@ -37,6 +37,7 @@
     , m_options(ResourceFetcher::defaultResourceOptions())
     , m_priority(priority)
     , m_forPreload(false)
+    , m_avoidBlockingOnLoad(false)
     , m_defer(NoDefer)
     , m_originRestriction(UseDefaultOriginRestrictionForType)
 {
@@ -48,6 +49,7 @@
     , m_options(options)
     , m_priority(ResourceLoadPriorityUnresolved)
     , m_forPreload(false)
+    , m_avoidBlockingOnLoad(false)
     , m_defer(NoDefer)
     , m_originRestriction(UseDefaultOriginRestrictionForType)
 {
@@ -59,6 +61,7 @@
     , m_options(ResourceFetcher::defaultResourceOptions())
     , m_priority(ResourceLoadPriorityUnresolved)
     , m_forPreload(false)
+    , m_avoidBlockingOnLoad(false)
     , m_defer(NoDefer)
     , m_originRestriction(UseDefaultOriginRestrictionForType)
 {
diff --git a/third_party/WebKit/Source/core/fetch/FetchRequest.h b/third_party/WebKit/Source/core/fetch/FetchRequest.h
index b476fbf..9e864fad 100644
--- a/third_party/WebKit/Source/core/fetch/FetchRequest.h
+++ b/third_party/WebKit/Source/core/fetch/FetchRequest.h
@@ -86,6 +86,9 @@
     bool forPreload() const { return m_forPreload; }
     void setForPreload(bool forPreload) { m_forPreload = forPreload; }
 
+    bool avoidBlockingOnLoad() { return m_avoidBlockingOnLoad; }
+    void setAvoidBlockingOnLoad(bool doNotBlock) { m_avoidBlockingOnLoad = doNotBlock; }
+
     void setContentSecurityCheck(ContentSecurityPolicyDisposition contentSecurityPolicyOption) { m_options.contentSecurityPolicyOption = contentSecurityPolicyOption; }
     void setCrossOriginAccessControl(SecurityOrigin*, StoredCredentials, CredentialRequest);
     void setCrossOriginAccessControl(SecurityOrigin*, StoredCredentials);
@@ -101,6 +104,7 @@
     ResourceLoaderOptions m_options;
     ResourceLoadPriority m_priority;
     bool m_forPreload;
+    bool m_avoidBlockingOnLoad;
     DeferOption m_defer;
     OriginRestriction m_originRestriction;
     ResourceWidth m_resourceWidth;
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp
index de290b6..15fbaa8d 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -163,6 +163,7 @@
     , m_status(Pending)
     , m_wasPurged(false)
     , m_needsSynchronousCacheHit(false)
+    , m_avoidBlockingOnLoad(false)
 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
     , m_deleted(false)
 #endif
@@ -1022,6 +1023,20 @@
     return initatorTypeNameToString(initiatorInfo.name);
 }
 
+bool Resource::shouldBlockLoadEvent() const
+{
+    return !m_avoidBlockingOnLoad && isNonBlockingResourceType();
+}
+
+bool Resource::isNonBlockingResourceType() const
+{
+    return type() != LinkPrefetch
+        && type() != LinkSubresource
+        && type() != Media
+        && type() != Raw
+        && type() != TextTrack;
+}
+
 #if !LOG_DISABLED
 const char* ResourceTypeName(Resource::Type type)
 {
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h
index 589bb3a..9af0d10 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.h
+++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -113,6 +113,9 @@
 
     void setNeedsSynchronousCacheHit(bool needsSynchronousCacheHit) { m_needsSynchronousCacheHit = needsSynchronousCacheHit; }
 
+    void setAvoidBlockingOnLoad(bool doNotBlock) { m_avoidBlockingOnLoad = doNotBlock; }
+    bool avoidBlockingOnLoad() { return m_avoidBlockingOnLoad; }
+
     void setResourceError(const ResourceError& error) { m_error = error; }
     const ResourceError& resourceError() const { return m_error; }
 
@@ -171,14 +174,8 @@
     ResourceLoader* loader() const { return m_loader.get(); }
 
     virtual bool isImage() const { return false; }
-    bool shouldBlockLoadEvent() const
-    {
-        return type() != LinkPrefetch
-            && type() != LinkSubresource
-            && type() != Media
-            && type() != Raw
-            && type() != TextTrack;
-    }
+    bool shouldBlockLoadEvent() const;
+    bool isNonBlockingResourceType() const;
 
     // Computes the status of an object after loading.
     // Updates the expire date on the cache entry file
@@ -410,6 +407,7 @@
     unsigned m_wasPurged : 1;
 
     unsigned m_needsSynchronousCacheHit : 1;
+    unsigned m_avoidBlockingOnLoad : 1;
 
 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
     bool m_deleted;
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
index d52c3ef..9066f81 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -323,6 +323,18 @@
     scheduleDocumentResourcesGC();
 }
 
+void ResourceFetcher::moveCachedNonBlockingResourceToBlocking(Resource* resource)
+{
+    // TODO(yoav): Test that non-blocking resources (video/audio/track) continue to not-block even after being preloaded and discovered.
+    if (resource && resource->loader() && resource->isNonBlockingResourceType() && resource->avoidBlockingOnLoad()) {
+        if (m_nonBlockingLoaders)
+            m_nonBlockingLoaders->remove(resource->loader());
+        if (!m_loaders)
+            m_loaders = ResourceLoaderSet::create();
+        m_loaders->add(resource->loader());
+    }
+}
+
 ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, const ResourceFactory& factory, const SubstituteData& substituteData)
 {
     ASSERT(request.options().synchronousPolicy == RequestAsynchronously || factory.type() == Resource::Raw || factory.type() == Resource::XSLStyleSheet);
@@ -364,8 +376,9 @@
         }
     }
 
-    // See if we can use an existing resource from the cache.
+    // See if we can use an existing resource from the cache. If so, we need to move it to be load blocking.
     ResourcePtr<Resource> resource = memoryCache()->resourceForURL(url, getCacheIdentifier());
+    moveCachedNonBlockingResourceToBlocking(resource.get());
 
     const RevalidationPolicy policy = determineRevalidationPolicy(factory.type(), request, resource.get(), isStaticData);
     switch (policy) {
@@ -519,6 +532,7 @@
 
     initializeResourceRequest(request.mutableResourceRequest(), factory.type());
     ResourcePtr<Resource> resource = factory.create(request.resourceRequest(), charset);
+    resource->setAvoidBlockingOnLoad(request.avoidBlockingOnLoad());
     resource->setCacheIdentifier(cacheIdentifier);
 
     memoryCache()->add(resource.get());
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
index 893c17f..f74b5eb 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -167,6 +167,8 @@
     enum RevalidationPolicy { Use, Revalidate, Reload, Load };
     RevalidationPolicy determineRevalidationPolicy(Resource::Type, const FetchRequest&, Resource* existingResource, bool isStaticData) const;
 
+    void moveCachedNonBlockingResourceToBlocking(Resource*);
+
     void initializeResourceRequest(ResourceRequest&, Resource::Type);
 
     static bool resourceNeedsLoad(Resource*, const FetchRequest&, RevalidationPolicy);
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp b/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp
index 33f8535..0113356 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp
@@ -87,6 +87,12 @@
 
 void DocumentLoadTiming::markNavigationStart()
 {
+    // Allow the embedder to override navigationStart before we record it if
+    // they have a more accurate timestamp.
+    if (m_navigationStart) {
+        ASSERT(m_referenceMonotonicTime && m_referenceWallTime);
+        return;
+    }
     TRACE_EVENT_MARK("blink.user_timing", "navigationStart");
     ASSERT(!m_navigationStart && !m_referenceMonotonicTime && !m_referenceWallTime);
 
@@ -98,14 +104,16 @@
 void DocumentLoadTiming::setNavigationStart(double navigationStart)
 {
     TRACE_EVENT_MARK_WITH_TIMESTAMP("blink.user_timing", "navigationStart", navigationStart);
-    ASSERT(m_referenceMonotonicTime && m_referenceWallTime);
     m_navigationStart = navigationStart;
 
     // |m_referenceMonotonicTime| and |m_referenceWallTime| represent
     // navigationStart. When the embedder sets navigationStart (because the
     // navigation started earlied on the browser side), we need to adjust these
     // as well.
-    m_referenceWallTime = monotonicTimeToPseudoWallTime(navigationStart);
+    if (!m_referenceWallTime)
+        m_referenceWallTime = currentTime();
+    else
+        m_referenceWallTime = monotonicTimeToPseudoWallTime(navigationStart);
     m_referenceMonotonicTime = navigationStart;
     notifyDocumentTimingChanged();
 }
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.cpp b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
index a2a2329c..6de4b8e 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
@@ -205,6 +205,8 @@
         Settings* settings = document.settings();
         if (settings && settings->logPreload())
             document.addConsoleMessage(ConsoleMessage::create(OtherMessageSource, DebugMessageLevel, String("Preload triggered for " + href.host() + href.path())));
+        linkRequest.setForPreload(true);
+        linkRequest.setAvoidBlockingOnLoad(true);
         document.loader()->startPreload(type, linkRequest);
     }
 }
diff --git a/third_party/libvpx_new/README.chromium b/third_party/libvpx_new/README.chromium
index a4941116..70b04b59 100644
--- a/third_party/libvpx_new/README.chromium
+++ b/third_party/libvpx_new/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Wednesday November 4 2015
+Date: Friday November 6 2015
 Branch: master
-Commit: c6641709a707ccb98cbdf785428659e44d4f2c8b
+Commit: eba14ddbe7e7b69803dab770ba25ae2ba75c65e2
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx_new/source/config/vpx_version.h b/third_party/libvpx_new/source/config/vpx_version.h
index b5c4b1f5..7b83a66 100644
--- a/third_party/libvpx_new/source/config/vpx_version.h
+++ b/third_party/libvpx_new/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  4
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "1647-gc664170"
+#define VERSION_EXTRA  "1655-geba14dd"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.4.0-1647-gc664170"
-#define VERSION_STRING      " v1.4.0-1647-gc664170"
+#define VERSION_STRING_NOSP "v1.4.0-1655-geba14dd"
+#define VERSION_STRING      " v1.4.0-1655-geba14dd"