| 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} |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 chrome.embeddedSearch.newTabPage.logEvent(eventType); | 110 chrome.embeddedSearch.newTabPage.logEvent(eventType); |
| 111 }; | 111 }; |
| 112 | 112 |
| 113 /** | 113 /** |
| 114 * Log impression of an NTP tile. | 114 * Log impression of an NTP tile. |
| 115 * @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES. | 115 * @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES. |
| 116 * @param {number} tileSource The source from TileSource. | 116 * @param {number} tileSource The source from TileSource. |
| 117 * @param {number} tileType The type from TileVisualType. | 117 * @param {number} tileType The type from TileVisualType. |
| 118 */ | 118 */ |
| 119 function logMostVisitedImpression(tileIndex, tileSource, tileType) { | 119 function logMostVisitedImpression(tileIndex, tileSource, tileType) { |
| 120 chrome.embeddedSearch.newTabPage.logMostVisitedImpression(tileIndex, | 120 chrome.embeddedSearch.newTabPage.logMostVisitedImpression( |
| 121 tileSource, | 121 tileIndex, tileSource, tileType); |
| 122 tileType); | |
| 123 } | 122 } |
| 124 | 123 |
| 125 /** | 124 /** |
| 126 * Log click on an NTP tile. | 125 * Log click on an NTP tile. |
| 127 * @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES. | 126 * @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES. |
| 128 * @param {number} tileSource The source from TileSource. | 127 * @param {number} tileSource The source from TileSource. |
| 129 * @param {number} tileType The type from TileVisualType. | 128 * @param {number} tileType The type from TileVisualType. |
| 130 */ | 129 */ |
| 131 function logMostVisitedNavigation(tileIndex, tileSource, tileType) { | 130 function logMostVisitedNavigation(tileIndex, tileSource, tileType) { |
| 132 chrome.embeddedSearch.newTabPage.logMostVisitedNavigation(tileIndex, | 131 chrome.embeddedSearch.newTabPage.logMostVisitedNavigation( |
| 133 tileSource, | 132 tileIndex, tileSource, tileType); |
| 134 tileType); | |
| 135 } | 133 } |
| 136 | 134 |
| 137 /** | 135 /** |
| 138 * Down counts the DOM elements that we are waiting for the page to load. | 136 * Down counts the DOM elements that we are waiting for the page to load. |
| 139 * When we get to 0, we send a message to the parent window. | 137 * When we get to 0, we send a message to the parent window. |
| 140 * This is usually used as an EventListener of onload/onerror. | 138 * This is usually used as an EventListener of onload/onerror. |
| 141 */ | 139 */ |
| 142 var countLoad = function() { | 140 var countLoad = function() { |
| 143 loadedCounter -= 1; | 141 loadedCounter -= 1; |
| 144 if (loadedCounter <= 0) { | 142 if (loadedCounter <= 0) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 | 198 |
| 201 | 199 |
| 202 /** | 200 /** |
| 203 * Handler for the 'updateTheme' message from the host page. | 201 * Handler for the 'updateTheme' message from the host page. |
| 204 * @param {object} info Data received in the message. | 202 * @param {object} info Data received in the message. |
| 205 */ | 203 */ |
| 206 var updateTheme = function(info) { | 204 var updateTheme = function(info) { |
| 207 var themeStyle = []; | 205 var themeStyle = []; |
| 208 | 206 |
| 209 if (info.tileBorderColor) { | 207 if (info.tileBorderColor) { |
| 210 themeStyle.push('.mv-tile {' + | 208 themeStyle.push( |
| 209 '.mv-tile {' + |
| 211 'border: 1px solid ' + info.tileBorderColor + '; }'); | 210 'border: 1px solid ' + info.tileBorderColor + '; }'); |
| 212 } | 211 } |
| 213 if (info.tileHoverBorderColor) { | 212 if (info.tileHoverBorderColor) { |
| 214 themeStyle.push('.mv-tile:hover {' + | 213 themeStyle.push( |
| 214 '.mv-tile:hover {' + |
| 215 'border-color: ' + info.tileHoverBorderColor + '; }'); | 215 'border-color: ' + info.tileHoverBorderColor + '; }'); |
| 216 } | 216 } |
| 217 if (info.isThemeDark) { | 217 if (info.isThemeDark) { |
| 218 themeStyle.push('.mv-tile, .mv-empty-tile { ' + | 218 themeStyle.push( |
| 219 '.mv-tile, .mv-empty-tile { ' + |
| 219 'background: rgb(51,51,51); }'); | 220 'background: rgb(51,51,51); }'); |
| 220 themeStyle.push('.mv-thumb.failed-img { ' + | 221 themeStyle.push( |
| 222 '.mv-thumb.failed-img { ' + |
| 221 'background-color: #555; }'); | 223 'background-color: #555; }'); |
| 222 themeStyle.push('.mv-thumb.failed-img::after { ' + | 224 themeStyle.push( |
| 225 '.mv-thumb.failed-img::after { ' + |
| 223 'border-color: #333; }'); | 226 'border-color: #333; }'); |
| 224 themeStyle.push('.mv-x { ' + | 227 themeStyle.push( |
| 228 '.mv-x { ' + |
| 225 'background: linear-gradient(to left, ' + | 229 'background: linear-gradient(to left, ' + |
| 226 'rgb(51,51,51) 60%, transparent); }'); | 230 'rgb(51,51,51) 60%, transparent); }'); |
| 227 themeStyle.push('html[dir=rtl] .mv-x { ' + | 231 themeStyle.push( |
| 232 'html[dir=rtl] .mv-x { ' + |
| 228 'background: linear-gradient(to right, ' + | 233 'background: linear-gradient(to right, ' + |
| 229 'rgb(51,51,51) 60%, transparent); }'); | 234 'rgb(51,51,51) 60%, transparent); }'); |
| 230 themeStyle.push('.mv-x::after { ' + | 235 themeStyle.push( |
| 236 '.mv-x::after { ' + |
| 231 'background-color: rgba(255,255,255,0.7); }'); | 237 'background-color: rgba(255,255,255,0.7); }'); |
| 232 themeStyle.push('.mv-x:hover::after { ' + | 238 themeStyle.push( |
| 239 '.mv-x:hover::after { ' + |
| 233 'background-color: #fff; }'); | 240 'background-color: #fff; }'); |
| 234 themeStyle.push('.mv-x:active::after { ' + | 241 themeStyle.push( |
| 242 '.mv-x:active::after { ' + |
| 235 'background-color: rgba(255,255,255,0.5); }'); | 243 'background-color: rgba(255,255,255,0.5); }'); |
| 236 } | 244 } |
| 237 if (info.tileTitleColor) { | 245 if (info.tileTitleColor) { |
| 238 themeStyle.push('body { color: ' + info.tileTitleColor + '; }'); | 246 themeStyle.push('body { color: ' + info.tileTitleColor + '; }'); |
| 239 } | 247 } |
| 240 | 248 |
| 241 document.querySelector('#custom-theme').textContent = themeStyle.join('\n'); | 249 document.querySelector('#custom-theme').textContent = themeStyle.join('\n'); |
| 242 }; | 250 }; |
| 243 | 251 |
| 244 | 252 |
| 245 /** | 253 /** |
| 246 * Hides extra tiles that don't fit on screen. Called in response to the 'show' | 254 * Hides extra tiles that don't fit on screen. Called in response to the 'show' |
| 247 * and 'tilesVisible' messages from the host page. | 255 * and 'tilesVisible' messages from the host page. |
| 248 */ | 256 */ |
| 249 var hideOverflowTiles = function(data) { | 257 var hideOverflowTiles = function(data) { |
| 250 var tileAndEmptyTileList = document.querySelectorAll( | 258 var tileAndEmptyTileList = |
| 251 '#mv-tiles .mv-tile,#mv-tiles .mv-empty-tile'); | 259 document.querySelectorAll('#mv-tiles .mv-tile,#mv-tiles .mv-empty-tile'); |
| 252 for (var i = 0; i < tileAndEmptyTileList.length; ++i) { | 260 for (var i = 0; i < tileAndEmptyTileList.length; ++i) { |
| 253 tileAndEmptyTileList[i].classList.toggle('hidden', i >= data.maxVisible); | 261 tileAndEmptyTileList[i].classList.toggle('hidden', i >= data.maxVisible); |
| 254 } | 262 } |
| 255 }; | 263 }; |
| 256 | 264 |
| 257 | 265 |
| 258 /** | 266 /** |
| 259 * Removes all old instances of #mv-tiles that are pending for deletion. | 267 * Removes all old instances of #mv-tiles that are pending for deletion. |
| 260 */ | 268 */ |
| 261 var removeAllOldTiles = function() { | 269 var removeAllOldTiles = function() { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 359 |
| 352 /** | 360 /** |
| 353 * Called when the user decided to add a tile to the blacklist. | 361 * Called when the user decided to add a tile to the blacklist. |
| 354 * It sets off the animation for the blacklist and sends the blacklisted id | 362 * It sets off the animation for the blacklist and sends the blacklisted id |
| 355 * to the host page. | 363 * to the host page. |
| 356 * @param {Element} tile DOM node of the tile we want to remove. | 364 * @param {Element} tile DOM node of the tile we want to remove. |
| 357 */ | 365 */ |
| 358 var blacklistTile = function(tile) { | 366 var blacklistTile = function(tile) { |
| 359 tile.classList.add('blacklisted'); | 367 tile.classList.add('blacklisted'); |
| 360 tile.addEventListener('transitionend', function(ev) { | 368 tile.addEventListener('transitionend', function(ev) { |
| 361 if (ev.propertyName != 'width') return; | 369 if (ev.propertyName != 'width') |
| 370 return; |
| 362 | 371 |
| 363 window.parent.postMessage({cmd: 'tileBlacklisted', | 372 window.parent.postMessage( |
| 364 tid: Number(tile.getAttribute('data-tid'))}, | 373 {cmd: 'tileBlacklisted', tid: Number(tile.getAttribute('data-tid'))}, |
| 365 DOMAIN_ORIGIN); | 374 DOMAIN_ORIGIN); |
| 366 }); | 375 }); |
| 367 }; | 376 }; |
| 368 | 377 |
| 369 | 378 |
| 370 /** | 379 /** |
| 371 * Returns whether the given URL has a known, safe scheme. | 380 * Returns whether the given URL has a known, safe scheme. |
| 372 * @param {string} url URL to check. | 381 * @param {string} url URL to check. |
| 373 */ | 382 */ |
| 374 var isSchemeAllowed = function(url) { | 383 var isSchemeAllowed = function(url) { |
| 375 return url.startsWith('http://') || url.startsWith('https://') || | 384 return url.startsWith('http://') || url.startsWith('https://') || |
| 376 url.startsWith('ftp://') || url.startsWith('chrome-extension://'); | 385 url.startsWith('ftp://') || url.startsWith('chrome-extension://'); |
| 377 }; | 386 }; |
| 378 | 387 |
| 379 | 388 |
| 380 /** | 389 /** |
| 381 * Renders a MostVisited tile to the DOM. | 390 * Renders a MostVisited tile to the DOM. |
| 382 * @param {object} data Object containing rid, url, title, favicon, thumbnail. | 391 * @param {object} data Object containing rid, url, title, favicon, thumbnail. |
| 383 * data is null if you want to construct an empty tile. | 392 * data is null if you want to construct an empty tile. |
| 384 */ | 393 */ |
| 385 var renderTile = function(data) { | 394 var renderTile = function(data) { |
| 386 var tile = document.createElement('a'); | 395 var tile = document.createElement('a'); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 414 tile.addEventListener('click', function(ev) { | 423 tile.addEventListener('click', function(ev) { |
| 415 logMostVisitedNavigation(position, data.tileSource, tileType); | 424 logMostVisitedNavigation(position, data.tileSource, tileType); |
| 416 }); | 425 }); |
| 417 | 426 |
| 418 tile.addEventListener('keydown', function(event) { | 427 tile.addEventListener('keydown', function(event) { |
| 419 if (event.keyCode == 46 /* DELETE */ || | 428 if (event.keyCode == 46 /* DELETE */ || |
| 420 event.keyCode == 8 /* BACKSPACE */) { | 429 event.keyCode == 8 /* BACKSPACE */) { |
| 421 event.preventDefault(); | 430 event.preventDefault(); |
| 422 event.stopPropagation(); | 431 event.stopPropagation(); |
| 423 blacklistTile(this); | 432 blacklistTile(this); |
| 424 } else if (event.keyCode == 13 /* ENTER */ || | 433 } else if ( |
| 425 event.keyCode == 32 /* SPACE */) { | 434 event.keyCode == 13 /* ENTER */ || event.keyCode == 32 /* SPACE */) { |
| 426 event.preventDefault(); | 435 event.preventDefault(); |
| 427 this.click(); | 436 this.click(); |
| 428 } else if (event.keyCode >= 37 && event.keyCode <= 40 /* ARROWS */) { | 437 } else if (event.keyCode >= 37 && event.keyCode <= 40 /* ARROWS */) { |
| 429 // specify the direction of movement | 438 // specify the direction of movement |
| 430 var inArrowDirection = function(origin, target) { | 439 var inArrowDirection = function(origin, target) { |
| 431 return (event.keyCode == 37 /* LEFT */ && | 440 return (event.keyCode == 37 /* LEFT */ && |
| 432 origin.offsetTop == target.offsetTop && | 441 origin.offsetTop == target.offsetTop && |
| 433 origin.offsetLeft > target.offsetLeft) || | 442 origin.offsetLeft > target.offsetLeft) || |
| 434 (event.keyCode == 38 /* UP */ && | 443 (event.keyCode == 38 /* UP */ && |
| 435 origin.offsetTop > target.offsetTop && | 444 origin.offsetTop > target.offsetTop && |
| 436 origin.offsetLeft == target.offsetLeft) || | 445 origin.offsetLeft == target.offsetLeft) || |
| 437 (event.keyCode == 39 /* RIGHT */ && | 446 (event.keyCode == 39 /* RIGHT */ && |
| 438 origin.offsetTop == target.offsetTop && | 447 origin.offsetTop == target.offsetTop && |
| 439 origin.offsetLeft < target.offsetLeft) || | 448 origin.offsetLeft < target.offsetLeft) || |
| 440 (event.keyCode == 40 /* DOWN */ && | 449 (event.keyCode == 40 /* DOWN */ && |
| 441 origin.offsetTop < target.offsetTop && | 450 origin.offsetTop < target.offsetTop && |
| 442 origin.offsetLeft == target.offsetLeft); | 451 origin.offsetLeft == target.offsetLeft); |
| 443 }; | 452 }; |
| 444 | 453 |
| 445 var nonEmptyTiles = document.querySelectorAll('#mv-tiles .mv-tile'); | 454 var nonEmptyTiles = document.querySelectorAll('#mv-tiles .mv-tile'); |
| 446 var nextTile = null; | 455 var nextTile = null; |
| 447 // Find the closest tile in the appropriate direction. | 456 // Find the closest tile in the appropriate direction. |
| 448 for (var i = 0; i < nonEmptyTiles.length; i++) { | 457 for (var i = 0; i < nonEmptyTiles.length; i++) { |
| 449 if (inArrowDirection(this, nonEmptyTiles[i]) && | 458 if (inArrowDirection(this, nonEmptyTiles[i]) && |
| 450 (!nextTile || inArrowDirection(nonEmptyTiles[i], nextTile))) { | 459 (!nextTile || inArrowDirection(nonEmptyTiles[i], nextTile))) { |
| 451 nextTile = nonEmptyTiles[i]; | 460 nextTile = nonEmptyTiles[i]; |
| 452 } | 461 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 // one-by-one via addTile, and the whole thing will be inserted into the page | 535 // one-by-one via addTile, and the whole thing will be inserted into the page |
| 527 // in swapInNewTiles, after the parent has sent us the 'show' message, and all | 536 // in swapInNewTiles, after the parent has sent us the 'show' message, and all |
| 528 // thumbnails and favicons have loaded. | 537 // thumbnails and favicons have loaded. |
| 529 tiles = document.createElement('div'); | 538 tiles = document.createElement('div'); |
| 530 | 539 |
| 531 // Parse query arguments. | 540 // Parse query arguments. |
| 532 var query = window.location.search.substring(1).split('&'); | 541 var query = window.location.search.substring(1).split('&'); |
| 533 queryArgs = {}; | 542 queryArgs = {}; |
| 534 for (var i = 0; i < query.length; ++i) { | 543 for (var i = 0; i < query.length; ++i) { |
| 535 var val = query[i].split('='); | 544 var val = query[i].split('='); |
| 536 if (val[0] == '') continue; | 545 if (val[0] == '') |
| 546 continue; |
| 537 queryArgs[decodeURIComponent(val[0])] = decodeURIComponent(val[1]); | 547 queryArgs[decodeURIComponent(val[0])] = decodeURIComponent(val[1]); |
| 538 } | 548 } |
| 539 | 549 |
| 540 if ('ntl' in queryArgs) { | 550 if ('ntl' in queryArgs) { |
| 541 var ntl = parseInt(queryArgs['ntl'], 10); | 551 var ntl = parseInt(queryArgs['ntl'], 10); |
| 542 if (isFinite(ntl)) | 552 if (isFinite(ntl)) |
| 543 NUM_TITLE_LINES = ntl; | 553 NUM_TITLE_LINES = ntl; |
| 544 } | 554 } |
| 545 | 555 |
| 546 // Enable RTL. | 556 // Enable RTL. |
| 547 if (queryArgs['rtl'] == '1') { | 557 if (queryArgs['rtl'] == '1') { |
| 548 var html = document.querySelector('html'); | 558 var html = document.querySelector('html'); |
| 549 html.dir = 'rtl'; | 559 html.dir = 'rtl'; |
| 550 } | 560 } |
| 551 | 561 |
| 552 window.addEventListener('message', handlePostMessage); | 562 window.addEventListener('message', handlePostMessage); |
| 553 }; | 563 }; |
| 554 | 564 |
| 555 | 565 |
| 556 window.addEventListener('DOMContentLoaded', init); | 566 window.addEventListener('DOMContentLoaded', init); |
| 557 })(); | 567 })(); |
| OLD | NEW |