Bug 989875 - Forward clicks to chrome js for ux elements in about pages that load remotely. f=felipe, r=mbrubeck

This commit is contained in:
Jim Mathies 2014-07-02 14:27:35 -05:00
parent 8a4d765a29
commit fc2483e662
2 changed files with 112 additions and 65 deletions

View File

@ -779,6 +779,7 @@ var gBrowserInit = {
DOMLinkHandler.init();
gPageStyleMenu.init();
LanguageDetectionListener.init();
BrowserOnClick.init();
let mm = window.getGroupMessageManager("browsers");
mm.loadFrameScript("chrome://browser/content/content.js", true);
@ -1322,6 +1323,8 @@ var gBrowserInit = {
ToolbarIconColor.uninit();
BrowserOnClick.uninit();
var enumerator = Services.wm.getEnumerator(null);
enumerator.getNext();
if (!enumerator.hasMoreElements()) {
@ -2270,44 +2273,62 @@ function PageProxyClickHandler(aEvent)
/**
* Handle command events bubbling up from error page content
* or from about:newtab
* or from about:newtab or from remote error pages that invoke
* us via async messaging.
*/
let BrowserOnClick = {
handleEvent: function BrowserOnClick_handleEvent(aEvent) {
if (!aEvent.isTrusted || // Don't trust synthetic events
aEvent.button == 2) {
init: function () {
let mm = window.messageManager;
mm.addMessageListener("Browser:CertExceptionError", this);
mm.addMessageListener("Browser:SiteBlockedError", this);
mm.addMessageListener("Browser:NetworkError", this);
},
uninit: function () {
let mm = window.messageManager;
mm.removeMessageListener("Browser:CertExceptionError", this);
mm.removeMessageListener("Browser:SiteBlockedError", this);
mm.removeMessageListener("Browser:NetworkError", this);
},
handleEvent: function (event) {
if (!event.isTrusted || // Don't trust synthetic events
event.button == 2) {
return;
}
let originalTarget = aEvent.originalTarget;
let originalTarget = event.originalTarget;
let ownerDoc = originalTarget.ownerDocument;
// If the event came from an ssl error page, it is probably either the "Add
// Exception…" or "Get me out of here!" button
if (ownerDoc.documentURI.startsWith("about:certerror")) {
this.onAboutCertError(originalTarget, ownerDoc);
}
else if (ownerDoc.documentURI.startsWith("about:blocked")) {
this.onAboutBlocked(originalTarget, ownerDoc);
}
else if (ownerDoc.documentURI.startsWith("about:neterror")) {
this.onAboutNetError(originalTarget, ownerDoc);
}
else if (gMultiProcessBrowser &&
ownerDoc.documentURI.toLowerCase() == "about:newtab") {
this.onE10sAboutNewTab(aEvent, ownerDoc);
if (gMultiProcessBrowser &&
ownerDoc.documentURI.toLowerCase() == "about:newtab") {
this.onE10sAboutNewTab(event, ownerDoc);
}
else if (ownerDoc.documentURI.startsWith("about:tabcrashed")) {
this.onAboutTabCrashed(aEvent, ownerDoc);
this.onAboutTabCrashed(event, ownerDoc);
}
},
onAboutCertError: function BrowserOnClick_onAboutCertError(aTargetElm, aOwnerDoc) {
let elmId = aTargetElm.getAttribute("id");
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
let isTopFrame = (aOwnerDoc.defaultView.parent === aOwnerDoc.defaultView);
receiveMessage: function (msg) {
switch (msg.name) {
case "Browser:CertExceptionError":
this.onAboutCertError(msg.target, msg.json.elementId,
msg.json.isTopFrame, msg.json.location);
break;
case "Browser:SiteBlockedError":
this.onAboutBlocked(msg.json.elementId, msg.json.isMalware,
msg.json.isTopFrame, msg.json.location);
break;
case "Browser:NetworkError":
// Reset network state, the error page will refresh on its own.
Services.io.offline = false;
break;
}
},
switch (elmId) {
onAboutCertError: function (browser, elementId, isTopFrame, location) {
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
switch (elementId) {
case "exceptionDialogButton":
if (isTopFrame) {
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_CLICK_ADD_EXCEPTION);
@ -2319,7 +2340,7 @@ let BrowserOnClick = {
case 2 : // Pre-fetch & pre-populate
params.prefetchCert = true;
case 1 : // Pre-populate
params.location = aOwnerDoc.location.href;
params.location = location;
}
} catch (e) {
Components.utils.reportError("Couldn't get ssl_override pref: " + e);
@ -2330,7 +2351,7 @@ let BrowserOnClick = {
// If the user added the exception cert, attempt to reload the page
if (params.exceptionAdded) {
aOwnerDoc.location.reload();
browser.reload();
}
break;
@ -2356,20 +2377,14 @@ let BrowserOnClick = {
}
},
onAboutBlocked: function BrowserOnClick_onAboutBlocked(aTargetElm, aOwnerDoc) {
let elmId = aTargetElm.getAttribute("id");
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
// The event came from a button on a malware/phishing block page
// First check whether it's malware or phishing, so that we can
// use the right strings/links
let isMalware = /e=malwareBlocked/.test(aOwnerDoc.documentURI);
onAboutBlocked: function (elementId, isMalware, isTopFrame, location) {
// Depending on what page we are displaying here (malware/phishing)
// use the right strings and links for each.
let bucketName = isMalware ? "WARNING_MALWARE_PAGE_":"WARNING_PHISHING_PAGE_";
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
let nsISecTel = Ci.nsISecurityUITelemetry;
let isIframe = (aOwnerDoc.defaultView.parent === aOwnerDoc.defaultView);
bucketName += isIframe ? "TOP_" : "FRAME_";
switch (elmId) {
bucketName += isTopFrame ? "TOP_" : "FRAME_";
switch (elementId) {
case "getMeOutButton":
secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
getMeOutOfHere();
@ -2389,7 +2404,7 @@ let BrowserOnClick = {
// append the current url, and go there.
try {
let reportURL = formatURL("browser.safebrowsing.malware.reportURL", true);
reportURL += aOwnerDoc.location.href;
reportURL += location;
content.location = reportURL;
} catch (e) {
Components.utils.reportError("Couldn't get malware report URL: " + e);
@ -2413,17 +2428,17 @@ let BrowserOnClick = {
* the next page also in the parent) and instructs the browser to open the url
* in the current tab which will make it update the remoteness of the tab.
*/
onE10sAboutNewTab: function(aEvent, aOwnerDoc) {
let isTopFrame = (aOwnerDoc.defaultView.parent === aOwnerDoc.defaultView);
if (!isTopFrame || aEvent.button != 0) {
onE10sAboutNewTab: function(event, ownerDoc) {
let isTopFrame = (ownerDoc.defaultView.parent === ownerDoc.defaultView);
if (!isTopFrame || event.button != 0) {
return;
}
let anchorTarget = aEvent.originalTarget.parentNode;
let anchorTarget = event.originalTarget.parentNode;
if (anchorTarget instanceof HTMLAnchorElement &&
anchorTarget.classList.contains("newtab-link")) {
aEvent.preventDefault();
event.preventDefault();
openUILinkIn(anchorTarget.href, "current");
}
},
@ -2432,17 +2447,17 @@ let BrowserOnClick = {
* The about:tabcrashed can't do window.reload() because that
* would reload the page but not use a remote browser.
*/
onAboutTabCrashed: function(aEvent, aOwnerDoc) {
let isTopFrame = (aOwnerDoc.defaultView.parent === aOwnerDoc.defaultView);
onAboutTabCrashed: function(event, ownerDoc) {
let isTopFrame = (ownerDoc.defaultView.parent === ownerDoc.defaultView);
if (!isTopFrame) {
return;
}
let button = aEvent.originalTarget;
let button = event.originalTarget;
if (button.id == "tryAgain") {
#ifdef MOZ_CRASHREPORTER
if (aOwnerDoc.getElementById("checkSendReport").checked) {
let browser = gBrowser.getBrowserForDocument(aOwnerDoc);
if (ownerDoc.getElementById("checkSendReport").checked) {
let browser = gBrowser.getBrowserForDocument(ownerDoc);
TabCrashReporter.submitCrashReport(browser);
}
#endif
@ -2451,7 +2466,7 @@ let BrowserOnClick = {
}
},
ignoreWarningButton: function BrowserOnClick_ignoreWarningButton(aIsMalware) {
ignoreWarningButton: function (isMalware) {
// Allow users to override and continue through to the site,
// but add a notify bar as a reminder, so that they don't lose
// track after, e.g., tab switching.
@ -2470,7 +2485,7 @@ let BrowserOnClick = {
}];
let title;
if (aIsMalware) {
if (isMalware) {
title = gNavigatorBundle.getString("safebrowsing.reportedAttackSite");
buttons[1] = {
label: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.label"),
@ -2509,13 +2524,6 @@ let BrowserOnClick = {
// doesn't get removed on redirects.
notification.persistence = -1;
},
onAboutNetError: function BrowserOnClick_onAboutNetError(aTargetElm, aOwnerDoc) {
let elmId = aTargetElm.getAttribute("id");
if (elmId != "errorTryAgain" || !/e=netOffline/.test(aOwnerDoc.documentURI))
return;
Services.io.offline = false;
},
};
/**

View File

@ -258,10 +258,23 @@ let ClickEventHandler = {
},
handleEvent: function(event) {
// Bug 903016: Most of this code is an unfortunate duplication from
// contentAreaClick in browser.js.
if (!event.isTrusted || event.defaultPrevented || event.button == 2)
if (!event.isTrusted || event.defaultPrevented || event.button == 2) {
return;
}
let originalTarget = event.originalTarget;
let ownerDoc = originalTarget.ownerDocument;
// Handle click events from about pages
if (ownerDoc.documentURI.startsWith("about:certerror")) {
this.onAboutCertError(originalTarget, ownerDoc);
return;
} else if (ownerDoc.documentURI.startsWith("about:blocked")) {
this.onAboutBlocked(originalTarget, ownerDoc);
return;
} else if (ownerDoc.documentURI.startsWith("about:neterror")) {
this.onAboutNetError(originalTarget, ownerDoc);
}
let [href, node] = this._hrefAndLinkNodeForClickEvent(event);
@ -274,12 +287,12 @@ let ClickEventHandler = {
json.href = href;
if (node) {
json.title = node.getAttribute("title");
if (event.button == 0 && !event.ctrlKey && !event.shiftKey &&
!event.altKey && !event.metaKey) {
json.bookmark = node.getAttribute("rel") == "sidebar";
if (json.bookmark)
if (json.bookmark) {
event.preventDefault(); // Need to prevent the pageload.
}
}
}
@ -288,8 +301,34 @@ let ClickEventHandler = {
}
// This might be middle mouse navigation.
if (event.button == 1)
if (event.button == 1) {
sendAsyncMessage("Content:Click", json);
}
},
onAboutCertError: function (targetElement, ownerDoc) {
sendAsyncMessage("Browser:CertExceptionError", {
location: ownerDoc.location.href,
elementId: targetElement.getAttribute("id"),
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView)
});
},
onAboutBlocked: function (targetElement, ownerDoc) {
sendAsyncMessage("Browser:SiteBlockedError", {
location: ownerDoc.location.href,
isMalware: /e=malwareBlocked/.test(ownerDoc.documentURI),
elementId: targetElement.getAttribute("id"),
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView)
});
},
onAboutNetError: function (targetElement, ownerDoc) {
let elmId = targetElement.getAttribute("id");
if (elmId != "errorTryAgain" || !/e=netOffline/.test(ownerDoc.documentURI)) {
return;
}
sendSyncMessage("Browser:NetworkError", {});
},
/**