From b573f693316de8ac6cf6cbb47457cd20830c8c0d Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 8 Jul 2014 18:27:59 -0700 Subject: [PATCH] Bug 1001957 - Don't use a CPOW for reload. r=felipe/mccr8/smaug Original patch from billm. --- browser/base/content/browser.js | 24 ++----- browser/base/content/content.js | 28 ++++++++ .../content/test/general/browser_bug822367.js | 8 ++- dom/base/nsDOMWindowUtils.cpp | 69 +++++++++++++++++++ .../mochitest/browserElement_KeyEvents.js | 5 ++ dom/interfaces/base/nsIDOMWindowUtils.idl | 19 ++++- 6 files changed, 134 insertions(+), 19 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index ea25acc7f94..38a76754e92 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2632,24 +2632,14 @@ function BrowserReloadWithFlags(reloadFlags) { return; } - /* First, we'll try to use the session history object to reload so - * that framesets are handled properly. If we're in a special - * window (such as view-source) that has no session history, fall - * back on using the web navigation's reload method. - */ + let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); - var webNav = gBrowser.webNavigation; - try { - var sh = webNav.sessionHistory; - if (sh) - webNav = sh.QueryInterface(nsIWebNavigation); - } catch (e) { - } - - try { - webNav.reload(reloadFlags); - } catch (e) { - } + gBrowser.selectedBrowser + .messageManager + .sendAsyncMessage("Browser:Reload", + { flags: reloadFlags, + handlingUserInput: windowUtils.isHandlingUserInput }); } var PrintPreviewListener = { diff --git a/browser/base/content/content.js b/browser/base/content/content.js index d4034c6831a..87b9d4ae3b7 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -34,6 +34,34 @@ addMessageListener("Browser:HideSessionRestoreButton", function (message) { } }); +addMessageListener("Browser:Reload", function(message) { + /* First, we'll try to use the session history object to reload so + * that framesets are handled properly. If we're in a special + * window (such as view-source) that has no session history, fall + * back on using the web navigation's reload method. + */ + + let webNav = docShell.QueryInterface(Ci.nsIWebNavigation); + try { + let sh = webNav.sessionHistory; + if (sh) + webNav = sh.QueryInterface(Ci.nsIWebNavigation); + } catch (e) { + } + + let reloadFlags = message.data.flags; + let handlingUserInput; + try { + handlingUserInput = content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils) + .setHandlingUserInput(message.data.handlingUserInput); + webNav.reload(reloadFlags); + } catch (e) { + } finally { + handlingUserInput.destruct(); + } +}); + addEventListener("DOMFormHasPassword", function(event) { InsecurePasswordUtils.checkForInsecurePasswords(event.target); LoginManagerContent.onFormPassword(event); diff --git a/browser/base/content/test/general/browser_bug822367.js b/browser/base/content/test/general/browser_bug822367.js index 780fae952cf..a0a091a6a3c 100644 --- a/browser/base/content/test/general/browser_bug822367.js +++ b/browser/base/content/test/general/browser_bug822367.js @@ -173,7 +173,13 @@ function MixedTest6B() { function MixedTest6C() { gTestBrowser.removeEventListener("load", MixedTest6C, true); - waitForCondition(function() content.document.getElementById('f1').contentDocument.getElementById('p1').innerHTML == "hello", MixedTest6D, "Waited too long for mixed script to run in Test 6"); + waitForCondition(function() { + try { + return content.document.getElementById('f1').contentDocument.getElementById('p1').innerHTML == "hello"; + } catch (e) { + return false; + } + }, MixedTest6D, "Waited too long for mixed script to run in Test 6"); } function MixedTest6D() { ok(content.document.getElementById('f1').contentDocument.getElementById('p1').innerHTML == "hello","Mixed script didn't load in Test 6"); diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 020cf2936e4..8042aad6118 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sts=2 sw=2 et tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -3587,6 +3588,74 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement, return NS_OK; } +namespace { + +class HandlingUserInputHelper MOZ_FINAL : public nsIJSRAIIHelper +{ +public: + HandlingUserInputHelper(bool aHandlingUserInput); + + NS_DECL_ISUPPORTS + NS_DECL_NSIJSRAIIHELPER + +private: + ~HandlingUserInputHelper(); + + bool mHandlingUserInput; + bool mDestructCalled; +}; + +NS_IMPL_ISUPPORTS(HandlingUserInputHelper, nsIJSRAIIHelper) + +HandlingUserInputHelper::HandlingUserInputHelper(bool aHandlingUserInput) + : mHandlingUserInput(aHandlingUserInput), + mDestructCalled(false) +{ + if (aHandlingUserInput) { + EventStateManager::StartHandlingUserInput(); + } +} + +HandlingUserInputHelper::~HandlingUserInputHelper() +{ + // We assert, but just in case, make sure we notify the ESM. + MOZ_ASSERT(mDestructCalled); + if (!mDestructCalled) { + Destruct(); + } +} + +NS_IMETHODIMP +HandlingUserInputHelper::Destruct() +{ + if (NS_WARN_IF(mDestructCalled)) { + return NS_ERROR_FAILURE; + } + + mDestructCalled = true; + if (mHandlingUserInput) { + EventStateManager::StopHandlingUserInput(); + } + + return NS_OK; +} + +} + +NS_IMETHODIMP +nsDOMWindowUtils::SetHandlingUserInput(bool aHandlingUserInput, + nsIJSRAIIHelper** aHelper) +{ + if (!nsContentUtils::IsCallerChrome()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsRefPtr helper( + new HandlingUserInputHelper(aHandlingUserInput)); + helper.forget(aHelper); + return NS_OK; +} + NS_IMETHODIMP nsDOMWindowUtils::GetContentAPZTestData(JSContext* aContext, JS::MutableHandleValue aOutContentTestData) diff --git a/dom/browser-element/mochitest/browserElement_KeyEvents.js b/dom/browser-element/mochitest/browserElement_KeyEvents.js index 9a2f6ddd6a2..f6367e1bcb2 100644 --- a/dom/browser-element/mochitest/browserElement_KeyEvents.js +++ b/dom/browser-element/mochitest/browserElement_KeyEvents.js @@ -76,6 +76,11 @@ function eventHandler(e) { nbEvents--; + // Prevent default for F5 because on desktop that reloads the page. + if (e.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_F5) { + e.preventDefault(); + } + if (nbEvents == 0) { SimpleTest.finish(); return; diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 2115e625831..d544837dc33 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -47,8 +47,9 @@ interface nsIDOMEventTarget; interface nsIRunnable; interface nsICompositionStringSynthesizer; interface nsITranslationNodeList; +interface nsIJSRAIIHelper; -[scriptable, uuid(46e3f206-9a8f-4d66-8248-7ec6a37de45a)] +[scriptable, uuid(e156a9f5-d0e3-4a2f-a4a8-19c648d5ecb9)] interface nsIDOMWindowUtils : nsISupports { /** @@ -1638,6 +1639,13 @@ interface nsIDOMWindowUtils : nsISupports { */ AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty); + /** + * If we are currently handling user input, this informs the event state + * manager. Remember to call destruct() on the return value! + * See also nsIDOMWindowUtils::isHandlingUserInput. + */ + nsIJSRAIIHelper setHandlingUserInput(in boolean aHandlingInput); + /** * Get the content- and compositor-side APZ test data instances. * The return values are of type APZTestData (see APZTestData.webidl). @@ -1674,3 +1682,12 @@ interface nsITranslationNodeList : nsISupports { // which its parent is not a translation node. boolean isTranslationRootAtIndex(in unsigned long index); }; + +/** + * JS doesn't do RAII very well. We can use this interface to make remembering + * to destruct an object in a finally clause easier. + */ +[scriptable, uuid(52e5a996-d0a9-4efc-a6fa-24489c532b19)] +interface nsIJSRAIIHelper : nsISupports { + void destruct(); +};