Gracefully handle a disconnected popup menu client on disposing open popup.

If the client of a PopupMenu disconnects itself before destructing a
currently open popup menu (and its page), handle the fact that the client
is not reachable for notifications.

R=keishi,haraken
BUG=457383

Review URL: https://codereview.chromium.org/920433002

git-svn-id: svn://svn.chromium.org/blink/trunk@189983 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/third_party/WebKit/LayoutTests/fast/forms/resources/popup-no-crash.html b/third_party/WebKit/LayoutTests/fast/forms/resources/popup-no-crash.html
new file mode 100644
index 0000000..9eb61bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/resources/popup-no-crash.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<script src="../../../resources/js-test.js"></script>
+<script>
+description("Check that first disconnecting then closing a page popup does not crash.");
+testPassed("no crash");
+
+testRunner.notifyDone();
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select-popup-close-no-crash-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/select-popup-close-no-crash-expected.txt
new file mode 100644
index 0000000..61d484c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select-popup-close-no-crash-expected.txt
@@ -0,0 +1,10 @@
+Check that first disconnecting then closing a page popup does not crash.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no crash
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select-popup-close-no-crash.html b/third_party/WebKit/LayoutTests/fast/forms/select-popup-close-no-crash.html
new file mode 100644
index 0000000..87b7f2b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select-popup-close-no-crash.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="resources/picker-common.js"></script>
+</head>
+<body>
+<select id="menu">
+<option>foo</option>
+<option>bar</option>
+</select>
+<form action="resources/popup-no-crash.html" id="form1"></form>
+<script>
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function openCallback() {
+    document.getElementById('form1').submit();
+}
+
+function errorCallback() {
+    window.location = "resources/popup-no-crash.html";
+}
+
+window.onload = function () {
+    openPicker(document.getElementById('menu'), openCallback, errorCallback);
+}
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 04356d0..4241f1b 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -919,7 +919,11 @@
     DocumentLifecycle::DetachScope willDetach(document().lifecycle());
 
 #if ENABLE(ASSERT)
-    ASSERT(!detachingNode);
+    // The detaching might trigger destruction of a popup menu window,
+    // with ensuing detachment of its Nodes. In a separate document, so
+    // don't assert for these, but do set detachingNode to the most recent
+    // Node being detached.
+    ASSERT(!detachingNode || detachingNode->document() != document());
     detachingNode = this;
 #endif
 
diff --git a/third_party/WebKit/Source/web/PopupMenuImpl.cpp b/third_party/WebKit/Source/web/PopupMenuImpl.cpp
index a0bc7f3..40695b6 100644
--- a/third_party/WebKit/Source/web/PopupMenuImpl.cpp
+++ b/third_party/WebKit/Source/web/PopupMenuImpl.cpp
@@ -234,11 +234,12 @@
 
 void PopupMenuImpl::didClosePopup()
 {
-    if (m_indexToSetOnClose >= 0)
+    if (m_client && m_indexToSetOnClose >= 0)
         m_client->valueChanged(m_indexToSetOnClose);
     m_indexToSetOnClose = -1;
     m_popup = nullptr;
-    m_client->popupDidHide();
+    if (m_client)
+        m_client->popupDidHide();
 }
 
 Element& PopupMenuImpl::ownerElement()