browser/base/content/newtab/sites.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 #ifdef 0
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5 #endif
michael@0 6
michael@0 7 /**
michael@0 8 * This class represents a site that is contained in a cell and can be pinned,
michael@0 9 * moved around or deleted.
michael@0 10 */
michael@0 11 function Site(aNode, aLink) {
michael@0 12 this._node = aNode;
michael@0 13 this._node._newtabSite = this;
michael@0 14
michael@0 15 this._link = aLink;
michael@0 16
michael@0 17 this._render();
michael@0 18 this._addEventHandlers();
michael@0 19 }
michael@0 20
michael@0 21 Site.prototype = {
michael@0 22 /**
michael@0 23 * The site's DOM node.
michael@0 24 */
michael@0 25 get node() this._node,
michael@0 26
michael@0 27 /**
michael@0 28 * The site's link.
michael@0 29 */
michael@0 30 get link() this._link,
michael@0 31
michael@0 32 /**
michael@0 33 * The url of the site's link.
michael@0 34 */
michael@0 35 get url() this.link.url,
michael@0 36
michael@0 37 /**
michael@0 38 * The title of the site's link.
michael@0 39 */
michael@0 40 get title() this.link.title,
michael@0 41
michael@0 42 /**
michael@0 43 * The site's parent cell.
michael@0 44 */
michael@0 45 get cell() {
michael@0 46 let parentNode = this.node.parentNode;
michael@0 47 return parentNode && parentNode._newtabCell;
michael@0 48 },
michael@0 49
michael@0 50 /**
michael@0 51 * Pins the site on its current or a given index.
michael@0 52 * @param aIndex The pinned index (optional).
michael@0 53 */
michael@0 54 pin: function Site_pin(aIndex) {
michael@0 55 if (typeof aIndex == "undefined")
michael@0 56 aIndex = this.cell.index;
michael@0 57
michael@0 58 this._updateAttributes(true);
michael@0 59 gPinnedLinks.pin(this._link, aIndex);
michael@0 60 },
michael@0 61
michael@0 62 /**
michael@0 63 * Unpins the site and calls the given callback when done.
michael@0 64 */
michael@0 65 unpin: function Site_unpin() {
michael@0 66 if (this.isPinned()) {
michael@0 67 this._updateAttributes(false);
michael@0 68 gPinnedLinks.unpin(this._link);
michael@0 69 gUpdater.updateGrid();
michael@0 70 }
michael@0 71 },
michael@0 72
michael@0 73 /**
michael@0 74 * Checks whether this site is pinned.
michael@0 75 * @return Whether this site is pinned.
michael@0 76 */
michael@0 77 isPinned: function Site_isPinned() {
michael@0 78 return gPinnedLinks.isPinned(this._link);
michael@0 79 },
michael@0 80
michael@0 81 /**
michael@0 82 * Blocks the site (removes it from the grid) and calls the given callback
michael@0 83 * when done.
michael@0 84 */
michael@0 85 block: function Site_block() {
michael@0 86 if (!gBlockedLinks.isBlocked(this._link)) {
michael@0 87 gUndoDialog.show(this);
michael@0 88 gBlockedLinks.block(this._link);
michael@0 89 gUpdater.updateGrid();
michael@0 90 }
michael@0 91 },
michael@0 92
michael@0 93 /**
michael@0 94 * Gets the DOM node specified by the given query selector.
michael@0 95 * @param aSelector The query selector.
michael@0 96 * @return The DOM node we found.
michael@0 97 */
michael@0 98 _querySelector: function Site_querySelector(aSelector) {
michael@0 99 return this.node.querySelector(aSelector);
michael@0 100 },
michael@0 101
michael@0 102 /**
michael@0 103 * Updates attributes for all nodes which status depends on this site being
michael@0 104 * pinned or unpinned.
michael@0 105 * @param aPinned Whether this site is now pinned or unpinned.
michael@0 106 */
michael@0 107 _updateAttributes: function (aPinned) {
michael@0 108 let control = this._querySelector(".newtab-control-pin");
michael@0 109
michael@0 110 if (aPinned) {
michael@0 111 control.setAttribute("pinned", true);
michael@0 112 control.setAttribute("title", newTabString("unpin"));
michael@0 113 } else {
michael@0 114 control.removeAttribute("pinned");
michael@0 115 control.setAttribute("title", newTabString("pin"));
michael@0 116 }
michael@0 117 },
michael@0 118
michael@0 119 /**
michael@0 120 * Renders the site's data (fills the HTML fragment).
michael@0 121 */
michael@0 122 _render: function Site_render() {
michael@0 123 let url = this.url;
michael@0 124 let title = this.title || url;
michael@0 125 let tooltip = (title == url ? title : title + "\n" + url);
michael@0 126
michael@0 127 let link = this._querySelector(".newtab-link");
michael@0 128 link.setAttribute("title", tooltip);
michael@0 129 link.setAttribute("href", url);
michael@0 130 this._querySelector(".newtab-title").textContent = title;
michael@0 131 this.node.setAttribute("type", this.link.type);
michael@0 132
michael@0 133 if (this.isPinned())
michael@0 134 this._updateAttributes(true);
michael@0 135 // Capture the page if the thumbnail is missing, which will cause page.js
michael@0 136 // to be notified and call our refreshThumbnail() method.
michael@0 137 this.captureIfMissing();
michael@0 138 // but still display whatever thumbnail might be available now.
michael@0 139 this.refreshThumbnail();
michael@0 140 },
michael@0 141
michael@0 142 /**
michael@0 143 * Captures the site's thumbnail in the background, but only if there's no
michael@0 144 * existing thumbnail and the page allows background captures.
michael@0 145 */
michael@0 146 captureIfMissing: function Site_captureIfMissing() {
michael@0 147 if (gPage.allowBackgroundCaptures && !this.link.imageURI) {
michael@0 148 BackgroundPageThumbs.captureIfMissing(this.url);
michael@0 149 }
michael@0 150 },
michael@0 151
michael@0 152 /**
michael@0 153 * Refreshes the thumbnail for the site.
michael@0 154 */
michael@0 155 refreshThumbnail: function Site_refreshThumbnail() {
michael@0 156 let thumbnail = this._querySelector(".newtab-thumbnail");
michael@0 157 if (this.link.bgColor) {
michael@0 158 thumbnail.style.backgroundColor = this.link.bgColor;
michael@0 159 }
michael@0 160 let uri = this.link.imageURI || PageThumbs.getThumbnailURL(this.url);
michael@0 161 thumbnail.style.backgroundImage = "url(" + uri + ")";
michael@0 162 },
michael@0 163
michael@0 164 /**
michael@0 165 * Adds event handlers for the site and its buttons.
michael@0 166 */
michael@0 167 _addEventHandlers: function Site_addEventHandlers() {
michael@0 168 // Register drag-and-drop event handlers.
michael@0 169 this._node.addEventListener("dragstart", this, false);
michael@0 170 this._node.addEventListener("dragend", this, false);
michael@0 171 this._node.addEventListener("mouseover", this, false);
michael@0 172
michael@0 173 // Specially treat the sponsored icon to prevent regular hover effects
michael@0 174 let sponsored = this._querySelector(".newtab-control-sponsored");
michael@0 175 sponsored.addEventListener("mouseover", () => {
michael@0 176 this.cell.node.setAttribute("ignorehover", "true");
michael@0 177 });
michael@0 178 sponsored.addEventListener("mouseout", () => {
michael@0 179 this.cell.node.removeAttribute("ignorehover");
michael@0 180 });
michael@0 181 },
michael@0 182
michael@0 183 /**
michael@0 184 * Speculatively opens a connection to the current site.
michael@0 185 */
michael@0 186 _speculativeConnect: function Site_speculativeConnect() {
michael@0 187 let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
michael@0 188 let uri = Services.io.newURI(this.url, null, null);
michael@0 189 sc.speculativeConnect(uri, null);
michael@0 190 },
michael@0 191
michael@0 192 /**
michael@0 193 * Record interaction with site using telemetry.
michael@0 194 */
michael@0 195 _recordSiteClicked: function Site_recordSiteClicked(aIndex) {
michael@0 196 if (Services.prefs.prefHasUserValue("browser.newtabpage.rows") ||
michael@0 197 Services.prefs.prefHasUserValue("browser.newtabpage.columns") ||
michael@0 198 aIndex > 8) {
michael@0 199 // We only want to get indices for the default configuration, everything
michael@0 200 // else goes in the same bucket.
michael@0 201 aIndex = 9;
michael@0 202 }
michael@0 203 Services.telemetry.getHistogramById("NEWTAB_PAGE_SITE_CLICKED")
michael@0 204 .add(aIndex);
michael@0 205
michael@0 206 // Specially count clicks on directory tiles
michael@0 207 let typeIndex = DirectoryLinksProvider.linkTypes.indexOf(this.link.type);
michael@0 208 if (typeIndex != -1) {
michael@0 209 Services.telemetry.getHistogramById("NEWTAB_PAGE_DIRECTORY_TYPE_CLICKED")
michael@0 210 .add(typeIndex);
michael@0 211 }
michael@0 212 },
michael@0 213
michael@0 214 /**
michael@0 215 * Handles site click events.
michael@0 216 */
michael@0 217 onClick: function Site_onClick(aEvent) {
michael@0 218 let {button, target} = aEvent;
michael@0 219 if (target.classList.contains("newtab-link") ||
michael@0 220 target.parentElement.classList.contains("newtab-link")) {
michael@0 221 // Record for primary and middle clicks
michael@0 222 if (button == 0 || button == 1) {
michael@0 223 this._recordSiteClicked(this.cell.index);
michael@0 224 }
michael@0 225 return;
michael@0 226 }
michael@0 227
michael@0 228 // Only handle primary clicks for the remaining targets
michael@0 229 if (button != 0) {
michael@0 230 return;
michael@0 231 }
michael@0 232
michael@0 233 aEvent.preventDefault();
michael@0 234 if (aEvent.target.classList.contains("newtab-control-block"))
michael@0 235 this.block();
michael@0 236 else if (target.classList.contains("newtab-control-sponsored"))
michael@0 237 gPage.showSponsoredPanel(target);
michael@0 238 else if (this.isPinned())
michael@0 239 this.unpin();
michael@0 240 else
michael@0 241 this.pin();
michael@0 242 },
michael@0 243
michael@0 244 /**
michael@0 245 * Handles all site events.
michael@0 246 */
michael@0 247 handleEvent: function Site_handleEvent(aEvent) {
michael@0 248 switch (aEvent.type) {
michael@0 249 case "mouseover":
michael@0 250 this._node.removeEventListener("mouseover", this, false);
michael@0 251 this._speculativeConnect();
michael@0 252 break;
michael@0 253 case "dragstart":
michael@0 254 gDrag.start(this, aEvent);
michael@0 255 break;
michael@0 256 case "dragend":
michael@0 257 gDrag.end(this, aEvent);
michael@0 258 break;
michael@0 259 }
michael@0 260 }
michael@0 261 };

mercurial