diff options
Diffstat (limited to 'mobile/android/modules/NetErrorHelper.jsm')
-rw-r--r-- | mobile/android/modules/NetErrorHelper.jsm | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/mobile/android/modules/NetErrorHelper.jsm b/mobile/android/modules/NetErrorHelper.jsm new file mode 100644 index 000000000..9c74df8fe --- /dev/null +++ b/mobile/android/modules/NetErrorHelper.jsm @@ -0,0 +1,175 @@ +/* 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/. */ +"use strict"; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Messaging.jsm"); +Cu.import("resource://gre/modules/UITelemetry.jsm"); + +this.EXPORTED_SYMBOLS = ["NetErrorHelper"]; + +const KEY_CODE_ENTER = 13; + +/* Handlers is a list of objects that will be notified when an error page is shown + * or when an event occurs on the page that they are registered to handle. Registration + * is done by just adding yourself to the dictionary. + * + * handlers.myKey = { + * onPageShown: function(browser) { }, + * handleEvent: function(event) { }, + * } + * + * The key that you register yourself with should match the ID of the element you want to + * watch for click events on. + */ + +var handlers = {}; + +function NetErrorHelper(browser) { + browser.addEventListener("click", this.handleClick, true); + + let listener = () => { + browser.removeEventListener("click", this.handleClick, true); + browser.removeEventListener("pagehide", listener, true); + }; + browser.addEventListener("pagehide", listener, true); + + // Handlers may want to customize the page + for (let id in handlers) { + if (handlers[id].onPageShown) { + handlers[id].onPageShown(browser); + } + } +} + +NetErrorHelper.attachToBrowser = function(browser) { + return new NetErrorHelper(browser); +} + +NetErrorHelper.prototype = { + handleClick: function(event) { + let node = event.target; + + while(node) { + if (node.id in handlers && handlers[node.id].handleClick) { + handlers[node.id].handleClick(event); + return; + } + + node = node.parentNode; + } + }, +} + +handlers.searchbutton = { + onPageShown: function(browser) { + let search = browser.contentDocument.querySelector("#searchbox"); + if (!search) { + return; + } + + let browserWin = Services.wm.getMostRecentWindow("navigator:browser"); + let tab = browserWin.BrowserApp.getTabForBrowser(browser); + + // If there is no stored userRequested, just hide the searchbox + if (!tab.userRequested) { + search.style.display = "none"; + } else { + let text = browser.contentDocument.querySelector("#searchtext"); + text.value = tab.userRequested; + text.addEventListener("keypress", (event) => { + if (event.keyCode === KEY_CODE_ENTER) { + this.doSearch(event.target.value); + } + }); + } + }, + + handleClick: function(event) { + let value = event.target.previousElementSibling.value; + this.doSearch(value); + }, + + doSearch: function(value) { + UITelemetry.addEvent("neterror.1", "button", null, "search"); + let engine = Services.search.defaultEngine; + let uri = engine.getSubmission(value).uri; + + let browserWin = Services.wm.getMostRecentWindow("navigator:browser"); + // Reset the user search to whatever the new search term was + browserWin.BrowserApp.loadURI(uri.spec, undefined, { isSearch: true, userRequested: value }); + } +}; + +handlers.wifi = { + // This registers itself with the nsIObserverService as a weak ref, + // so we have to implement GetWeakReference as well. + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsISupportsWeakReference]), + + GetWeakReference: function() { + return Cu.getWeakReference(this); + }, + + onPageShown: function(browser) { + // If we have a connection, don't bother showing the wifi toggle. + let network = Cc["@mozilla.org/network/network-link-service;1"].getService(Ci.nsINetworkLinkService); + if (network.isLinkUp && network.linkStatusKnown) { + let nodes = browser.contentDocument.querySelectorAll("#wifi"); + for (let i = 0; i < nodes.length; i++) { + nodes[i].style.display = "none"; + } + } + }, + + handleClick: function(event) { + let node = event.target; + while(node && node.id !== "wifi") { + node = node.parentNode; + } + + if (!node) { + return; + } + + UITelemetry.addEvent("neterror.1", "button", null, "wifitoggle"); + // Show indeterminate progress while we wait for the network. + node.disabled = true; + node.classList.add("inProgress"); + + this.node = Cu.getWeakReference(node); + Services.obs.addObserver(this, "network:link-status-changed", true); + + Messaging.sendRequest({ + type: "Wifi:Enable" + }); + }, + + observe: function(subject, topic, data) { + let node = this.node.get(); + if (!node) { + return; + } + + // Remove the progress bar + node.disabled = false; + node.classList.remove("inProgress"); + + let network = Cc["@mozilla.org/network/network-link-service;1"].getService(Ci.nsINetworkLinkService); + if (network.isLinkUp && network.linkStatusKnown) { + // If everything worked, reload the page + UITelemetry.addEvent("neterror.1", "button", null, "wifitoggle.reload"); + Services.obs.removeObserver(this, "network:link-status-changed"); + + // Even at this point, Android sometimes lies about the real state of the network and this reload request fails. + // Add a 500ms delay before refreshing the page. + node.ownerDocument.defaultView.setTimeout(function() { + node.ownerDocument.location.reload(false); + }, 500); + } + } +} + |