Re-allow JavaScript dialogs with user navigation.
BUG=587922
TEST=as in bug
Review URL: https://codereview.chromium.org/1733763002
Cr-Commit-Position: refs/heads/master@{#377597}
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index d748d53..3103e95e 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3153,6 +3153,11 @@
if (!details.is_in_page)
CancelActiveAndPendingDialogs();
+ // If this is a user-initiated navigation, start allowing JavaScript dialogs
+ // again.
+ if (params.gesture == NavigationGestureUser && dialog_manager_)
+ dialog_manager_->ResetDialogState(this);
+
// Notify observers about navigation.
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidNavigateAnyFrame(render_frame_host, details, params));
@@ -4793,4 +4798,9 @@
FOR_EACH_OBSERVER(WebContentsObserver, observers_, MediaStoppedPlaying(id));
}
+void WebContentsImpl::SetJavaScriptDialogManagerForTesting(
+ JavaScriptDialogManager* dialog_manager) {
+ dialog_manager_ = dialog_manager;
+}
+
} // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 753c690..79c0c86e 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -744,6 +744,8 @@
LoadResourceFromMemoryCacheWithBadSecurityInfo);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest,
LoadResourceFromMemoryCacheWithEmptySecurityInfo);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest,
+ ResetJavaScriptDialogOnUserNavigate);
FRIEND_TEST_ALL_PREFIXES(FormStructureBrowserTest, HTMLFiles);
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, PageDoesBackAndReload);
@@ -1028,6 +1030,9 @@
// the main frame if empty).
WebUI* CreateWebUI(const GURL& url, const std::string& frame_name);
+ void SetJavaScriptDialogManagerForTesting(
+ JavaScriptDialogManager* dialog_manager);
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 965da64..45d920b 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -28,6 +28,7 @@
#include "content/common/view_messages.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/interstitial_page_delegate.h"
+#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
@@ -3384,4 +3385,69 @@
EXPECT_TRUE(backend->HasAllowException(test_url.host()));
}
+class TestJavaScriptDialogManager : public JavaScriptDialogManager {
+ public:
+ TestJavaScriptDialogManager() {}
+ ~TestJavaScriptDialogManager() override {}
+
+ size_t reset_count() { return reset_count_; }
+
+ // JavaScriptDialogManager
+
+ void RunJavaScriptDialog(WebContents* web_contents,
+ const GURL& origin_url,
+ const std::string& accept_lang,
+ JavaScriptMessageType javascript_message_type,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
+ const DialogClosedCallback& callback,
+ bool* did_suppress_message) override {
+ *did_suppress_message = true;
+ };
+
+ void RunBeforeUnloadDialog(WebContents* web_contents,
+ const base::string16& message_text,
+ bool is_reload,
+ const DialogClosedCallback& callback) override {}
+
+ bool HandleJavaScriptDialog(WebContents* web_contents,
+ bool accept,
+ const base::string16* prompt_override) override {
+ return true;
+ }
+
+ void CancelActiveAndPendingDialogs(WebContents* web_contents) override {}
+
+ void ResetDialogState(WebContents* web_contents) override { ++reset_count_; }
+
+ private:
+ size_t reset_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
+};
+
+TEST_F(WebContentsImplTest, ResetJavaScriptDialogOnUserNavigate) {
+ scoped_ptr<TestJavaScriptDialogManager> delegate(
+ new TestJavaScriptDialogManager());
+ contents()->SetJavaScriptDialogManagerForTesting(delegate.get());
+
+ // A user-initiated navigation.
+
+ contents()->GetMainFrame()->PrepareForCommit();
+ contents()->TestDidNavigate(contents()->GetMainFrame(), 1, 0, true,
+ GURL("about:whatever"),
+ ui::PAGE_TRANSITION_TYPED);
+ EXPECT_EQ(1u, delegate->reset_count());
+
+ // An automatic navigation.
+
+ contents()->GetMainFrame()->PrepareForCommit();
+ contents()->GetMainFrame()->SendNavigateWithModificationCallback(
+ 2, 0, true, GURL(url::kAboutBlankURL), base::Bind(SetAsNonUserGesture));
+
+ EXPECT_EQ(1u, delegate->reset_count());
+
+ contents()->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
} // namespace content