[TabDiscarding] Differentiate between beforeunload and unload handlers

To enable fast killing of tabs in more situations, the TabManager need
to be aware of the cause of the sudden termination disabler. This CL
propagates the disabler type to the RenderFrameHostImpl where it can be
stored and queried.

This step is required to enable the TabManager to fastkill in more
situations.

This CL is extracted from oysteine's CL:
https://chromium-review.googlesource.com/c/537072 which I took over
with his permission.

Bug: chromium:731264,chromium:123049
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_site_isolation
Change-Id: Ibd3a96df76793d4808bf84edecf4353093d81620
Reviewed-on: https://chromium-review.googlesource.com/562616
Commit-Queue: Fadi Meawad <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Reviewed-by: Chris Hamilton <[email protected]>
Cr-Commit-Position: refs/heads/master@{#487680}
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 4d234c0..ed95369 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -81,6 +81,7 @@
   "+third_party/WebKit/public/platform/WebReferrerPolicy.h",
   "+third_party/WebKit/public/platform/WebScreenInfo.h",
   "+third_party/WebKit/public/platform/WebSecurityStyle.h",
+  "+third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h",
   "+third_party/WebKit/public/platform/WebTouchEvent.h",
   "+third_party/WebKit/public/platform/WebTextInputType.h",
   "+third_party/WebKit/public/platform/mac/WebScrollbarTheme.h",
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index fba3353..7ed45ca 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -906,6 +906,8 @@
     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_SnapshotResponse,
                         OnAccessibilitySnapshotResponse)
     IPC_MESSAGE_HANDLER(FrameHostMsg_ToggleFullscreen, OnToggleFullscreen)
+    IPC_MESSAGE_HANDLER(FrameHostMsg_SuddenTerminationDisablerChanged,
+                        OnSuddenTerminationDisablerChanged)
     IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading)
     IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
     IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress,
@@ -2576,6 +2578,22 @@
   }
 }
 
+void RenderFrameHostImpl::OnSuddenTerminationDisablerChanged(
+    bool present,
+    blink::WebSuddenTerminationDisablerType disabler_type) {
+  DCHECK_NE(GetSuddenTerminationDisablerState(disabler_type), present);
+  if (present) {
+    sudden_termination_disabler_types_enabled_ |= disabler_type;
+  } else {
+    sudden_termination_disabler_types_enabled_ &= ~disabler_type;
+  }
+}
+
+bool RenderFrameHostImpl::GetSuddenTerminationDisablerState(
+    blink::WebSuddenTerminationDisablerType disabler_type) {
+  return (sudden_termination_disabler_types_enabled_ & disabler_type) != 0;
+}
+
 void RenderFrameHostImpl::OnDidStopLoading() {
   TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnDidStopLoading",
                "frame_tree_node", frame_tree_node_->frame_tree_node_id());
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index ebe6e6f..39ebd9c 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -53,6 +53,7 @@
 #include "services/device/public/interfaces/wake_lock_context.mojom.h"
 #include "third_party/WebKit/public/platform/WebFocusType.h"
 #include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
+#include "third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h"
 #include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
 #include "third_party/WebKit/public/web/WebTextDirection.h"
 #include "third_party/WebKit/public/web/WebTreeScopeType.h"
@@ -193,6 +194,9 @@
   void ResumeBlockedRequestsForFrame() override;
   void DisableBeforeUnloadHangMonitorForTesting() override;
   bool IsBeforeUnloadHangMonitorDisabledForTesting() override;
+  bool GetSuddenTerminationDisablerState(
+      blink::WebSuddenTerminationDisablerType disabler_type) override;
+
   bool IsFeatureEnabled(blink::WebFeaturePolicyFeature feature) override;
 
   // mojom::FrameHostInterfaceBroker
@@ -788,6 +792,9 @@
                                 base::string16 text,
                                 base::string16 html);
   void OnToggleFullscreen(bool enter_fullscreen);
+  void OnSuddenTerminationDisablerChanged(
+      bool present,
+      blink::WebSuddenTerminationDisablerType disabler_type);
   void OnDidStartLoading(bool to_different_document);
   void OnDidStopLoading();
   void OnDidChangeLoadProgress(double load_progress);
@@ -1220,6 +1227,10 @@
       PendingNavigation;
   std::unique_ptr<PendingNavigation> pendinging_navigate_;
 
