| OLD | NEW |
| 1 /* Copyright 2015 The Chromium Authors. All rights reserved. | 1 /* Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. */ | 3 * found in the LICENSE file. */ |
| 4 | 4 |
| 5 // Single iframe for NTP tiles. | 5 // Single iframe for NTP tiles. |
| 6 (function() { | 6 (function() { |
| 7 'use strict'; | 7 'use strict'; |
| 8 | 8 |
| 9 | 9 |
| 10 /** | 10 /** |
| 11 * The different types of events that are logged from the NTP. This enum is | 11 * The different types of events that are logged from the NTP. This enum is |
| 12 * used to transfer information from the NTP JavaScript to the renderer and is | 12 * used to transfer information from the NTP JavaScript to the renderer and is |
| 13 * not used as a UMA enum histogram's logged value. | 13 * not used as a UMA enum histogram's logged value. |
| 14 * Note: Keep in sync with common/ntp_logging_events.h | 14 * Note: Keep in sync with common/ntp_logging_events.h |
| 15 * @enum {number} | 15 * @enum {number} |
| 16 * @const | 16 * @const |
| 17 */ | 17 */ |
| 18 var LOG_TYPE = { | 18 var LOG_TYPE = { |
| 19 // All NTP Tiles have finished loading (successfully or failing). | 19 // All NTP tiles have finished loading (successfully or failing). |
| 20 NTP_ALL_TILES_LOADED: 11, | 20 NTP_ALL_TILES_LOADED: 11, |
| 21 // The data for all NTP tiles (title, URL, etc, but not the thumbnail image) |
| 22 // has been received. In contrast to NTP_ALL_TILES_LOADED, this is recorded |
| 23 // before the actual DOM elements have loaded (in particular the thumbnail |
| 24 // images). |
| 25 NTP_ALL_TILES_RECEIVED: 12, |
| 21 }; | 26 }; |
| 22 | 27 |
| 23 | 28 |
| 24 /** | 29 /** |
| 25 * The different sources that an NTP tile can have. | 30 * The different sources that an NTP tile can have. |
| 26 * Note: Keep in sync with components/ntp_tiles/ntp_tile_source.h | 31 * Note: Keep in sync with components/ntp_tiles/ntp_tile_source.h |
| 27 * @enum {number} | 32 * @enum {number} |
| 28 * @const | 33 * @const |
| 29 */ | 34 */ |
| 30 var NTPTileSource = { | 35 var NTPTileSource = { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 } | 114 } |
| 110 | 115 |
| 111 /** | 116 /** |
| 112 * Down counts the DOM elements that we are waiting for the page to load. | 117 * Down counts the DOM elements that we are waiting for the page to load. |
| 113 * When we get to 0, we send a message to the parent window. | 118 * When we get to 0, we send a message to the parent window. |
| 114 * This is usually used as an EventListener of onload/onerror. | 119 * This is usually used as an EventListener of onload/onerror. |
| 115 */ | 120 */ |
| 116 var countLoad = function() { | 121 var countLoad = function() { |
| 117 loadedCounter -= 1; | 122 loadedCounter -= 1; |
| 118 if (loadedCounter <= 0) { | 123 if (loadedCounter <= 0) { |
| 119 showTiles(); | 124 swapInNewTiles(); |
| 120 logEvent(LOG_TYPE.NTP_ALL_TILES_LOADED); | 125 logEvent(LOG_TYPE.NTP_ALL_TILES_LOADED); |
| 121 window.parent.postMessage({cmd: 'loaded'}, DOMAIN_ORIGIN); | 126 window.parent.postMessage({cmd: 'loaded'}, DOMAIN_ORIGIN); |
| 122 // TODO(treib): Why do we reset to 1 here? | 127 // TODO(treib): Why do we reset to 1 here? |
| 123 loadedCounter = 1; | 128 loadedCounter = 1; |
| 124 } | 129 } |
| 125 }; | 130 }; |
| 126 | 131 |
| 127 | 132 |
| 128 /** | 133 /** |
| 129 * Handles postMessages coming from the host page to the iframe. | 134 * Handles postMessages coming from the host page to the iframe. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 144 * Handles a single command coming from the host page to the iframe. | 149 * Handles a single command coming from the host page to the iframe. |
| 145 * We try to keep the logic here to a minimum and just dispatch to the relevant | 150 * We try to keep the logic here to a minimum and just dispatch to the relevant |
| 146 * functions. | 151 * functions. |
| 147 */ | 152 */ |
| 148 var handleCommand = function(data) { | 153 var handleCommand = function(data) { |
| 149 var cmd = data.cmd; | 154 var cmd = data.cmd; |
| 150 | 155 |
| 151 if (cmd == 'tile') { | 156 if (cmd == 'tile') { |
| 152 addTile(data); | 157 addTile(data); |
| 153 } else if (cmd == 'show') { | 158 } else if (cmd == 'show') { |
| 154 countLoad(); | 159 showTiles(data); |
| 155 hideOverflowTiles(data); | |
| 156 } else if (cmd == 'updateTheme') { | 160 } else if (cmd == 'updateTheme') { |
| 157 updateTheme(data); | 161 updateTheme(data); |
| 158 } else if (cmd == 'tilesVisible') { | 162 } else if (cmd == 'tilesVisible') { |
| 159 hideOverflowTiles(data); | 163 hideOverflowTiles(data); |
| 160 } else { | 164 } else { |
| 161 console.error('Unknown command: ' + JSON.stringify(data)); | 165 console.error('Unknown command: ' + JSON.stringify(data)); |
| 162 } | 166 } |
| 163 }; | 167 }; |
| 164 | 168 |
| 165 | 169 |
| 170 /** |
| 171 * Handler for the 'show' message from the host page. |
| 172 * @param {object} info Data received in the message. |
| 173 */ |
| 174 var showTiles = function(info) { |
| 175 logEvent(LOG_TYPE.NTP_ALL_TILES_RECEIVED); |
| 176 countLoad(); |
| 177 hideOverflowTiles(info); |
| 178 } |
| 179 |
| 180 |
| 181 /** |
| 182 * Handler for the 'updateTheme' message from the host page. |
| 183 * @param {object} info Data received in the message. |
| 184 */ |
| 166 var updateTheme = function(info) { | 185 var updateTheme = function(info) { |
| 167 var themeStyle = []; | 186 var themeStyle = []; |
| 168 | 187 |
| 169 if (info.tileBorderColor) { | 188 if (info.tileBorderColor) { |
| 170 themeStyle.push('.mv-tile {' + | 189 themeStyle.push('.mv-tile {' + |
| 171 'border: 1px solid ' + info.tileBorderColor + '; }'); | 190 'border: 1px solid ' + info.tileBorderColor + '; }'); |
| 172 } | 191 } |
| 173 if (info.tileHoverBorderColor) { | 192 if (info.tileHoverBorderColor) { |
| 174 themeStyle.push('.mv-tile:hover {' + | 193 themeStyle.push('.mv-tile:hover {' + |
| 175 'border-color: ' + info.tileHoverBorderColor + '; }'); | 194 'border-color: ' + info.tileHoverBorderColor + '; }'); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 196 } | 215 } |
| 197 if (info.tileTitleColor) { | 216 if (info.tileTitleColor) { |
| 198 themeStyle.push('body { color: ' + info.tileTitleColor + '; }'); | 217 themeStyle.push('body { color: ' + info.tileTitleColor + '; }'); |
| 199 } | 218 } |
| 200 | 219 |
| 201 document.querySelector('#custom-theme').textContent = themeStyle.join('\n'); | 220 document.querySelector('#custom-theme').textContent = themeStyle.join('\n'); |
| 202 }; | 221 }; |
| 203 | 222 |
| 204 | 223 |
| 205 /** | 224 /** |
| 206 * Hides extra tiles that don't fit on screen. | 225 * Hides extra tiles that don't fit on screen. Called in response to the 'show' |
| 226 * and 'tilesVisible' messages from the host page. |
| 207 */ | 227 */ |
| 208 var hideOverflowTiles = function(data) { | 228 var hideOverflowTiles = function(data) { |
| 209 var tileAndEmptyTileList = document.querySelectorAll( | 229 var tileAndEmptyTileList = document.querySelectorAll( |
| 210 '#mv-tiles .mv-tile,#mv-tiles .mv-empty-tile'); | 230 '#mv-tiles .mv-tile,#mv-tiles .mv-empty-tile'); |
| 211 for (var i = 0; i < tileAndEmptyTileList.length; ++i) { | 231 for (var i = 0; i < tileAndEmptyTileList.length; ++i) { |
| 212 tileAndEmptyTileList[i].classList.toggle('hidden', i >= data.maxVisible); | 232 tileAndEmptyTileList[i].classList.toggle('hidden', i >= data.maxVisible); |
| 213 } | 233 } |
| 214 }; | 234 }; |
| 215 | 235 |
| 216 | 236 |
| 217 /** | 237 /** |
| 218 * Removes all old instances of #mv-tiles that are pending for deletion. | 238 * Removes all old instances of #mv-tiles that are pending for deletion. |
| 219 */ | 239 */ |
| 220 var removeAllOldTiles = function() { | 240 var removeAllOldTiles = function() { |
| 221 var parent = document.querySelector('#most-visited'); | 241 var parent = document.querySelector('#most-visited'); |
| 222 var oldList = parent.querySelectorAll('.mv-tiles-old'); | 242 var oldList = parent.querySelectorAll('.mv-tiles-old'); |
| 223 for (var i = 0; i < oldList.length; ++i) { | 243 for (var i = 0; i < oldList.length; ++i) { |
| 224 parent.removeChild(oldList[i]); | 244 parent.removeChild(oldList[i]); |
| 225 } | 245 } |
| 226 }; | 246 }; |
| 227 | 247 |
| 228 | 248 |
| 229 /** | 249 /** |
| 230 * Called when the host page has finished sending us tile information and | 250 * Called when all tiles have finished loading (successfully or not), including |
| 231 * we are ready to show the new tiles and drop the old ones. | 251 * their thumbnail images, and we are ready to show the new tiles and drop the |
| 252 * old ones. |
| 232 */ | 253 */ |
| 233 var showTiles = function() { | 254 var swapInNewTiles = function() { |
| 234 // Store the tiles on the current closure. | 255 // Store the tiles on the current closure. |
| 235 var cur = tiles; | 256 var cur = tiles; |
| 236 | 257 |
| 237 // Create empty tiles until we have NUMBER_OF_TILES. | 258 // Create empty tiles until we have NUMBER_OF_TILES. |
| 238 while (cur.childNodes.length < NUMBER_OF_TILES) { | 259 while (cur.childNodes.length < NUMBER_OF_TILES) { |
| 239 addTile({}); | 260 addTile({}); |
| 240 } | 261 } |
| 241 | 262 |
| 242 var parent = document.querySelector('#most-visited'); | 263 var parent = document.querySelector('#most-visited'); |
| 243 | 264 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 260 // Add new tileset. | 281 // Add new tileset. |
| 261 cur.id = 'mv-tiles'; | 282 cur.id = 'mv-tiles'; |
| 262 parent.appendChild(cur); | 283 parent.appendChild(cur); |
| 263 // getComputedStyle causes the initial style (opacity 0) to be applied, so | 284 // getComputedStyle causes the initial style (opacity 0) to be applied, so |
| 264 // that when we then set it to 1, that triggers the CSS transition. | 285 // that when we then set it to 1, that triggers the CSS transition. |
| 265 if (fadeIn) { | 286 if (fadeIn) { |
| 266 window.getComputedStyle(cur).opacity; | 287 window.getComputedStyle(cur).opacity; |
| 267 } | 288 } |
| 268 cur.style.opacity = 1.0; | 289 cur.style.opacity = 1.0; |
| 269 | 290 |
| 270 // Make sure the tiles variable contain the next tileset we may use. | 291 // Make sure the tiles variable contain the next tileset we'll use if the host |
| 292 // page sends us an updated set of tiles. |
| 271 tiles = document.createElement('div'); | 293 tiles = document.createElement('div'); |
| 272 }; | 294 }; |
| 273 | 295 |
| 274 | 296 |
| 275 /** | 297 /** |
| 276 * Called when the host page wants to add a suggestion tile. | 298 * Handler for the 'show' message from the host page, called when it wants to |
| 277 * For Most Visited, it grabs the data from Chrome and pass on. | 299 * add a suggestion tile. |
| 278 * For host page generated it just passes the data. | 300 * It's also used to fill up our tiles to NUMBER_OF_TILES if necessary. |
| 279 * @param {object} args Data for the tile to be rendered. | 301 * @param {object} args Data for the tile to be rendered. |
| 280 */ | 302 */ |
| 281 var addTile = function(args) { | 303 var addTile = function(args) { |
| 282 if (isFinite(args.rid)) { | 304 if (isFinite(args.rid)) { |
| 283 // If a valid number passed in |args.rid|: a local chrome suggestion. | 305 // If a valid number passed in |args.rid|: a local Chrome suggestion. Grab |
| 306 // the data from the embeddedSearch API. |
| 284 var data = | 307 var data = |
| 285 chrome.embeddedSearch.newTabPage.getMostVisitedItemData(args.rid); | 308 chrome.embeddedSearch.newTabPage.getMostVisitedItemData(args.rid); |
| 286 if (!data) | 309 if (!data) |
| 287 return; | 310 return; |
| 288 | 311 |
| 289 data.tid = data.rid; | 312 data.tid = data.rid; |
| 290 if (!data.faviconUrl) { | 313 if (!data.faviconUrl) { |
| 291 data.faviconUrl = 'chrome-search://favicon/size/16@' + | 314 data.faviconUrl = 'chrome-search://favicon/size/16@' + |
| 292 window.devicePixelRatio + 'x/' + data.renderViewId + '/' + data.tid; | 315 window.devicePixelRatio + 'x/' + data.renderViewId + '/' + data.tid; |
| 293 } | 316 } |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 return tile; | 551 return tile; |
| 529 }; | 552 }; |
| 530 | 553 |
| 531 | 554 |
| 532 /** | 555 /** |
| 533 * Does some initialization and parses the query arguments passed to the iframe. | 556 * Does some initialization and parses the query arguments passed to the iframe. |
| 534 */ | 557 */ |
| 535 var init = function() { | 558 var init = function() { |
| 536 // Create a new DOM element to hold the tiles. The tiles will be added | 559 // Create a new DOM element to hold the tiles. The tiles will be added |
| 537 // one-by-one via addTile, and the whole thing will be inserted into the page | 560 // one-by-one via addTile, and the whole thing will be inserted into the page |
| 538 // in showTiles, after the parent has sent us the 'show' message, and all | 561 // in swapInNewTiles, after the parent has sent us the 'show' message, and all |
| 539 // thumbnails and favicons have loaded. | 562 // thumbnails and favicons have loaded. |
| 540 tiles = document.createElement('div'); | 563 tiles = document.createElement('div'); |
| 541 | 564 |
| 542 // Parse query arguments. | 565 // Parse query arguments. |
| 543 var query = window.location.search.substring(1).split('&'); | 566 var query = window.location.search.substring(1).split('&'); |
| 544 queryArgs = {}; | 567 queryArgs = {}; |
| 545 for (var i = 0; i < query.length; ++i) { | 568 for (var i = 0; i < query.length; ++i) { |
| 546 var val = query[i].split('='); | 569 var val = query[i].split('='); |
| 547 if (val[0] == '') continue; | 570 if (val[0] == '') continue; |
| 548 queryArgs[decodeURIComponent(val[0])] = decodeURIComponent(val[1]); | 571 queryArgs[decodeURIComponent(val[0])] = decodeURIComponent(val[1]); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 559 var html = document.querySelector('html'); | 582 var html = document.querySelector('html'); |
| 560 html.dir = 'rtl'; | 583 html.dir = 'rtl'; |
| 561 } | 584 } |
| 562 | 585 |
| 563 window.addEventListener('message', handlePostMessage); | 586 window.addEventListener('message', handlePostMessage); |
| 564 }; | 587 }; |
| 565 | 588 |
| 566 | 589 |
| 567 window.addEventListener('DOMContentLoaded', init); | 590 window.addEventListener('DOMContentLoaded', init); |
| 568 })(); | 591 })(); |
| OLD | NEW |