browser/base/content/newtab/page.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 #ifdef 0
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #endif
     7 /**
     8  * This singleton represents the whole 'New Tab Page' and takes care of
     9  * initializing all its components.
    10  */
    11 let gPage = {
    12   /**
    13    * Initializes the page.
    14    */
    15   init: function Page_init() {
    16     // Add ourselves to the list of pages to receive notifications.
    17     gAllPages.register(this);
    19     // Listen for 'unload' to unregister this page.
    20     addEventListener("unload", this, false);
    22     // XXX bug 991111 - Not all click events are correctly triggered when
    23     // listening from xhtml nodes -- in particular middle clicks on sites, so
    24     // listen from the xul window and filter then delegate
    25     addEventListener("click", this, false);
    27     // Initialize sponsored panel
    28     this._sponsoredPanel = document.getElementById("sponsored-panel");
    29     let link = this._sponsoredPanel.querySelector(".text-link");
    30     link.addEventListener("click", () => this._sponsoredPanel.hidePopup());
    31     if (UpdateChannel.get().startsWith("release")) {
    32       document.getElementById("sponsored-panel-trial-descr").style.display = "none";
    33     }
    34     else {
    35       document.getElementById("sponsored-panel-release-descr").style.display = "none";
    36     }
    38     // Check if the new tab feature is enabled.
    39     let enabled = gAllPages.enabled;
    40     if (enabled)
    41       this._init();
    43     this._updateAttributes(enabled);
    44   },
    46   /**
    47    * True if the page is allowed to capture thumbnails using the background
    48    * thumbnail service.
    49    */
    50   get allowBackgroundCaptures() {
    51     // The preloader is bypassed altogether for private browsing windows, and
    52     // therefore allow-background-captures will not be set.  In that case, the
    53     // page is not preloaded and so it's visible, so allow background captures.
    54     return inPrivateBrowsingMode() ||
    55            document.documentElement.getAttribute("allow-background-captures") ==
    56            "true";
    57   },
    59   /**
    60    * Listens for notifications specific to this page.
    61    */
    62   observe: function Page_observe(aSubject, aTopic, aData) {
    63     if (aTopic == "nsPref:changed") {
    64       let enabled = gAllPages.enabled;
    65       this._updateAttributes(enabled);
    67       // Initialize the whole page if we haven't done that, yet.
    68       if (enabled) {
    69         this._init();
    70       } else {
    71         gUndoDialog.hide();
    72       }
    73     } else if (aTopic == "page-thumbnail:create" && gGrid.ready) {
    74       for (let site of gGrid.sites) {
    75         if (site && site.url === aData) {
    76           site.refreshThumbnail();
    77         }
    78       }
    79     }
    80   },
    82   /**
    83    * Updates the whole page and the grid when the storage has changed.
    84    * @param aOnlyIfHidden If true, the page is updated only if it's hidden in
    85    *                      the preloader.
    86    */
    87   update: function Page_update(aOnlyIfHidden=false) {
    88     let skipUpdate = aOnlyIfHidden && this.allowBackgroundCaptures;
    89     // The grid might not be ready yet as we initialize it asynchronously.
    90     if (gGrid.ready && !skipUpdate) {
    91       gGrid.refresh();
    92     }
    93   },
    95   /**
    96    * Shows sponsored panel
    97    */
    98   showSponsoredPanel: function Page_showSponsoredPanel(aTarget) {
    99     if (this._sponsoredPanel.state == "closed") {
   100       let self = this;
   101       this._sponsoredPanel.addEventListener("popuphidden", function onPopupHidden(aEvent) {
   102         self._sponsoredPanel.removeEventListener("popuphidden", onPopupHidden, false);
   103         aTarget.removeAttribute("panelShown");
   104       });
   105     }
   106     aTarget.setAttribute("panelShown", "true");
   107     this._sponsoredPanel.openPopup(aTarget);
   108   },
   110   /**
   111    * Internally initializes the page. This runs only when/if the feature
   112    * is/gets enabled.
   113    */
   114   _init: function Page_init() {
   115     if (this._initialized)
   116       return;
   118     this._initialized = true;
   120     gSearch.init();
   122     this._mutationObserver = new MutationObserver(() => {
   123       if (this.allowBackgroundCaptures) {
   124         Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
   126         // Initialize type counting with the types we want to count
   127         let directoryCount = {};
   128         for (let type of DirectoryLinksProvider.linkTypes) {
   129           directoryCount[type] = 0;
   130         }
   132         for (let site of gGrid.sites) {
   133           if (site) {
   134             site.captureIfMissing();
   135             let {type} = site.link;
   136             if (type in directoryCount) {
   137               directoryCount[type]++;
   138             }
   139           }
   140         }
   142         // Record how many directory sites were shown, but place counts over the
   143         // default 9 in the same bucket
   144         for (let [type, count] of Iterator(directoryCount)) {
   145           let shownId = "NEWTAB_PAGE_DIRECTORY_" + type.toUpperCase() + "_SHOWN";
   146           let shownCount = Math.min(10, count);
   147           Services.telemetry.getHistogramById(shownId).add(shownCount);
   148         }
   150         // content.js isn't loaded for the page while it's in the preloader,
   151         // which is why this is necessary.
   152         gSearch.setUpInitialState();
   153       }
   154     });
   155     this._mutationObserver.observe(document.documentElement, {
   156       attributes: true,
   157       attributeFilter: ["allow-background-captures"],
   158     });
   160     gLinks.populateCache(function () {
   161       // Initialize and render the grid.
   162       gGrid.init();
   164       // Initialize the drop target shim.
   165       gDropTargetShim.init();
   167 #ifdef XP_MACOSX
   168       // Workaround to prevent a delay on MacOSX due to a slow drop animation.
   169       document.addEventListener("dragover", this, false);
   170       document.addEventListener("drop", this, false);
   171 #endif
   172     }.bind(this));
   173   },
   175   /**
   176    * Updates the 'page-disabled' attributes of the respective DOM nodes.
   177    * @param aValue Whether the New Tab Page is enabled or not.
   178    */
   179   _updateAttributes: function Page_updateAttributes(aValue) {
   180     // Set the nodes' states.
   181     let nodeSelector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid, #newtab-search-container";
   182     for (let node of document.querySelectorAll(nodeSelector)) {
   183       if (aValue)
   184         node.removeAttribute("page-disabled");
   185       else
   186         node.setAttribute("page-disabled", "true");
   187     }
   189     // Enables/disables the control and link elements.
   190     let inputSelector = ".newtab-control, .newtab-link";
   191     for (let input of document.querySelectorAll(inputSelector)) {
   192       if (aValue) 
   193         input.removeAttribute("tabindex");
   194       else
   195         input.setAttribute("tabindex", "-1");
   196     }
   198     // Update the toggle button's title.
   199     let toggle = document.getElementById("newtab-toggle");
   200     toggle.setAttribute("title", newTabString(aValue ? "hide" : "show"));
   201   },
   203   /**
   204    * Handles all page events.
   205    */
   206   handleEvent: function Page_handleEvent(aEvent) {
   207     switch (aEvent.type) {
   208       case "unload":
   209         if (this._mutationObserver)
   210           this._mutationObserver.disconnect();
   211         gAllPages.unregister(this);
   212         break;
   213       case "click":
   214         let {button, target} = aEvent;
   215         if (target.id == "newtab-toggle") {
   216           if (button == 0) {
   217             gAllPages.enabled = !gAllPages.enabled;
   218           }
   219           break;
   220         }
   222         // Go up ancestors until we find a Site or not
   223         while (target) {
   224           if (target.hasOwnProperty("_newtabSite")) {
   225             target._newtabSite.onClick(aEvent);
   226             break;
   227           }
   228           target = target.parentNode;
   229         }
   230         break;
   231       case "dragover":
   232         if (gDrag.isValid(aEvent) && gDrag.draggedSite)
   233           aEvent.preventDefault();
   234         break;
   235       case "drop":
   236         if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
   237           aEvent.preventDefault();
   238           aEvent.stopPropagation();
   239         }
   240         break;
   241     }
   242   }
   243 };

mercurial