+  // Bitfield for renderer-side state that blocks fast shutdown of the frame.
+  blink::WebSuddenTerminationDisablerType
+      sudden_termination_disabler_types_enabled_ = 0;
+
   // Callback for responding when
   // |FrameHostMsg_TextSurroundingSelectionResponse| message comes.
   TextSurroundingSelectionCallback text_surrounding_selection_callback_;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index fea1eb6..0570818 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -938,6 +938,57 @@
 }
 
 namespace {
+void NavigateToDataURLAndCheckForTerminationDisabler(
+    Shell* shell,
+    const std::string& html,
+    bool expect_onunload,
+    bool expect_onbeforeunload) {
+  NavigateToURL(shell, GURL("data:text/html," + html));
+  RenderFrameHostImpl* rfh =
+      static_cast<RenderFrameHostImpl*>(shell->web_contents()->GetMainFrame());
+  EXPECT_EQ(expect_onunload,
+            rfh->GetSuddenTerminationDisablerState(blink::kUnloadHandler));
+  EXPECT_EQ(expect_onbeforeunload, rfh->GetSuddenTerminationDisablerState(
+                                       blink::kBeforeUnloadHandler));
+}
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       SuddenTerminationDisablerNone) {
+  const std::string NO_HANDLERS_HTML = "<html><body>foo</body></html>";
+  NavigateToDataURLAndCheckForTerminationDisabler(shell(), NO_HANDLERS_HTML,
+                                                  false, false);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       SuddenTerminationDisablerOnUnload) {
+  const std::string UNLOAD_HTML =
+      "<html><body><script>window.onunload=function(e) {}</script>"
+      "</body></html>";
+  NavigateToDataURLAndCheckForTerminationDisabler(shell(), UNLOAD_HTML, true,
+                                                  false);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       SuddenTerminationDisablerOnBeforeUnload) {
+  const std::string BEFORE_UNLOAD_HTML =
+      "<html><body><script>window.onbeforeunload=function(e) {}</script>"
+      "</body></html>";
+  NavigateToDataURLAndCheckForTerminationDisabler(shell(), BEFORE_UNLOAD_HTML,
+                                                  false, true);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       SuddenTerminationDisablerOnUnloadAndBeforeUnload) {
+  const std::string UNLOAD_AND_BEFORE_UNLOAD_HTML =
+      "<html><body><script>window.onunload=function(e) {};"
+      "window.onbeforeunload=function(e) {}</script>"
+      "</body></html>";
+  NavigateToDataURLAndCheckForTerminationDisabler(
+      shell(), UNLOAD_AND_BEFORE_UNLOAD_HTML, true, true);
+}
+
+namespace {
 
 class TestJavaScriptDialogManager : public JavaScriptDialogManager,
                                     public WebContentsDelegate {
diff --git a/content/common/DEPS b/content/common/DEPS
index a7b3f43..9538e1d 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -35,6 +35,7 @@
   "+third_party/WebKit/public/platform/WebScreenInfo.h",
   "+third_party/WebKit/public/platform/WebScrollbarButtonsPlacement.h",
   "+third_party/WebKit/public/platform/WebStorageArea.h",
+  "+third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h",
   "+third_party/WebKit/public/platform/WebTouchEvent.h",
   "+third_party/WebKit/public/platform/linux/WebFallbackFont.h",
   "+third_party/WebKit/public/platform/mac/WebScrollbarTheme.h",
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index e2788736..168d64f 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -54,6 +54,7 @@
 #include "third_party/WebKit/public/platform/WebFeaturePolicy.h"
 #include "third_party/WebKit/public/platform/WebFocusType.h"
 #include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
+#include "third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h"
 #include "third_party/WebKit/public/web/WebFindOptions.h"
 #include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
 #include "third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h"
@@ -1578,6 +1579,12 @@
 // See the comment in chrome/browser/ui/browser.h for more details.
 IPC_MESSAGE_ROUTED1(FrameHostMsg_ToggleFullscreen, bool /* enter_fullscreen */)
 
+// Sent when a new sudden termination disabler condition is either introduced or
+// removed.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_SuddenTerminationDisablerChanged,
+                    bool /* present */,
+                    blink::WebSuddenTerminationDisablerType /* disabler_type */)
+
 // Dispatch a load event for this frame in the iframe element of an
 // out-of-process parent frame.
 IPC_MESSAGE_ROUTED0(FrameHostMsg_DispatchLoad)
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index c155b229..11f5f90 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -16,6 +16,7 @@
 #include "ipc/ipc_sender.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
+#include "third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 #include "url/gurl.h"
@@ -284,6 +285,11 @@
   virtual void DisableBeforeUnloadHangMonitorForTesting() = 0;
   virtual bool IsBeforeUnloadHangMonitorDisabledForTesting() = 0;
 
+  // Check whether the specific Blink feature is currently preventing fast
+  // shutdown of the frame.
+  virtual bool GetSuddenTerminationDisablerState(
+      blink::WebSuddenTerminationDisablerType disabler_type) = 0;
+
   // Returns true if the given Feature Policy |feature| is enabled for this
   // RenderFrameHost and is allowed to be used by it. Use this in the browser
   // process to determine whether access to a feature is allowed.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index e29e6f1..1153000a 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4707,6 +4707,13 @@
   Send(new FrameHostMsg_ToggleFullscreen(routing_id_, false));
 }
 
