browser/base/content/newtab/page.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/base/content/newtab/page.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,243 @@
     1.4 +#ifdef 0
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +#endif
     1.9 +
    1.10 +/**
    1.11 + * This singleton represents the whole 'New Tab Page' and takes care of
    1.12 + * initializing all its components.
    1.13 + */
    1.14 +let gPage = {
    1.15 +  /**
    1.16 +   * Initializes the page.
    1.17 +   */
    1.18 +  init: function Page_init() {
    1.19 +    // Add ourselves to the list of pages to receive notifications.
    1.20 +    gAllPages.register(this);
    1.21 +
    1.22 +    // Listen for 'unload' to unregister this page.
    1.23 +    addEventListener("unload", this, false);
    1.24 +
    1.25 +    // XXX bug 991111 - Not all click events are correctly triggered when
    1.26 +    // listening from xhtml nodes -- in particular middle clicks on sites, so
    1.27 +    // listen from the xul window and filter then delegate
    1.28 +    addEventListener("click", this, false);
    1.29 +
    1.30 +    // Initialize sponsored panel
    1.31 +    this._sponsoredPanel = document.getElementById("sponsored-panel");
    1.32 +    let link = this._sponsoredPanel.querySelector(".text-link");
    1.33 +    link.addEventListener("click", () => this._sponsoredPanel.hidePopup());
    1.34 +    if (UpdateChannel.get().startsWith("release")) {
    1.35 +      document.getElementById("sponsored-panel-trial-descr").style.display = "none";
    1.36 +    }
    1.37 +    else {
    1.38 +      document.getElementById("sponsored-panel-release-descr").style.display = "none";
    1.39 +    }
    1.40 +
    1.41 +    // Check if the new tab feature is enabled.
    1.42 +    let enabled = gAllPages.enabled;
    1.43 +    if (enabled)
    1.44 +      this._init();
    1.45 +
    1.46 +    this._updateAttributes(enabled);
    1.47 +  },
    1.48 +
    1.49 +  /**
    1.50 +   * True if the page is allowed to capture thumbnails using the background
    1.51 +   * thumbnail service.
    1.52 +   */
    1.53 +  get allowBackgroundCaptures() {
    1.54 +    // The preloader is bypassed altogether for private browsing windows, and
    1.55 +    // therefore allow-background-captures will not be set.  In that case, the
    1.56 +    // page is not preloaded and so it's visible, so allow background captures.
    1.57 +    return inPrivateBrowsingMode() ||
    1.58 +           document.documentElement.getAttribute("allow-background-captures") ==
    1.59 +           "true";
    1.60 +  },
    1.61 +
    1.62 +  /**
    1.63 +   * Listens for notifications specific to this page.
    1.64 +   */
    1.65 +  observe: function Page_observe(aSubject, aTopic, aData) {
    1.66 +    if (aTopic == "nsPref:changed") {
    1.67 +      let enabled = gAllPages.enabled;
    1.68 +      this._updateAttributes(enabled);
    1.69 +
    1.70 +      // Initialize the whole page if we haven't done that, yet.
    1.71 +      if (enabled) {
    1.72 +        this._init();
    1.73 +      } else {
    1.74 +        gUndoDialog.hide();
    1.75 +      }
    1.76 +    } else if (aTopic == "page-thumbnail:create" && gGrid.ready) {
    1.77 +      for (let site of gGrid.sites) {
    1.78 +        if (site && site.url === aData) {
    1.79 +          site.refreshThumbnail();
    1.80 +        }
    1.81 +      }
    1.82 +    }
    1.83 +  },
    1.84 +
    1.85 +  /**
    1.86 +   * Updates the whole page and the grid when the storage has changed.
    1.87 +   * @param aOnlyIfHidden If true, the page is updated only if it's hidden in
    1.88 +   *                      the preloader.
    1.89 +   */
    1.90 +  update: function Page_update(aOnlyIfHidden=false) {
    1.91 +    let skipUpdate = aOnlyIfHidden && this.allowBackgroundCaptures;
    1.92 +    // The grid might not be ready yet as we initialize it asynchronously.
    1.93 +    if (gGrid.ready && !skipUpdate) {
    1.94 +      gGrid.refresh();
    1.95 +    }
    1.96 +  },
    1.97 +
    1.98 +  /**
    1.99 +   * Shows sponsored panel
   1.100 +   */
   1.101 +  showSponsoredPanel: function Page_showSponsoredPanel(aTarget) {
   1.102 +    if (this._sponsoredPanel.state == "closed") {
   1.103 +      let self = this;
   1.104 +      this._sponsoredPanel.addEventListener("popuphidden", function onPopupHidden(aEvent) {
   1.105 +        self._sponsoredPanel.removeEventListener("popuphidden", onPopupHidden, false);
   1.106 +        aTarget.removeAttribute("panelShown");
   1.107 +      });
   1.108 +    }
   1.109 +    aTarget.setAttribute("panelShown", "true");
   1.110 +    this._sponsoredPanel.openPopup(aTarget);
   1.111 +  },
   1.112 +
   1.113 +  /**
   1.114 +   * Internally initializes the page. This runs only when/if the feature
   1.115 +   * is/gets enabled.
   1.116 +   */
   1.117 +  _init: function Page_init() {
   1.118 +    if (this._initialized)
   1.119 +      return;
   1.120 +
   1.121 +    this._initialized = true;
   1.122 +
   1.123 +    gSearch.init();
   1.124 +
   1.125 +    this._mutationObserver = new MutationObserver(() => {
   1.126 +      if (this.allowBackgroundCaptures) {
   1.127 +        Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
   1.128 +
   1.129 +        // Initialize type counting with the types we want to count
   1.130 +        let directoryCount = {};
   1.131 +        for (let type of DirectoryLinksProvider.linkTypes) {
   1.132 +          directoryCount[type] = 0;
   1.133 +        }
   1.134 +
   1.135 +        for (let site of gGrid.sites) {
   1.136 +          if (site) {
   1.137 +            site.captureIfMissing();
   1.138 +            let {type} = site.link;
   1.139 +            if (type in directoryCount) {
   1.140 +              directoryCount[type]++;
   1.141 +            }
   1.142 +          }
   1.143 +        }
   1.144 +
   1.145 +        // Record how many directory sites were shown, but place counts over the
   1.146 +        // default 9 in the same bucket
   1.147 +        for (let [type, count] of Iterator(directoryCount)) {
   1.148 +          let shownId = "NEWTAB_PAGE_DIRECTORY_" + type.toUpperCase() + "_SHOWN";
   1.149 +          let shownCount = Math.min(10, count);
   1.150 +          Services.telemetry.getHistogramById(shownId).add(shownCount);
   1.151 +        }
   1.152 +
   1.153 +        // content.js isn't loaded for the page while it's in the preloader,
   1.154 +        // which is why this is necessary.
   1.155 +        gSearch.setUpInitialState();
   1.156 +      }
   1.157 +    });
   1.158 +    this._mutationObserver.observe(document.documentElement, {
   1.159 +      attributes: true,
   1.160 +      attributeFilter: ["allow-background-captures"],
   1.161 +    });
   1.162 +
   1.163 +    gLinks.populateCache(function () {
   1.164 +      // Initialize and render the grid.
   1.165 +      gGrid.init();
   1.166 +
   1.167 +      // Initialize the drop target shim.
   1.168 +      gDropTargetShim.init();
   1.169 +
   1.170 +#ifdef XP_MACOSX
   1.171 +      // Workaround to prevent a delay on MacOSX due to a slow drop animation.
   1.172 +      document.addEventListener("dragover", this, false);
   1.173 +      document.addEventListener("drop", this, false);
   1.174 +#endif
   1.175 +    }.bind(this));
   1.176 +  },
   1.177 +
   1.178 +  /**
   1.179 +   * Updates the 'page-disabled' attributes of the respective DOM nodes.
   1.180 +   * @param aValue Whether the New Tab Page is enabled or not.
   1.181 +   */
   1.182 +  _updateAttributes: function Page_updateAttributes(aValue) {
   1.183 +    // Set the nodes' states.
   1.184 +    let nodeSelector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid, #newtab-search-container";
   1.185 +    for (let node of document.querySelectorAll(nodeSelector)) {
   1.186 +      if (aValue)
   1.187 +        node.removeAttribute("page-disabled");
   1.188 +      else
   1.189 +        node.setAttribute("page-disabled", "true");
   1.190 +    }
   1.191 +
   1.192 +    // Enables/disables the control and link elements.
   1.193 +    let inputSelector = ".newtab-control, .newtab-link";
   1.194 +    for (let input of document.querySelectorAll(inputSelector)) {
   1.195 +      if (aValue) 
   1.196 +        input.removeAttribute("tabindex");
   1.197 +      else
   1.198 +        input.setAttribute("tabindex", "-1");
   1.199 +    }
   1.200 +
   1.201 +    // Update the toggle button's title.
   1.202 +    let toggle = document.getElementById("newtab-toggle");
   1.203 +    toggle.setAttribute("title", newTabString(aValue ? "hide" : "show"));
   1.204 +  },
   1.205 +
   1.206 +  /**
   1.207 +   * Handles all page events.
   1.208 +   */
   1.209 +  handleEvent: function Page_handleEvent(aEvent) {
   1.210 +    switch (aEvent.type) {
   1.211 +      case "unload":
   1.212 +        if (this._mutationObserver)
   1.213 +          this._mutationObserver.disconnect();
   1.214 +        gAllPages.unregister(this);
   1.215 +        break;
   1.216 +      case "click":
   1.217 +        let {button, target} = aEvent;
   1.218 +        if (target.id == "newtab-toggle") {
   1.219 +          if (button == 0) {
   1.220 +            gAllPages.enabled = !gAllPages.enabled;
   1.221 +          }
   1.222 +          break;
   1.223 +        }
   1.224 +
   1.225 +        // Go up ancestors until we find a Site or not
   1.226 +        while (target) {
   1.227 +          if (target.hasOwnProperty("_newtabSite")) {
   1.228 +            target._newtabSite.onClick(aEvent);
   1.229 +            break;
   1.230 +          }
   1.231 +          target = target.parentNode;
   1.232 +        }
   1.233 +        break;
   1.234 +      case "dragover":
   1.235 +        if (gDrag.isValid(aEvent) && gDrag.draggedSite)
   1.236 +          aEvent.preventDefault();
   1.237 +        break;
   1.238 +      case "drop":
   1.239 +        if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
   1.240 +          aEvent.preventDefault();
   1.241 +          aEvent.stopPropagation();
   1.242 +        }
   1.243 +        break;
   1.244 +    }
   1.245 +  }
   1.246 +};

mercurial