| Index: lib/child/typoNetError.js | 
| =================================================================== | 
| new file mode 100644 | 
| --- /dev/null | 
| +++ b/lib/child/typoNetError.js | 
| @@ -0,0 +1,139 @@ | 
| +/* | 
| + * This file is part of the URL Fixer, | 
| + * Copyright (C) 2006-2016 Eyeo GmbH | 
| + * | 
| + * URL Fixer is free software: you can redistribute it and/or modify | 
| + * it under the terms of the GNU General Public License version 3 as | 
| + * published by the Free Software Foundation. | 
| + * | 
| + * URL Fixer is distributed in the hope that it will be useful, | 
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| + * GNU General Public License for more details. | 
| + * | 
| + * You should have received a copy of the GNU General Public License | 
| + * along with URL Fixer.  If not, see <http://www.gnu.org/licenses/>. | 
| + */ | 
| + | 
| +"use strict"; | 
| + | 
| +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; | 
| + | 
| +let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | 
| + | 
| +let onShutdown = | 
| +{ | 
| +  shutdownHandlers: [], | 
| +  done: false, | 
| +  add: function(handler) | 
| +  { | 
| +    if (this.shutdownHandlers.indexOf(handler) < 0) | 
| +      this.shutdownHandlers.push(handler); | 
| +  }, | 
| +  remove: function(handler) | 
| +  { | 
| +    let index = this.shutdownHandlers.indexOf(handler); | 
| +    if (index >= 0) | 
| +      this.shutdownHandlers.splice(index, 1); | 
| +  } | 
| +}; | 
| + | 
| +let netErrorOverlay = null; | 
| + | 
| +function receivedNetErrorOverlay(message) | 
| +{ | 
| +  let parser = Cc["@mozilla.org/xmlextras/domparser;1"] | 
| +                 .createInstance(Ci.nsIDOMParser); | 
| +  netErrorOverlay = parser.parseFromString(message.data, "application/xml"); | 
| +} | 
| + | 
| +function shutdown(message) | 
| +{ | 
| +  if (message.data == Components.stack.filename && !onShutdown.done) | 
| +  { | 
| +    onShutdown.done = true; | 
| +    for (let i = onShutdown.shutdownHandlers.length - 1; i >= 0; i --) | 
| +    { | 
| +      try | 
| +      { | 
| +        onShutdown.shutdownHandlers[i](); | 
| +      } | 
| +      catch (e) | 
| +      { | 
| +        Cu.reportError(e); | 
| +      } | 
| +    } | 
| +    onShutdown.shutdownHandlers = null; | 
| +  } | 
| +} | 
| + | 
| +function onDocumentCreated(subject, topic, data) | 
| +{ | 
| +  if (topic != "content-document-global-created") | 
| +    return; | 
| +  if (!(subject instanceof Ci.nsIDOMWindow)) | 
| +    return; | 
| + | 
| +  subject.addEventListener("DOMContentLoaded", handlePageLoad); | 
| +} | 
| + | 
| +function handlePageLoad(event) | 
| +{ | 
| +  let document = event.target; | 
| +  if (document.documentURI.indexOf("about:neterror?") != 0 || | 
| +      document.documentURI.indexOf("e=netOffline") > 0 || | 
| +      document.documentURI.indexOf("e=notCached") > 0) | 
| +  { | 
| +    return; | 
| +  } | 
| + | 
| +  if (!netErrorOverlay || document.getElementById("url-fixer-section")) | 
| +    return; | 
| + | 
| +  let container = document.getElementById("errorPageContainer"); | 
| +  if (!container) | 
| +    return; | 
| + | 
| +  container.appendChild(netErrorOverlay.documentElement.cloneNode(true)); | 
| + | 
| +  let textField = document.getElementById("url-fixer-intention"); | 
| +  textField.value = document.defaultView.location.href; | 
| + | 
| +  let retryButton = document.getElementById("url-fixer-retry"); | 
| +  retryButton.addEventListener("click", function() | 
| +  { | 
| +    let newURL = textField.value.replace(/^\s+/, "").replace(/\s+$/, ""); | 
| +    if (!newURL.length) | 
| +      return; | 
| + | 
| +    let [prefix, newHost, suffix] = parseURL(newURL); | 
| +    let oldHost = document.defaultView.location.hostname.toLowerCase(); | 
| + | 
| +    sendAsyncMessage("URLFixer:UserCorrection", {oldHost, newHost}); | 
| + | 
| +    document.defaultView.location.replace(newURL); | 
| +  }, false); | 
| +} | 
| + | 
| +function parseURL(url) | 
| +{ | 
| +  if (/^\s*((?:\w+:)?\/*(?:[^\/#]*@)?)([^\/:#]*)/.test(url)) | 
| +    return [RegExp.$1, RegExp.$2.toLowerCase(), RegExp.rightContext]; | 
| +  else | 
| +    return [url, null, null]; | 
| +} | 
| + | 
| +addMessageListener("URLFixer:NetErrorOverlay", receivedNetErrorOverlay); | 
| +addMessageListener("URLFixer:Shutdown", shutdown); | 
| +onShutdown.add(() => | 
| +{ | 
| +  removeMessageListener("URLFixer:NetErrorOverlay", receivedNetErrorOverlay); | 
| +  removeMessageListener("URLFixer:Shutdown", shutdown); | 
| +}); | 
| +sendAsyncMessage("URLFixer:GetNetErrorOverlay"); | 
| + | 
| +Services.obs.addObserver(onDocumentCreated, "content-document-global-created", false); | 
| +onShutdown.add(() => | 
| +{ | 
| +  Services.obs.removeObserver(onDocumentCreated, "content-document-global-created"); | 
| +}); | 
|  |