| Index: lib/typoFixer.js | 
| =================================================================== | 
| --- a/lib/typoFixer.js | 
| +++ b/lib/typoFixer.js | 
| @@ -20,123 +20,49 @@ | 
|  | 
| let {Prefs} = require("prefs"); | 
| let {WindowObserver} = require("windowObserver"); | 
| -let {getSchemeCorrection, isKnownScheme, getDomainCorrection, getDomainReferral, onWhitelistEntryRemoved} = require("typoRules"); | 
| -let {processTypedDomain, processDomainCorrection, | 
| -     processUserCorrection, processFalsePositive} = require("typedItCollector"); | 
| +let {getSchemeCorrection, isKnownScheme, getDomainCorrection, getDomainReferral, onWhitelistEntryAdded} = require("typoRules"); | 
| +let {processTypedDomain, processDomainCorrection, processFalsePositive} = require("typoCollector"); | 
| let appIntegration = require("typoAppIntegration"); | 
| +let netError = require("typoNetError"); | 
|  | 
| -// Attach our handlers to all browser windows | 
| -new WindowObserver( | 
| +let typoWindowObserver = null; | 
| + | 
| +exports.attachWindowObserver = attachWindowObserver; | 
| +function attachWindowObserver() | 
| { | 
| -  applyToWindow: function(window) | 
| -  { | 
| -    if (!appIntegration.isKnownWindow(window)) | 
| -      return; | 
| +  if (typoWindowObserver) | 
| +    return; | 
| + | 
| +  // Attach our handlers to all browser windows | 
| +  typoWindowObserver = new WindowObserver({ | 
| +    applyToWindow: function(window) | 
| +    { | 
| +      if (!appIntegration.isKnownWindow(window)) | 
| +        return; | 
| + | 
| +      appIntegration.applyToWindow(window, correctURL); | 
| +    }, | 
|  | 
| -    let browser = appIntegration.getBrowser(window); | 
| -    if (browser) | 
| -      browser.addEventListener("DOMContentLoaded", handlePageLoad, false); | 
| +    removeFromWindow: function(window) | 
| +    { | 
| +      if (!appIntegration.isKnownWindow(window)) | 
| +        return; | 
| + | 
| +      appIntegration.removeFromWindow(window); | 
| +    } | 
| +  }); | 
| +} | 
| +attachWindowObserver(); | 
|  | 
| -    appIntegration.applyToWindow(window, correctURL); | 
| -  }, | 
| - | 
| -  removeFromWindow: function(window) | 
| -  { | 
| -    if (!appIntegration.isKnownWindow(window)) | 
| -      return; | 
| - | 
| -    let browser = appIntegration.getBrowser(window); | 
| -    if (browser) | 
| -    { | 
| -      browser.removeEventListener("DOMContentLoaded", handlePageLoad, false); | 
| -      if (browser.browsers) | 
| -      { | 
| -        for (let i = 0; i < browser.browsers.length; i++) | 
| -        { | 
| -          let contentWnd = browser.browsers[i].contentWindow; | 
| -          if (contentWnd.document.documentURI.indexOf("about:neterror?") == 0) | 
| -            removeFromNetErrorPage(contentWnd); | 
| -        } | 
| -      } | 
| -    } | 
| - | 
| -    appIntegration.removeFromWindow(window); | 
| -  } | 
| -}); | 
| - | 
| -// Load HTML code to add to network error pages | 
| -let netErrorOverlay = null; | 
| -let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest); | 
| -request.open("GET", "chrome://url-fixer/content/netError.xhtml"); | 
| -request.addEventListener("load", function(event) | 
| +exports.detachWindowObserver = detachWindowObserver; | 
| +function detachWindowObserver() | 
| { | 
| -  netErrorOverlay = event.target.responseXML; | 
| -}, false); | 
| -request.send(null) | 
| - | 
| -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) | 
| -  { | 
| +  if (!typoWindowObserver) | 
| 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(); | 
| - | 
| -    processUserCorrection(oldHost, newHost); | 
| - | 
| -    if (newHost.indexOf("www.") == 0 && oldHost.indexOf("www.") == 0) | 
| -    { | 
| -      // Ignore www. prefix if they both start with it | 
| -      newHost = newHost.substr(4); | 
| -      oldHost = oldHost.substr(4); | 
| -    } | 
| -    if (oldHost && newHost != oldHost) | 
| -    { | 
| -      Prefs.custom_replace[oldHost] = newHost; | 
| -      Prefs.custom_replace = JSON.parse(JSON.stringify(Prefs.custom_replace)); | 
| -    } | 
| - | 
| -    // Remove from whitelist | 
| -    if (oldHost in Prefs.whitelist) | 
| -    { | 
| -      delete Prefs.whitelist[oldHost]; | 
| -      onWhitelistEntryRemoved(oldHost); | 
| -      Prefs.whitelist = JSON.parse(JSON.stringify(Prefs.whitelist)); | 
| -    } | 
| - | 
| -    document.defaultView.location.replace(newURL); | 
| -  }, false); | 
| -} | 
| - | 
| -function removeFromNetErrorPage(window) | 
| -{ | 
| -  let overlay = window.document.getElementById("url-fixer-section"); | 
| -  if (overlay) | 
| -    overlay.parentNode.removeChild(overlay); | 
| + | 
| +  // Detach our handlers from all browser windows | 
| +  typoWindowObserver.shutdown(); | 
| +  typoWindowObserver = null; | 
| } | 
|  | 
| function parseURL(url) | 
| @@ -245,6 +171,9 @@ | 
|  | 
| if (!hasCorrection) | 
| return null; | 
| + | 
| +  if (!appIntegration.isTypoCorrectionEnabled(window, prefix, domain, suffix)) | 
| +    return null; | 
|  | 
| // Show infobar to inform and ask about correction | 
| let [message, yes, no] = getInfobarTexts(); | 
| @@ -264,7 +193,6 @@ | 
| callback:   function() | 
| { | 
| // No: Add to list of corrections (ignore) | 
| -        let {onWhitelistEntryAdded} = require("typoRules"); | 
| let entry = oldDomain.replace(/^www\./, ""); | 
| Prefs.whitelist[entry] = true; | 
| onWhitelistEntryAdded(entry); | 
| @@ -276,9 +204,9 @@ | 
| } | 
| ]; | 
| // We need to have persistence being set to 1 due to redirect which happens afterwards | 
| -  appIntegration.openInfobar(window, "url-fixer-infobar-askafter", message, buttons, 1); | 
| +  appIntegration.openInfobar(window, require("info").addonName + "-infobar-askafter", message, buttons, 1); | 
|  | 
| -  require("survey").incrementCorrectionsCounter(); | 
| +  require("typoSurvey").incrementCorrectionsCounter(); | 
|  | 
| return prefix + domain + suffix; | 
| } | 
| @@ -289,7 +217,7 @@ | 
| { | 
| // Randomize URI to work around bug 719376 | 
| if (!stringBundle) | 
| -    stringBundle = Services.strings.createBundle("chrome://url-fixer/locale/typo.properties?" + Math.random()); | 
| +    stringBundle = Services.strings.createBundle("chrome://" + require("info").addonName + "/locale/typo.properties?" + Math.random()); | 
| let result = [ | 
| stringBundle.GetStringFromName("urlfixer.isItCorrect"), | 
| stringBundle.GetStringFromName("urlfixer.yes"), | 
|  |