+void RenderFrameImpl::SuddenTerminationDisablerChanged(
+    bool present,
+    blink::WebSuddenTerminationDisablerType disabler_type) {
+  Send(new FrameHostMsg_SuddenTerminationDisablerChanged(routing_id_, present,
+                                                         disabler_type));
+}
+
 void RenderFrameImpl::RegisterProtocolHandler(const WebString& scheme,
                                               const WebURL& url,
                                               const WebString& title) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 6f6388c..39309d0a 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -662,6 +662,9 @@
   void DidChangeManifest() override;
   void EnterFullscreen() override;
   void ExitFullscreen() override;
+  void SuddenTerminationDisablerChanged(
+      bool present,
+      blink::WebSuddenTerminationDisablerType disabler_type) override;
   void RegisterProtocolHandler(const blink::WebString& scheme,
                                const blink::WebURL& url,
                                const blink::WebString& title) override;
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index 176fd8cb1..03394ef 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -171,7 +171,7 @@
 static void UpdateSuddenTerminationStatus(
     LocalDOMWindow* dom_window,
     bool added_listener,
-    LocalFrameClient::SuddenTerminationDisablerType disabler_type) {
+    WebSuddenTerminationDisablerType disabler_type) {
   Platform::Current()->SuddenTerminationChanged(!added_listener);
   if (dom_window->GetFrame() && dom_window->GetFrame()->Client())
     dom_window->GetFrame()->Client()->SuddenTerminationDisablerChanged(
@@ -191,80 +191,60 @@
   return windows_with_before_unload_event_listeners;
 }
 
-static void AddUnloadEventListener(LocalDOMWindow* dom_window) {
+static void TrackUnloadEventListener(LocalDOMWindow* dom_window) {
   DOMWindowSet& set = WindowsWithUnloadEventListeners();
-  if (set.IsEmpty()) {
-    UpdateSuddenTerminationStatus(dom_window, true,
-                                  LocalFrameClient::kUnloadHandler);
+  if (set.insert(dom_window).is_new_entry) {
+    // The first unload handler was added.
+    UpdateSuddenTerminationStatus(dom_window, true, kUnloadHandler);
   }
-
-  set.insert(dom_window);
 }
 
-static void RemoveUnloadEventListener(LocalDOMWindow* dom_window) {
+static void UntrackUnloadEventListener(LocalDOMWindow* dom_window) {
   DOMWindowSet& set = WindowsWithUnloadEventListeners();
   DOMWindowSet::iterator it = set.find(dom_window);
   if (it == set.end())
     return;
-  set.erase(it);
-  if (set.IsEmpty()) {
-    UpdateSuddenTerminationStatus(dom_window, false,
-                                  LocalFrameClient::kUnloadHandler);
+  if (set.erase(it)) {
+    // The last unload handler was removed.
+    UpdateSuddenTerminationStatus(dom_window, false, kUnloadHandler);
   }
 }
 
-static void RemoveAllUnloadEventListeners(LocalDOMWindow* dom_window) {
+static void UntrackAllUnloadEventListeners(LocalDOMWindow* dom_window) {
   DOMWindowSet& set = WindowsWithUnloadEventListeners();
   DOMWindowSet::iterator it = set.find(dom_window);
   if (it == set.end())
     return;
   set.RemoveAll(it);
-  if (set.IsEmpty()) {
-    UpdateSuddenTerminationStatus(dom_window, false,
-                                  LocalFrameClient::kUnloadHandler);
-  }
+  UpdateSuddenTerminationStatus(dom_window, false, kUnloadHandler);
 }
 
-static void AddBeforeUnloadEventListener(LocalDOMWindow* dom_window) {
+static void TrackBeforeUnloadEventListener(LocalDOMWindow* dom_window) {
   DOMWindowSet& set = WindowsWithBeforeUnloadEventListeners();
-  if (set.IsEmpty()) {
-    UpdateSuddenTerminationStatus(dom_window, true,
-                                  LocalFrameClient::kBeforeUnloadHandler);
+  if (set.insert(dom_window).is_new_entry) {
+    // The first beforeunload handler was added.
+    UpdateSuddenTerminationStatus(dom_window, true, kBeforeUnloadHandler);
   }
-
-  set.insert(dom_window);
 }
 
-static void RemoveBeforeUnloadEventListener(LocalDOMWindow* dom_window) {
+static void UntrackBeforeUnloadEventListener(LocalDOMWindow* dom_window) {
   DOMWindowSet& set = WindowsWithBeforeUnloadEventListeners();
   DOMWindowSet::iterator it = set.find(dom_window);
   if (it == set.end())
     return;
-  set.erase(it);
-  if (set.IsEmpty()) {
-    UpdateSuddenTerminationStatus(dom_window, false,
-                                  LocalFrameClient::kBeforeUnloadHandler);
+  if (set.erase(it)) {
+    // The last beforeunload handler was removed.
+    UpdateSuddenTerminationStatus(dom_window, false, kBeforeUnloadHandler);
   }
 }
 
-static void RemoveAllBeforeUnloadEventListeners(LocalDOMWindow* dom_window) {
+static void UntrackAllBeforeUnloadEventListeners(LocalDOMWindow* dom_window) {
   DOMWindowSet& set = WindowsWithBeforeUnloadEventListeners();
   DOMWindowSet::iterator it = set.find(dom_window);
   if (it == set.end())
     return;
   set.RemoveAll(it);
-  if (set.IsEmpty()) {
-    UpdateSuddenTerminationStatus(dom_window, false,
-                                  LocalFrameClient::kBeforeUnloadHandler);
-  }
-}
-
-static bool AllowsBeforeUnloadListeners(LocalDOMWindow* window) {
-  DCHECK(window);
-  LocalFrame* frame = window->GetFrame();
-  if (!frame)
-    return false;
-  return frame->IsMainFrame();
+  UpdateSuddenTerminationStatus(dom_window, false, kBeforeUnloadHandler);
 }
 
 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame)
@@ -1438,17 +1418,11 @@
 
   if (event_type == EventTypeNames::unload) {
     UseCounter::Count(document(), WebFeature::kDocumentUnloadRegistered);
-    AddUnloadEventListener(this);
+    TrackUnloadEventListener(this);
   } else if (event_type == EventTypeNames::beforeunload) {
     UseCounter::Count(document(), WebFeature::kDocumentBeforeUnloadRegistered);
-    if (AllowsBeforeUnloadListeners(this)) {
-      // This is confusingly named. It doesn't actually add the listener. It
-      // just increments a count so that we know we have listeners registered
-      // for the purposes of determining if we can fast terminate the renderer
-      // process.
-      AddBeforeUnloadEventListener(this);
-    } else {
-      // Subframes return false from allowsBeforeUnloadListeners.
+    TrackBeforeUnloadEventListener(this);
+    if (GetFrame() && !GetFrame()->IsMainFrame()) {
       UseCounter::Count(document(),
                         WebFeature::kSubFrameBeforeUnloadRegistered);
     }
@@ -1468,10 +1442,9 @@
   }
 
   if (event_type == EventTypeNames::unload) {
-    RemoveUnloadEventListener(this);
-  } else if (event_type == EventTypeNames::beforeunload &&
-             AllowsBeforeUnloadListeners(this)) {
-    RemoveBeforeUnloadEventListener(this);
+    UntrackUnloadEventListener(this);
+  } else if (event_type == EventTypeNames::beforeunload) {
+    UntrackBeforeUnloadEventListener(this);
   }
 }
 
@@ -1562,8 +1535,8 @@
     GetFrame()->GetPage()->GetEventHandlerRegistry().DidRemoveAllEventHandlers(
         *this);
 
-  RemoveAllUnloadEventListeners(this);
-  RemoveAllBeforeUnloadEventListeners(this);
+  UntrackAllUnloadEventListeners(this);
+  UntrackAllBeforeUnloadEventListeners(this);
 }
 
 void LocalDOMWindow::FinishedLoading() {
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
index 02967c9..402eac4 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -54,6 +54,7 @@
 #include "public/platform/WebFeaturePolicy.h"
 #include "public/platform/WebInsecureRequestPolicy.h"
 #include "public/platform/WebLoadingBehaviorFlag.h"
+#include "public/platform/WebSuddenTerminationDisablerType.h"
 #include "public/platform/WebURLRequest.h"
 #include "public/web/WebTriggeringEventInfo.h"
 #include "v8/include/v8.h"
@@ -302,16 +303,9 @@
 
   virtual bool IsLocalFrameClientImpl() const { return false; }
 
-  // Called when elements preventing the sudden termination of the frame become
-  // present or stop being present. |type| is the type of element (BeforeUnload
-  // handler, Unload handler).
-  enum SuddenTerminationDisablerType {
-    kBeforeUnloadHandler,
-    kUnloadHandler,
-  };
-  virtual void SuddenTerminationDisablerChanged(bool present,
-                                                SuddenTerminationDisablerType) {
-  }
+  virtual void SuddenTerminationDisablerChanged(
+      bool present,
+      WebSuddenTerminationDisablerType) {}
 
   virtual LinkResource* CreateServiceWorkerLinkResource(HTMLLinkElement*) {
     return nullptr;
diff --git a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
index b81ff82a..04746bc 100644
--- a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
+++ b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
@@ -419,11 +419,6 @@
                    kSandboxPropagatesToAuxiliaryBrowsingContexts);
 STATIC_ASSERT_ENUM(WebSandboxFlags::kModals, kSandboxModals);
 
-STATIC_ASSERT_ENUM(LocalFrameClient::kBeforeUnloadHandler,
-                   WebFrameClient::kBeforeUnloadHandler);
-STATIC_ASSERT_ENUM(LocalFrameClient::kUnloadHandler,
-                   WebFrameClient::kUnloadHandler);
-
 STATIC_ASSERT_ENUM(WebFrameLoadType::kStandard, kFrameLoadTypeStandard);
 STATIC_ASSERT_ENUM(WebFrameLoadType::kBackForward, kFrameLoadTypeBackForward);
 STATIC_ASSERT_ENUM(WebFrameLoadType::kReload, kFrameLoadTypeReload);
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
index 10c2fe5..cac5d29 100644
--- a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
@@ -989,11 +989,9 @@
 
 void LocalFrameClientImpl::SuddenTerminationDisablerChanged(
     bool present,
-    SuddenTerminationDisablerType type) {
+    WebSuddenTerminationDisablerType type) {
   if (web_frame_->Client()) {
-    web_frame_->Client()->SuddenTerminationDisablerChanged(
-        present,
-        static_cast<WebFrameClient::SuddenTerminationDisablerType>(type));
+    web_frame_->Client()->SuddenTerminationDisablerChanged(present, type);
   }
 }
 
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.h b/third_party/WebKit/Source/web/LocalFrameClientImpl.h
index c6a7dc4..c02c52d3 100644
--- a/third_party/WebKit/Source/web/LocalFrameClientImpl.h
+++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.h
@@ -210,8 +210,9 @@
 
   unsigned BackForwardLength() override;
 
-  void SuddenTerminationDisablerChanged(bool present,
-                                        SuddenTerminationDisablerType) override;
+  void SuddenTerminationDisablerChanged(
+      bool present,
+      WebSuddenTerminationDisablerType) override;
 
   BlameContext* GetFrameBlameContext() override;
 
diff --git a/third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h b/third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h
new file mode 100644
index 0000000..437308dd
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h
@@ -0,0 +1,18 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebSuddenTerminationDisablerType_h
+#define WebSuddenTerminationDisablerType_h
+
+namespace blink {
+
+// Used when elements preventing the sudden termination of the frame become
+// present or become absent.
+using WebSuddenTerminationDisablerType = uint8_t;
+const WebSuddenTerminationDisablerType kBeforeUnloadHandler = 1 << 0;
+const WebSuddenTerminationDisablerType kUnloadHandler = 1 << 1;
+
+}  // namespace blink
+
+#endif  // WebSuddenTerminationDisablerType_h
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h
index c0a14fd6..5c48b2d 100644
--- a/third_party/WebKit/public/web/WebFrameClient.h
+++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -68,6 +68,7 @@
 #include "public/platform/WebSourceLocation.h"
 #include "public/platform/WebStorageQuotaCallbacks.h"
 #include "public/platform/WebStorageQuotaType.h"
+#include "public/platform/WebSuddenTerminationDisablerType.h"
 #include "public/platform/WebURLError.h"
 #include "public/platform/WebURLLoader.h"
 #include "public/platform/WebURLRequest.h"
@@ -769,13 +770,9 @@
   // Called when elements preventing the sudden termination of the frame
   // become present or stop being present. |type| is the type of element
   // (BeforeUnload handler, Unload handler).
-  enum SuddenTerminationDisablerType {
-    kBeforeUnloadHandler,
-    kUnloadHandler,
-  };
-  virtual void SuddenTerminationDisablerChanged(bool present,
-                                                SuddenTerminationDisablerType) {
-  }
+  virtual void SuddenTerminationDisablerChanged(
+      bool present,
+      WebSuddenTerminationDisablerType) {}
 
   // Navigator Content Utils  --------------------------------------------