15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// File Description:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     Contains all the necessary functions for rendering the NTP on mobile
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     devices.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The event type used to determine when a touch starts.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string}
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var PRESS_START_EVT = 'touchstart';
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The event type used to determine when a touch finishes.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var PRESS_STOP_EVT = 'touchend';
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The event type used to determine when a touch moves.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var PRESS_MOVE_EVT = 'touchmove';
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('ntp', function() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Constant for the localStorage key used to specify the default bookmark
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * folder to be selected when navigating to the bookmark tab for the first
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * time of a new NTP instance.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var DEFAULT_BOOKMARK_FOLDER_KEY = 'defaultBookmarkFolder';
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Constant for the localStorage key used to store whether or not sync was
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * enabled on the last call to syncEnabled().
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var SYNC_ENABLED_KEY = 'syncEnabled';
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The time before and item gets marked as active (in milliseconds).  This
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * prevents an item from being marked as active when the user is scrolling
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * the page.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {number}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var ACTIVE_ITEM_DELAY_MS = 100;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The CSS class identifier for grid layouts.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var GRID_CSS_CLASS = 'icon-grid';
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The element to center when centering a GRID_CSS_CLASS.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var GRID_CENTER_CSS_CLASS = 'center-icon-grid';
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Attribute used to specify the number of columns to use in a grid.  If
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * left unspecified, the grid will fill the container.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var GRID_COLUMNS = 'grid-columns';
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Attribute used to specify whether the top margin should be set to match
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * the left margin of the grid.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var GRID_SET_TOP_MARGIN_CLASS = 'grid-set-top-margin';
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Attribute used to specify whether the margins of individual items within
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * the grid should be adjusted to better fill the space.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var GRID_SET_ITEM_MARGINS = 'grid-set-item-margins';
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The CSS class identifier for centered empty section containers.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var CENTER_EMPTY_CONTAINER_CSS_CLASS = 'center-empty-container';
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The CSS class identifier for marking list items as active.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var ACTIVE_LIST_ITEM_CSS_CLASS = 'list-item-active';
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Attributes set on elements representing data in a section, specifying
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * which section that element belongs to. Used for context menus.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var SECTION_KEY = 'sectionType';
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Attribute set on an element that has a context menu. Specifies the URL for
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * which the context menu action should apply.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var CONTEXT_MENU_URL_KEY = 'url';
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The list of main section panes added.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {Array.<Element>}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var panes = [];
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The list of section prefixes, which are used to append to the hash of the
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * page to allow the native toolbar to see url changes when the pane is
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * switched.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var sectionPrefixes = [];
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The next available index for new favicons.  Users must increment this
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * value once assigning this index to a favicon.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {number}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var faviconIndex = 0;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The currently selected pane DOM element.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {Element}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var currentPane = null;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The index of the currently selected top level pane.  The index corresponds
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * to the elements defined in {@see #panes}.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {number}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var currentPaneIndex;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The ID of the bookmark folder currently selected.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string|number}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var bookmarkFolderId = null;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The current element active item.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {?Element}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var activeItem;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The element to be marked as active if no actions cancel it.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {?Element}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var pendingActiveItem;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The timer ID to mark an element as active.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {number}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var activeItemDelayTimerId;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Enum for the different load states based on the initialization of the NTP.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @enum {number}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var LoadStatusType = {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOAD_NOT_DONE: 0,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOAD_IMAGES_COMPLETE: 1,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOAD_BOOKMARKS_FINISHED: 2,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOAD_COMPLETE: 3  // An OR'd combination of all necessary states.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The current loading status for the NTP.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {LoadStatusType}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var loadStatus_ = LoadStatusType.LOAD_NOT_DONE;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether the loading complete notification has been sent.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var finishedLoadingNotificationSent_ = false;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * Whether the page title has been loaded.
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @type {boolean}
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var titleLoadedStatus_ = false;
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether the NTP is in incognito mode or not.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var isIncognito = false;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch   * Whether incognito mode is enabled. (It can be blocked e.g. with a policy.)
1999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch   * @type {boolean}
2009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch   */
2019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  var isIncognitoEnabled = true;
2029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
2039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  /**
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether the initial history state has been replaced.  The state will be
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * replaced once the bookmark data has loaded to ensure the proper folder
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * id is persisted.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var replacedInitialState = false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Stores number of most visited pages.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {number}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var numberOfMostVisitedPages = 0;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether there are any recently closed tabs.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var hasRecentlyClosedTabs = false;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether promo is not allowed or not (external to NTP).
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var promoIsAllowed = false;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether promo should be shown on Most Visited page (externally set).
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var promoIsAllowedOnMostVisited = false;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether promo should be shown on Open Tabs page (externally set).
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var promoIsAllowedOnOpenTabs = false;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether promo should show a virtual computer on Open Tabs (externally set).
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {boolean}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var promoIsAllowedAsVirtualComputer = false;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Promo-injected title of a virtual computer on an open tabs pane.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var promoInjectedComputerTitleText = '';
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Promo-injected last synced text of a virtual computer on an open tabs pane.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var promoInjectedComputerLastSyncedText = '';
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The different sections that are displayed.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @enum {number}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var SectionType = {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOKMARKS: 'bookmarks',
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOREIGN_SESSION: 'foreign_session',
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOREIGN_SESSION_HEADER: 'foreign_session_header',
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MOST_VISITED: 'most_visited',
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PROMO_VC_SESSION_HEADER: 'promo_vc_session_header',
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RECENTLY_CLOSED: 'recently_closed',
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SNAPSHOTS: 'snapshots',
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNKNOWN: 'unknown',
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The different ids used of our custom context menu. Sent to the ChromeView
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * and sent back when a menu is selected.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @enum {number}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var ContextMenuItemIds = {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOKMARK_EDIT: 0,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOKMARK_DELETE: 1,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOKMARK_OPEN_IN_NEW_TAB: 2,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOKMARK_OPEN_IN_INCOGNITO_TAB: 3,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOKMARK_SHORTCUT: 4,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MOST_VISITED_OPEN_IN_NEW_TAB: 10,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MOST_VISITED_OPEN_IN_INCOGNITO_TAB: 11,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MOST_VISITED_REMOVE: 12,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RECENTLY_CLOSED_OPEN_IN_NEW_TAB: 20,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RECENTLY_CLOSED_OPEN_IN_INCOGNITO_TAB: 21,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RECENTLY_CLOSED_REMOVE: 22,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOREIGN_SESSIONS_REMOVE: 30,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PROMO_VC_SESSION_REMOVE: 40,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The URL of the element for the context menu.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var contextMenuUrl = null;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var contextMenuItem = null;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var currentSnapshots = null;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var currentSessions = null;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The possible states of the sync section
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @enum {number}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var SyncState = {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    INITIAL: 0,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WAITING_FOR_DATA: 1,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISPLAYING_LOADING: 2,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISPLAYED_LOADING: 3,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOADED: 4,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The current state of the sync section.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var syncState = SyncState.INITIAL;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Whether or not sync is enabled. It will be undefined until
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * setSyncEnabled() is called.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {?boolean}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var syncEnabled = undefined;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The current most visited data being displayed.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {Array.<Object>}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var mostVisitedData_ = [];
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The current bookmark data being displayed. Keep a reference to this data
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * in case the sync enabled state changes.  In this case, the bookmark data
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * will need to be refiltered.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {?Object}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var bookmarkData;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Keep track of any outstanding timers related to updating the sync section.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var syncTimerId = -1;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The minimum amount of time that 'Loading...' can be displayed. This is to
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * prevent flashing.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var SYNC_LOADING_TIMEOUT = 1000;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * How long to wait for sync data to load before displaying the 'Loading...'
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * text to the user.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var SYNC_INITIAL_LOAD_TIMEOUT = 1000;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * An array of images that are currently in loading state. Once an image
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * loads it is removed from this array.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var imagesBeingLoaded = new Array();
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Flag indicating if we are on bookmark shortcut mode.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * In this mode, only the bookmark section is available and selecting
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * a non-folder bookmark adds it to the home screen.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Context menu is disabled.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var bookmarkShortcutMode = false;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setIncognitoMode(incognito) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isIncognito = incognito;
382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!isIncognito) {
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      chrome.send('getMostVisited');
384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      chrome.send('getRecentlyClosedTabs');
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      chrome.send('getForeignSessions');
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      chrome.send('getPromotions');
3879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      chrome.send('getIncognitoDisabled');
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  function setIncognitoEnabled(item) {
3929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    isIncognitoEnabled = item.incognitoEnabled;
3939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  }
3949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Flag set to true when the page is loading its initial set of images. This
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * is set to false after all the initial images have loaded.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function onInitialImageLoaded(event) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var url = event.target.src;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0; i < imagesBeingLoaded.length; ++i) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (imagesBeingLoaded[i].src == url) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        imagesBeingLoaded.splice(i, 1);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (imagesBeingLoaded.length == 0) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // To send out the NTP loading complete notification.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          loadStatus_ |= LoadStatusType.LOAD_IMAGES_COMPLETE;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sendNTPNotification();
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Marks the given image as currently being loaded. Once all such images load
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * we inform the browser via a hash change.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function trackImageLoad(url) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (finishedLoadingNotificationSent_)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0; i < imagesBeingLoaded.length; ++i) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (imagesBeingLoaded[i].src == url)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loadStatus_ &= (~LoadStatusType.LOAD_IMAGES_COMPLETE);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var image = new Image();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.onload = onInitialImageLoaded;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.onerror = onInitialImageLoaded;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.src = url;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    imagesBeingLoaded.push(image);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Initializes all the UI once the page has loaded.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function init() {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special case to handle NTP caching.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window.location.hash == '#cached_ntp')
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.location.hash = '#most_visited';
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special case to show a specific bookmarks folder.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Used to show the mobile bookmarks folder after importing.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var bookmarkIdMatch = window.location.hash.match(/#bookmarks:(\d+)/);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bookmarkIdMatch && bookmarkIdMatch.length == 2) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      localStorage.setItem(DEFAULT_BOOKMARK_FOLDER_KEY, bookmarkIdMatch[1]);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.location.hash = '#bookmarks';
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special case to choose a bookmark for adding a shortcut.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See the doc of bookmarkShortcutMode for details.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window.location.hash == '#bookmark_shortcut')
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarkShortcutMode = true;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure a valid section is always displayed.  Both normal and
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // incognito NTPs have a bookmarks section.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (getPaneIndexFromHash() < 0)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.location.hash = '#bookmarks';
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Initialize common widgets.
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleScrollers =
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        document.getElementsByClassName('section-title-wrapper');
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0, len = titleScrollers.length; i < len; i++)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initializeTitleScroller(titleScrollers[i]);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Initialize virtual computers for the sync promo.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    createPromoVirtualComputers();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setCurrentBookmarkFolderData(
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        localStorage.getItem(DEFAULT_BOOKMARK_FOLDER_KEY));
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addMainSection('incognito');
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addMainSection('most_visited');
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addMainSection('bookmarks');
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addMainSection('open_tabs');
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    computeDynamicLayout();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrollToPane(getPaneIndexFromHash());
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updateSyncEmptyState();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window.onpopstate = onPopStateHandler;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window.addEventListener('hashchange', updatePaneOnHash);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window.addEventListener('resize', windowResizeHandler);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!bookmarkShortcutMode)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.addEventListener('contextmenu', contextMenuHandler);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  function sendNTPTitleLoadedNotification() {
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!titleLoadedStatus_) {
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      titleLoadedStatus_ = true;
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome.send('notifyNTPTitleLoaded');
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Notifies the chrome process of the status of the NTP.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function sendNTPNotification() {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (loadStatus_ != LoadStatusType.LOAD_COMPLETE)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!finishedLoadingNotificationSent_) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      finishedLoadingNotificationSent_ = true;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('notifyNTPReady');
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Navigating after the loading complete notification has been sent
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // might break tests.
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('NTPUnexpectedNavigation');
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The default click handler for created item shortcuts.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item The item specification.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function} evt The browser click event triggered.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function itemShortcutClickHandler(item, evt) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Handle the touch callback
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item['folder']) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browseToBookmarkFolder(item.id);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (bookmarkShortcutMode) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome.send('createHomeScreenBookmarkShortcut', [item.id]);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (!!item.url) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window.location = item.url;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Opens a recently closed tab.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item An object containing the necessary information to
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     reopen a tab.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function openRecentlyClosedTab(item, evt) {
538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    chrome.send('openedRecentlyClosed');
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome.send('reopenTab', [item.sessionId]);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a 'div' DOM element.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} className The CSS class name for the DIV.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string=} opt_backgroundUrl The background URL to be applied to the
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     DIV if required.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The newly created DIV element.
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function createDiv(className, opt_backgroundUrl) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var div = document.createElement('div');
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    div.className = className;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (opt_backgroundUrl)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      div.style.backgroundImage = 'url(' + opt_backgroundUrl + ')';
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return div;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Helper for creating new DOM elements.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} type The type of Element to be created (i.e. 'div',
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     'span').
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} params A mapping of element attribute key and values that
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     should be applied to the new element.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The newly created DOM element.
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function createElement(type, params) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var el = document.createElement(type);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (typeof params === 'string') {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      el.className = params;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (attr in params) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el[attr] = params[attr];
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return el;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Adds a click listener to a specified element with the ability to override
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * the default value of itemShortcutClickHandler.
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} el The element the click listener should be added to.
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item The item data represented by the element.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, string, BrowserEvent)=} opt_clickCallback The
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     click callback to be triggered upon selection.
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function wrapClickHandler(el, item, opt_clickCallback) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.addEventListener('click', function(evt) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var clickCallback =
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          opt_clickCallback ? opt_clickCallback : itemShortcutClickHandler;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clickCallback(item, evt);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Create a DOM element to contain a recently closed item for a tablet
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * device.
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item The data of the item used to generate the shortcut.
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, string, BrowserEvent)=} opt_clickCallback The
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     click callback to be triggered upon selection (if not provided it will
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     use the default -- itemShortcutClickHandler).
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The shortcut element created.
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function makeRecentlyClosedTabletItem(item, opt_clickCallback) {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var cell = createDiv('cell');
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cell.setAttribute(CONTEXT_MENU_URL_KEY, item.url);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var iconUrl = item.icon;
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!iconUrl) {
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      iconUrl = 'chrome://touch-icon/size/16@' + window.devicePixelRatio +
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          'x/' + item.url;
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var icon = createDiv('icon', iconUrl);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    trackImageLoad(iconUrl);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cell.appendChild(icon);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = createDiv('title');
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.textContent = item.title;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cell.appendChild(title);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wrapClickHandler(cell, item, opt_clickCallback);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cell;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a shortcut DOM element based on the item specified item
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * configuration using the thumbnail layout used for most visited.  Other
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * data types should not use this as they won't have a thumbnail.
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item The data of the item used to generate the shortcut.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, string, BrowserEvent)=} opt_clickCallback The
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     click callback to be triggered upon selection (if not provided it will
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     use the default -- itemShortcutClickHandler).
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The shortcut element created.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function makeMostVisitedItem(item, opt_clickCallback) {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // thumbnail-cell          -- main outer container
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   thumbnail-container   -- container for the thumbnail
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     thumbnail           -- the actual thumbnail image; outer border
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     inner-border        -- inner border
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   title                 -- container for the title
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     img                 -- hack align title text baseline with bottom
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     title text          -- the actual text of the title
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var thumbnailCell = createDiv('thumbnail-cell');
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var thumbnailContainer = createDiv('thumbnail-container');
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var backgroundUrl = item.thumbnailUrl || 'chrome://thumb/' + item.url;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (backgroundUrl == 'chrome://thumb/chrome://welcome/') {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ideally, it would be nice to use the URL as is.  However, as of now
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // theme support has been removed from Chrome.  Instead, load the image
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // URL from a style and use it.  Don't just use the style because
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // trackImageLoad(...) must be called with the background URL.
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var welcomeStyle = findCssRule('.welcome-to-chrome').style;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var backgroundImage = welcomeStyle.backgroundImage;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // trim the "url(" prefix and ")" suffix
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backgroundUrl = backgroundImage.substring(4, backgroundImage.length - 1);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    trackImageLoad(backgroundUrl);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var thumbnail = createDiv('thumbnail');
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use an Image object to ensure the thumbnail image actually exists.  If
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not, this will allow the default to show instead.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var thumbnailImg = new Image();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailImg.onload = function() {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thumbnail.style.backgroundImage = 'url(' + backgroundUrl + ')';
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailImg.src = backgroundUrl;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailContainer.appendChild(thumbnail);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var innerBorder = createDiv('inner-border');
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailContainer.appendChild(innerBorder);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailCell.appendChild(thumbnailContainer);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = createDiv('title');
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.textContent = item.title;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var spacerImg = createElement('img', 'title-spacer');
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    spacerImg.alt = '';
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.insertBefore(spacerImg, title.firstChild);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailCell.appendChild(title);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var shade = createDiv('thumbnail-cell-shade');
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thumbnailContainer.appendChild(shade);
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    addActiveTouchListener(shade, 'thumbnail-cell-shade-active');
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wrapClickHandler(thumbnailCell, item, opt_clickCallback);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailCell.setAttribute(CONTEXT_MENU_URL_KEY, item.url);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thumbnailCell.contextMenuItem = item;
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return thumbnailCell;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a shortcut DOM element based on the item specified item
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * configuration using the favicon layout used for bookmarks.
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item The data of the item used to generate the shortcut.
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, string, BrowserEvent)=} opt_clickCallback The
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     click callback to be triggered upon selection (if not provided it will
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     use the default -- itemShortcutClickHandler).
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The shortcut element created.
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function makeBookmarkItem(item, opt_clickCallback) {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var holder = createDiv('favicon-cell');
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addActiveTouchListener(holder, 'favicon-cell-active');
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    holder.setAttribute(CONTEXT_MENU_URL_KEY, item.url);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    holder.contextMenuItem = item;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var faviconBox = createDiv('favicon-box');
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item.folder) {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      faviconBox.classList.add('folder');
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var iconUrl = item.icon || 'chrome://touch-icon/largest/' + item.url;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var faviconIcon = createDiv('favicon-icon');
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      faviconIcon.style.backgroundImage = 'url(' + iconUrl + ')';
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      trackImageLoad(iconUrl);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var image = new Image();
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.src = iconUrl;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.onload = function() {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var w = image.width;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var h = image.height;
723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (Math.floor(w) <= 16 || Math.floor(h) <= 16) {
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // it's a standard favicon (or at least it's small).
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          faviconBox.classList.add('document');
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          faviconBox.appendChild(
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              createDiv('color-strip colorstrip-' + faviconIndex));
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          faviconBox.appendChild(createDiv('bookmark-border'));
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          var foldDiv = createDiv('fold');
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          foldDiv.id = 'fold_' + faviconIndex;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          foldDiv.style['background'] =
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              '-webkit-canvas(fold_' + faviconIndex + ')';
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Use a container so that the fold it self can be zoomed without
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // changing the positioning of the fold.
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          var foldContainer = createDiv('fold-container');
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          foldContainer.appendChild(foldDiv);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          faviconBox.appendChild(foldContainer);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // FaviconWebUIHandler::HandleGetFaviconDominantColor expects
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // an URL that starts with chrome://favicon/size/.
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // The handler always loads 16x16 1x favicon and assumes that
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // the dominant color for all scale factors is the same.
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send('getFaviconDominantColor',
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              [('chrome://favicon/size/16@1x/' + item.url), '' + faviconIndex]);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          faviconIndex++;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if ((w == 57 && h == 57) || (w == 114 && h == 114)) {
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // it's a touch icon for 1x or 2x.
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          faviconIcon.classList.add('touch-icon');
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // It's an html5 icon (or at least it's larger).
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Rescale it to be no bigger than 64x64 dip.
754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          var max = 64;
755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          if (w > max || h > max) {
756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            var scale = (w > h) ? (max / w) : (max / h);
757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            w *= scale;
758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            h *= scale;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          faviconIcon.style.backgroundSize = w + 'px ' + h + 'px';
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      faviconBox.appendChild(faviconIcon);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    holder.appendChild(faviconBox);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = createDiv('title');
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.textContent = item.title;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    holder.appendChild(title);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wrapClickHandler(holder, item, opt_clickCallback);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return holder;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Adds touch listeners to the specified element to apply a class when it is
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * selected (removing the class when no longer pressed).
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} el The element to apply the class to when touched.
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} activeClass The CSS class name to be applied when active.
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function addActiveTouchListener(el, activeClass) {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!window.touchCancelListener) {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.touchCancelListener = function(evt) {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (activeItemDelayTimerId) {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          clearTimeout(activeItemDelayTimerId);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          activeItemDelayTimerId = undefined;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!activeItem) {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        activeItem.classList.remove(activeItem.dataset.activeClass);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        activeItem = null;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.addEventListener('touchcancel', window.touchCancelListener);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.dataset.activeClass = activeClass;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.addEventListener(PRESS_START_EVT, function(evt) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (activeItemDelayTimerId) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        clearTimeout(activeItemDelayTimerId);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        activeItemDelayTimerId = undefined;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      activeItemDelayTimerId = setTimeout(function() {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.classList.add(activeClass);
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        activeItem = el;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }, ACTIVE_ITEM_DELAY_MS);
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.addEventListener(PRESS_STOP_EVT, function(evt) {
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (activeItemDelayTimerId) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        clearTimeout(activeItemDelayTimerId);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        activeItemDelayTimerId = undefined;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add the active class to ensure the pressed state is visible when
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // quickly tapping, which can happen if the start and stop events are
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // received before the active item delay timer has been executed.
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      el.classList.add(activeClass);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      el.classList.add('no-active-delay');
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setTimeout(function() {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.classList.remove(activeClass);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.classList.remove('no-active-delay');
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }, 0);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      activeItem = null;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a shortcut DOM element based on the item specified in the list
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * format.
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item The data of the item used to generate the shortcut.
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, string, BrowserEvent)=} opt_clickCallback The
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     click callback to be triggered upon selection (if not provided it will
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     use the default -- itemShortcutClickHandler).
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The shortcut element created.
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function makeListEntryItem(item, opt_clickCallback) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var listItem = createDiv('list-item');
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addActiveTouchListener(listItem, ACTIVE_LIST_ITEM_CSS_CLASS);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listItem.setAttribute(CONTEXT_MENU_URL_KEY, item.url);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var iconSize = item.iconSize || 64;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var iconUrl = item.icon ||
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        'chrome://touch-icon/size/' + iconSize + '@1x/' + item.url;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listItem.appendChild(createDiv('icon', iconUrl));
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    trackImageLoad(iconUrl);
846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var title = createElement('div', {
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      textContent: item.title,
848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      className: 'title session_title'
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listItem.appendChild(title);
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listItem.addEventListener('click', function(evt) {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var clickCallback =
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          opt_clickCallback ? opt_clickCallback : itemShortcutClickHandler;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clickCallback(item, evt);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item.divider == 'section') {
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add a child div because the section divider has a gradient and
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // webkit doesn't seem to currently support borders with gradients.
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listItem.appendChild(createDiv('section-divider'));
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listItem.classList.add('standard-divider');
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return listItem;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a DOM list entry for a remote session or tab.
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} item The data of the item used to generate the shortcut.
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, string, BrowserEvent)=} opt_clickCallback The
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     click callback to be triggered upon selection (if not provided it will
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     use the default -- itemShortcutClickHandler).
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The shortcut element created.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function makeForeignSessionListEntry(item, opt_clickCallback) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Session item
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var sessionOuterDiv = createDiv('list-item standard-divider');
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addActiveTouchListener(sessionOuterDiv, ACTIVE_LIST_ITEM_CSS_CLASS);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionOuterDiv.contextMenuItem = item;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var icon = createDiv('session-icon ' + item.iconStyle);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionOuterDiv.appendChild(icon);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var titleContainer = createElement('div', 'title');
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionOuterDiv.appendChild(titleContainer);
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Extra container to allow title & last-sync time to stack vertically.
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var sessionInnerDiv = createDiv('session_container');
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    titleContainer.appendChild(sessionInnerDiv);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = createDiv('session-name');
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.textContent = item.title;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.id = item.titleId || '';
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionInnerDiv.appendChild(title);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var lastSynced = createDiv('session-last-synced');
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lastSynced.textContent =
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        templateData.opentabslastsynced + ': ' + item.userVisibleTimestamp;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lastSynced.id = item.userVisibleTimestampId || '';
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionInnerDiv.appendChild(lastSynced);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionOuterDiv.addEventListener('click', function(evt) {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var clickCallback =
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          opt_clickCallback ? opt_clickCallback : itemShortcutClickHandler;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clickCallback(item, evt);
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sessionOuterDiv;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Saves the number of most visited pages and updates promo visibility.
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} n Number of most visited pages.
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setNumberOfMostVisitedPages(n) {
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    numberOfMostVisitedPages = n;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updatePromoVisibility();
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Saves the recently closed tabs flag and updates promo visibility.
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {boolean} anyTabs Whether there are any recently closed tabs.
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setHasRecentlyClosedTabs(anyTabs) {
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hasRecentlyClosedTabs = anyTabs;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updatePromoVisibility();
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the most visited pages.
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Array.<Object>} List of data for displaying the list of most
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     visited pages (see C++ handler for model description).
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {boolean} hasBlacklistedUrls Whether any blacklisted URLs are
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     present.
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setMostVisitedPages(data, hasBlacklistedUrls) {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setNumberOfMostVisitedPages(data.length);
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // limit the number of most visited items to display
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isPhone() && data.length > 6) {
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.splice(6, data.length - 6);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (isTablet() && data.length > 8) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.splice(8, data.length - 8);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (equals(data, mostVisitedData_))
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var clickFunction = function(item) {
950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      chrome.send('openedMostVisited');
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.location = item.url;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    populateData(findList('most_visited'), SectionType.MOST_VISITED, data,
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        makeMostVisitedItem, clickFunction);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    computeDynamicLayout();
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mostVisitedData_ = data;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the recently closed tabs.
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Array.<Object>} List of data for displaying the list of recently
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     closed tabs (see C++ handler for model description).
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setRecentlyClosedTabs(data) {
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var container = $('recently_closed_container');
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data || data.length == 0) {
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // hide the recently closed section if it is empty.
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      container.style.display = 'none';
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setHasRecentlyClosedTabs(false);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      container.style.display = 'block';
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setHasRecentlyClosedTabs(true);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var decoratorFunc = isPhone() ? makeListEntryItem :
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          makeRecentlyClosedTabletItem;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      populateData(findList('recently_closed'), SectionType.RECENTLY_CLOSED,
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          data, decoratorFunc, openRecentlyClosedTab);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    computeDynamicLayout();
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the bookmarks.
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Array.<Object>} List of data for displaying the bookmarks (see
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     C++ handler for model description).
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function bookmarks(data) {
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmarkFolderId = data.id;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!replacedInitialState) {
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      history.replaceState(
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {folderId: bookmarkFolderId, selectedPaneIndex: currentPaneIndex},
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          null, null);
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      replacedInitialState = true;
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (syncEnabled == undefined) {
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Wait till we know whether or not sync is enabled before displaying any
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // bookmarks (since they may need to be filtered below)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarkData = data;
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleWrapper = $('bookmarks_title_wrapper');
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setBookmarkTitleHierarchy(
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        titleWrapper, data, data['hierarchy']);
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var filteredBookmarks = data.bookmarks;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!syncEnabled) {
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filteredBookmarks = filteredBookmarks.filter(function(val) {
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (val.type != 'BOOKMARK_BAR' && val.type != 'OTHER_NODE');
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      });
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bookmarkShortcutMode) {
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      populateData(findList('bookmarks'), SectionType.BOOKMARKS,
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          filteredBookmarks, makeBookmarkItem);
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var clickFunction = function(item) {
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (item['folder']) {
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browseToBookmarkFolder(item.id);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (!!item.url) {
1022ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          chrome.send('openedBookmark');
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          window.location = item.url;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      populateData(findList('bookmarks'), SectionType.BOOKMARKS,
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          filteredBookmarks, makeBookmarkItem, clickFunction);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var bookmarkContainer = $('bookmarks_container');
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // update the shadows on the  breadcrumb bar
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    computeDynamicLayout();
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((loadStatus_ & LoadStatusType.LOAD_BOOKMARKS_FINISHED) !=
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LoadStatusType.LOAD_BOOKMARKS_FINISHED) {
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loadStatus_ |= LoadStatusType.LOAD_BOOKMARKS_FINISHED;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sendNTPNotification();
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Checks if promo is allowed and MostVisited requirements are satisfied.
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {boolean} Whether the promo should be shown on most_visited.
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function shouldPromoBeShownOnMostVisited() {
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return promoIsAllowed && promoIsAllowedOnMostVisited &&
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        numberOfMostVisitedPages >= 2 && !hasRecentlyClosedTabs;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Checks if promo is allowed and OpenTabs requirements are satisfied.
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {boolean} Whether the promo should be shown on open_tabs.
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function shouldPromoBeShownOnOpenTabs() {
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var snapshotsCount =
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        currentSnapshots == null ? 0 : currentSnapshots.length;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var sessionsCount = currentSessions == null ? 0 : currentSessions.length;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return promoIsAllowed && promoIsAllowedOnOpenTabs &&
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (snapshotsCount + sessionsCount != 0);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Checks if promo is allowed and SyncPromo requirements are satisfied.
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {boolean} Whether the promo should be shown on sync_promo.
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function shouldPromoBeShownOnSync() {
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var snapshotsCount =
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        currentSnapshots == null ? 0 : currentSnapshots.length;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var sessionsCount = currentSessions == null ? 0 : currentSessions.length;
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return promoIsAllowed && promoIsAllowedOnOpenTabs &&
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (snapshotsCount + sessionsCount == 0);
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Records a promo impression on a given section if necessary.
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} section Active section name to check.
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function promoUpdateImpressions(section) {
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (section == 'most_visited' && shouldPromoBeShownOnMostVisited())
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('recordImpression', ['most_visited']);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (section == 'open_tabs' && shouldPromoBeShownOnOpenTabs())
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('recordImpression', ['open_tabs']);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (section == 'open_tabs' && shouldPromoBeShownOnSync())
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('recordImpression', ['sync_promo']);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the visibility on all promo-related items as necessary.
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updatePromoVisibility() {
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var mostVisitedEl = $('promo_message_on_most_visited');
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var openTabsVCEl = $('promo_vc_list');
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var syncPromoLegacyEl = $('promo_message_on_sync_promo_legacy');
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var syncPromoReceivedEl = $('promo_message_on_sync_promo_received');
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mostVisitedEl.style.display =
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shouldPromoBeShownOnMostVisited() ? 'block' : 'none';
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncPromoReceivedEl.style.display =
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shouldPromoBeShownOnSync() ? 'block' : 'none';
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncPromoLegacyEl.style.display =
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shouldPromoBeShownOnSync() ? 'none' : 'block';
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    openTabsVCEl.style.display =
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (shouldPromoBeShownOnOpenTabs() && promoIsAllowedAsVirtualComputer) ?
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'block' : 'none';
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called from native.
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Clears the promotion.
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function clearPromotions() {
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setPromotions({});
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Set the element to a parsed and sanitized promotion HTML string.
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} el The element to set the promotion string to.
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} html The promotion HTML string.
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @throws {Error} In case of non supported markup.
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setPromotionHtml(el, html) {
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!el) return;
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.innerHTML = '';
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!html) return;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var tags = ['BR', 'DIV', 'BUTTON', 'SPAN'];
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var attrs = {
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      class: function(node, value) { return true; },
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      style: function(node, value) { return true; },
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try {
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var fragment = parseHtmlSubset(html, tags, attrs);
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      el.appendChild(fragment);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } catch (err) {
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      console.error(err.toString());
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ignore all errors while parsing or setting the element.
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called from native.
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Sets the text for all promo-related items, updates
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * promo-send-email-target items to send email on click and
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * updates the visibility of items.
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} promotions Dictionary used to fill-in the text.
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setPromotions(promotions) {
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var mostVisitedEl = $('promo_message_on_most_visited');
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var openTabsEl = $('promo_message_on_open_tabs');
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var syncPromoReceivedEl = $('promo_message_on_sync_promo_received');
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoIsAllowed = !!promotions.promoIsAllowed;
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoIsAllowedOnMostVisited = !!promotions.promoIsAllowedOnMostVisited;
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoIsAllowedOnOpenTabs = !!promotions.promoIsAllowedOnOpenTabs;
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoIsAllowedAsVirtualComputer = !!promotions.promoIsAllowedAsVC;
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setPromotionHtml(mostVisitedEl, promotions.promoMessage);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setPromotionHtml(openTabsEl, promotions.promoMessage);
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setPromotionHtml(syncPromoReceivedEl, promotions.promoMessageLong);
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoInjectedComputerTitleText = promotions.promoVCTitle || '';
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoInjectedComputerLastSyncedText = promotions.promoVCLastSynced || '';
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var openTabsVCTitleEl = $('promo_vc_title');
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (openTabsVCTitleEl)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      openTabsVCTitleEl.textContent = promoInjectedComputerTitleText;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var openTabsVCLastSyncEl = $('promo_vc_lastsync');
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (openTabsVCLastSyncEl)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      openTabsVCLastSyncEl.textContent = promoInjectedComputerLastSyncedText;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (promoIsAllowed) {
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var promoButtonEls =
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          document.getElementsByClassName('promo-button');
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (var i = 0, len = promoButtonEls.length; i < len; i++) {
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        promoButtonEls[i].onclick = executePromoAction;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        addActiveTouchListener(promoButtonEls[i], 'promo-button-active');
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updatePromoVisibility();
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * On-click handler for promo email targets.
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Performs the promo action "send email".
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} evt User interface event that triggered the action.
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function executePromoAction(evt) {
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (evt.preventDefault)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      evt.preventDefault();
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    evt.returnValue = false;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome.send('promoActionTriggered');
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called by the browser when a context menu has been selected.
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} itemId The id of the item that was selected, as specified
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     when chrome.send('showContextMenu') was called.
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function onCustomMenuSelected(itemId) {
1199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (contextMenuUrl != null) {
1200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      switch (itemId) {
1201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case ContextMenuItemIds.BOOKMARK_OPEN_IN_NEW_TAB:
1202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case ContextMenuItemIds.BOOKMARK_OPEN_IN_INCOGNITO_TAB:
1203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          chrome.send('openedBookmark');
1204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          break;
1205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case ContextMenuItemIds.MOST_VISITED_OPEN_IN_NEW_TAB:
1207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case ContextMenuItemIds.MOST_VISITED_OPEN_IN_INCOGNITO_TAB:
1208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          chrome.send('openedMostVisited');
1209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          break;
1210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case ContextMenuItemIds.RECENTLY_CLOSED_OPEN_IN_NEW_TAB:
1212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case ContextMenuItemIds.RECENTLY_CLOSED_OPEN_IN_INCOGNITO_TAB:
1213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          chrome.send('openedRecentlyClosed');
1214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          break;
1215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
1216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
1217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (itemId) {
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.BOOKMARK_OPEN_IN_NEW_TAB:
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.MOST_VISITED_OPEN_IN_NEW_TAB:
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.RECENTLY_CLOSED_OPEN_IN_NEW_TAB:
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuUrl != null)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send('openInNewTab', [contextMenuUrl]);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.BOOKMARK_OPEN_IN_INCOGNITO_TAB:
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.MOST_VISITED_OPEN_IN_INCOGNITO_TAB:
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.RECENTLY_CLOSED_OPEN_IN_INCOGNITO_TAB:
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuUrl != null)
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send('openInIncognitoTab', [contextMenuUrl]);
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.BOOKMARK_EDIT:
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuItem != null)
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          chrome.send('editBookmark', [contextMenuItem.id]);
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.BOOKMARK_DELETE:
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuUrl != null)
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send('deleteBookmark', [contextMenuItem.id]);
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.MOST_VISITED_REMOVE:
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuUrl != null)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send('blacklistURLFromMostVisited', [contextMenuUrl]);
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.BOOKMARK_SHORTCUT:
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuUrl != null)
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send('createHomeScreenBookmarkShortcut', [contextMenuItem.id]);
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.RECENTLY_CLOSED_REMOVE:
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome.send('clearRecentlyClosed');
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.FOREIGN_SESSIONS_REMOVE:
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuItem != null) {
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send(
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              'deleteForeignSession', [contextMenuItem.sessionTag]);
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome.send('getForeignSessions');
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ContextMenuItemIds.PROMO_VC_SESSION_REMOVE:
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome.send('promoDisabled');
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        log.error('Unknown context menu selected id=' + itemId);
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Generates the full bookmark folder hierarchy and populates the scrollable
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * title element.
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} wrapperEl The wrapper element containing the scrollable
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     title.
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} data The current bookmark folder node.
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Array.<Object>=} opt_ancestry The folder ancestry of the current
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     bookmark folder.  The list is ordered in order of closest descendant
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     (the root will always be the last node).  The definition of each
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     element is:
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     - id {number}: Unique ID of the folder (N/A for root node).
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     - name {string}: Name of the folder (N/A for root node).
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     - root {boolean}: Whether this is the root node.
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setBookmarkTitleHierarchy(wrapperEl, data, opt_ancestry) {
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = wrapperEl.getElementsByClassName('section-title')[0];
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.innerHTML = '';
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (opt_ancestry) {
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (var i = opt_ancestry.length - 1; i >= 0; i--) {
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var titleCrumb = createBookmarkTitleCrumb_(opt_ancestry[i]);
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        title.appendChild(titleCrumb);
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        title.appendChild(createDiv('bookmark-separator'));
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleCrumb = createBookmarkTitleCrumb_(data);
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    titleCrumb.classList.add('title-crumb-active');
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.appendChild(titleCrumb);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure the last crumb is as visible as possible.
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var windowWidth =
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wrapperEl.getElementsByClassName('section-title-mask')[0].offsetWidth;
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var crumbWidth = titleCrumb.offsetWidth;
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var leftOffset = titleCrumb.offsetLeft;
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var shiftLeft = windowWidth - crumbWidth - leftOffset;
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (shiftLeft < 0) {
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (crumbWidth > windowWidth)
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shifLeft = -leftOffset;
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Queue up the scrolling initially to allow for the mask element to
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // be placed into the dom and it's size correctly calculated.
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setTimeout(function() {
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handleTitleScroll(wrapperEl, shiftLeft);
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }, 0);
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handleTitleScroll(wrapperEl, 0);
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a clickable bookmark title crumb.
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} data The crumb data (see setBookmarkTitleHierarchy for
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     definition of the data object).
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The clickable title crumb element.
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @private
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function createBookmarkTitleCrumb_(data) {
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleCrumb = createDiv('title-crumb');
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data.root) {
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      titleCrumb.innerText = templateData.bookmarkstitle;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      titleCrumb.innerText = data.title;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    titleCrumb.addEventListener('click', function(evt) {
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browseToBookmarkFolder(data.root ? '0' : data.id);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return titleCrumb;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Handles scrolling a title element.
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} wrapperEl The wrapper element containing the scrollable
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     title.
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} scrollPosition The position to be scrolled to.
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function handleTitleScroll(wrapperEl, scrollPosition) {
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var overflowLeftMask =
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wrapperEl.getElementsByClassName('overflow-left-mask')[0];
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var overflowRightMask =
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wrapperEl.getElementsByClassName('overflow-right-mask')[0];
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = wrapperEl.getElementsByClassName('section-title')[0];
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleMask = wrapperEl.getElementsByClassName('section-title-mask')[0];
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleWidth = title.scrollWidth;
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var containerWidth = titleMask.offsetWidth;
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var maxRightScroll = containerWidth - titleWidth;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var boundedScrollPosition =
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Math.max(maxRightScroll, Math.min(scrollPosition, 0));
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overflowLeftMask.style.opacity =
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Math.min(
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            1,
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (Math.max(0, -boundedScrollPosition)) + 10 / 30);
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overflowRightMask.style.opacity =
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Math.min(
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            1,
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (Math.max(0, boundedScrollPosition - maxRightScroll) + 10) / 30);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the position of the title.
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (titleWidth < containerWidth) {
1377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // left-align on LTR and right-align on RTL.
1378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      title.style.left = '';
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      title.style.left = boundedScrollPosition + 'px';
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Initializes a scrolling title element.
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} wrapperEl The wrapper element of the scrolling title.
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function initializeTitleScroller(wrapperEl) {
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = wrapperEl.getElementsByClassName('section-title')[0];
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var inTitleScroll = false;
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var startingScrollPosition;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var startingOffset;
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wrapperEl.addEventListener(PRESS_START_EVT, function(evt) {
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inTitleScroll = true;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      startingScrollPosition = getTouchEventX(evt);
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      startingOffset = title.offsetLeft;
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    document.body.addEventListener(PRESS_STOP_EVT, function(evt) {
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!inTitleScroll)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inTitleScroll = false;
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    document.body.addEventListener(PRESS_MOVE_EVT, function(evt) {
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!inTitleScroll)
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handleTitleScroll(
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wrapperEl,
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          startingOffset - (startingScrollPosition - getTouchEventX(evt)));
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      evt.stopPropagation();
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Handles updates from the underlying bookmark model (calls originate
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * in the WebUI handler for bookmarks).
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} status Describes the type of change that occurred.  Can
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     contain the following fields:
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     - parent_id {string}: Unique id of the parent that was affected by
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *                           the change.  If the parent is the bookmark
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *                           bar, then the ID will be 'root'.
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     - node_id {string}: The unique ID of the node that was affected.
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function bookmarkChanged(status) {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (status) {
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var affectedParentNode = status['parent_id'];
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var affectedNodeId = status['node_id'];
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var shouldUpdate = (bookmarkFolderId == affectedParentNode ||
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bookmarkFolderId == affectedNodeId);
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (shouldUpdate)
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        setCurrentBookmarkFolderData(bookmarkFolderId);
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This typically happens when extensive changes could have happened to
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the model, such as initial load, import and sync.
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setCurrentBookmarkFolderData(bookmarkFolderId);
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Loads the bookarks data for a given folder.
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string|number} folderId The ID of the folder to load (or null if
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     it should load the root folder).
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setCurrentBookmarkFolderData(folderId) {
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (folderId != null) {
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('getBookmarks', [folderId]);
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('getBookmarks');
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try {
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (folderId == null) {
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        localStorage.removeItem(DEFAULT_BOOKMARK_FOLDER_KEY);
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        localStorage.setItem(DEFAULT_BOOKMARK_FOLDER_KEY, folderId);
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } catch (e) {}
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Navigates to the specified folder and handles loading the required data.
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Ensures the current folder can be navigated back to using the browser
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * controls.
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string|number} folderId The ID of the folder to navigate to.
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function browseToBookmarkFolder(folderId) {
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history.pushState(
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {folderId: folderId, selectedPaneIndex: currentPaneIndex},
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        null, null);
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setCurrentBookmarkFolderData(folderId);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called to inform the page of the current sync status. If the state has
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * changed from disabled to enabled, it changes the current and default
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * bookmark section to the root directory.  This makes desktop bookmarks are
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * visible.
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setSyncEnabled(enabled) {
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try {
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (syncEnabled != undefined && syncEnabled == enabled) {
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The value didn't change
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncEnabled = enabled;
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (enabled) {
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!localStorage.getItem(SYNC_ENABLED_KEY)) {
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          localStorage.setItem(SYNC_ENABLED_KEY, 'true');
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          setCurrentBookmarkFolderData('0');
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        localStorage.removeItem(SYNC_ENABLED_KEY);
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updatePromoVisibility();
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (bookmarkData) {
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Bookmark data can now be displayed (or needs to be refiltered)
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bookmarks(bookmarkData);
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updateSyncEmptyState();
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } catch (e) {}
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Handles adding or removing the 'nothing to see here' text from the session
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * list depending on the state of snapshots and sessions.
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {boolean} Whether the call is occuring because of a schedule
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     timeout.
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updateSyncEmptyState(timeout) {
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (syncState == SyncState.DISPLAYING_LOADING && !timeout) {
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make sure 'Loading...' is displayed long enough
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var openTabsList = findList('open_tabs');
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var snapshotsList = findList('snapshots');
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var syncPromo = $('sync_promo');
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var syncLoading = $('sync_loading');
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var syncEnableSync = $('sync_enable_sync');
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (syncEnabled == undefined ||
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        currentSnapshots == null ||
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        currentSessions == null) {
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (syncState == SyncState.INITIAL) {
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Wait one second for sync data to come in before displaying loading
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // text.
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncState = SyncState.WAITING_FOR_DATA;
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncTimerId = setTimeout(function() { updateSyncEmptyState(true); },
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SYNC_INITIAL_LOAD_TIMEOUT);
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (syncState == SyncState.WAITING_FOR_DATA && timeout) {
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We've waited for the initial info timeout to pass and still don't
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // have data.  So, display loading text so the user knows something is
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // happening.
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncState = SyncState.DISPLAYING_LOADING;
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncLoading.style.display = '-webkit-box';
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        centerEmptySections(syncLoading);
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncTimerId = setTimeout(function() { updateSyncEmptyState(true); },
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SYNC_LOADING_TIMEOUT);
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (syncState == SyncState.DISPLAYING_LOADING) {
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Allow the Loading... text to go away once data comes in
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncState = SyncState.DISPLAYED_LOADING;
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (syncTimerId != -1) {
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clearTimeout(syncTimerId);
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncTimerId = -1;
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncState = SyncState.LOADED;
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hide everything by default, display selectively below
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncEnableSync.style.display = 'none';
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncLoading.style.display = 'none';
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncPromo.style.display = 'none';
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var snapshotsCount =
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        currentSnapshots == null ? 0 : currentSnapshots.length;
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var sessionsCount = currentSessions == null ? 0 : currentSessions.length;
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!syncEnabled) {
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncEnableSync.style.display = '-webkit-box';
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      centerEmptySections(syncEnableSync);
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (sessionsCount + snapshotsCount == 0) {
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncPromo.style.display = '-webkit-box';
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      centerEmptySections(syncPromo);
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      openTabsList.style.display = sessionsCount == 0 ? 'none' : 'block';
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snapshotsList.style.display = snapshotsCount == 0 ? 'none' : 'block';
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updatePromoVisibility();
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called externally when updated snapshot data is available.
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} data The snapshot data
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function snapshots(data) {
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var list = findList('snapshots');
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list.innerHTML = '';
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    currentSnapshots = data;
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updateSyncEmptyState();
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data || data.length == 0)
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.sort(function(a, b) {
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return b.createTime - a.createTime;
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the main container
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var snapshotsEl = createElement('div');
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list.appendChild(snapshotsEl);
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the header container
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var headerEl = createDiv('session-header');
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snapshotsEl.appendChild(headerEl);
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the documents container
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var docsEl = createDiv('session-children-container');
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snapshotsEl.appendChild(docsEl);
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the container for the title & icon
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var headerInnerEl = createDiv('list-item standard-divider');
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addActiveTouchListener(headerInnerEl, ACTIVE_LIST_ITEM_CSS_CLASS);
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headerEl.appendChild(headerInnerEl);
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the header icon
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headerInnerEl.appendChild(createDiv('session-icon documents'));
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the header title
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleContainer = createElement('span', 'title');
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headerInnerEl.appendChild(titleContainer);
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var title = createDiv('session-name');
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.textContent = templateData.receivedDocuments;
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    titleContainer.appendChild(title);
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add support for expanding and collapsing the children
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var expando = createDiv();
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var expandoFunction = createExpandoFunction(expando, docsEl);
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headerInnerEl.addEventListener('click', expandoFunction);
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headerEl.appendChild(expando);
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Support for actually opening the document
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var snapshotClickCallback = function(item) {
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!item)
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (item.snapshotId) {
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window.location = 'chrome://snapshot/' + item.snapshotId;
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (item.printJobId) {
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window.location = 'chrome://printjob/' + item.printJobId;
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window.location = item.url;
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Finally, add the list of documents
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    populateData(docsEl, SectionType.SNAPSHOTS, data,
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        makeListEntryItem, snapshotClickCallback);
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Create a function to handle expanding and collapsing a section
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} expando The expando div
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} element The element to expand and collapse
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {function()} A callback function that should be invoked when the
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     expando is clicked
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function createExpandoFunction(expando, element) {
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expando.className = 'expando open';
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return function() {
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (element.style.height != '0px') {
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // It seems that '-webkit-transition' only works when explicit pixel
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // values are used.
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        setTimeout(function() {
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If this is the first time to collapse the list, store off the
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // expanded height and also set the height explicitly on the style.
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!element.expandedHeight) {
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            element.expandedHeight =
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                element.clientHeight + 'px';
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            element.style.height = element.expandedHeight;
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Now set the height to 0.  Note, this is also done in a callback to
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // give the layout engine a chance to run after possibly setting the
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // height above.
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          setTimeout(function() {
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            element.style.height = '0px';
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }, 0);
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }, 0);
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expando.className = 'expando closed';
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        element.style.height = element.expandedHeight;
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expando.className = 'expando open';
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Initializes the promo_vc_list div to look like a foreign session
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * with a desktop.
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function createPromoVirtualComputers() {
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var list = findList('promo_vc');
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list.innerHTML = '';
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set up the container and the "virtual computer" session header.
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var sessionEl = createDiv();
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list.appendChild(sessionEl);
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var sessionHeader = createDiv('session-header');
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionEl.appendChild(sessionHeader);
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set up the session children container and the promo as a child.
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var sessionChildren = createDiv('session-children-container');
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var promoMessage = createDiv('promo-message');
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoMessage.id = 'promo_message_on_open_tabs';
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionChildren.appendChild(promoMessage);
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionEl.appendChild(sessionChildren);
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add support for expanding and collapsing the children.
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var expando = createDiv();
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var expandoFunction = createExpandoFunction(expando, sessionChildren);
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fill-in the contents of the "virtual computer" session header.
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var headerList = [{
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'title': promoInjectedComputerTitleText,
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'titleId': 'promo_vc_title',
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'userVisibleTimestamp': promoInjectedComputerLastSyncedText,
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'userVisibleTimestampId': 'promo_vc_lastsync',
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'iconStyle': 'laptop'
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }];
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    populateData(sessionHeader, SectionType.PROMO_VC_SESSION_HEADER, headerList,
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        makeForeignSessionListEntry, expandoFunction);
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sessionHeader.appendChild(expando);
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called externally when updated synced sessions data is available.
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} data The snapshot data
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setForeignSessions(data, tabSyncEnabled) {
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var list = findList('open_tabs');
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list.innerHTML = '';
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    currentSessions = data;
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updateSyncEmptyState();
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sort the windows within each client such that more recently
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // modified windows appear first.
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.forEach(function(client) {
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (client.windows != null) {
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        client.windows.sort(function(a, b) {
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (b.timestamp == null) {
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return -1;
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else if (a.timestamp == null) {
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 1;
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return b.timestamp - a.timestamp;
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        });
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sort so more recently modified clients appear first.
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.sort(function(aClient, bClient) {
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var aWindows = aClient.windows;
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var bWindows = bClient.windows;
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (bWindows == null || bWindows.length == 0 ||
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bWindows[0].timestamp == null) {
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return -1;
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (aWindows == null || aWindows.length == 0 ||
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          aWindows[0].timestamp == null) {
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 1;
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return bWindows[0].timestamp - aWindows[0].timestamp;
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.forEach(function(client, clientNum) {
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var windows = client.windows;
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (windows == null || windows.length == 0)
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Set up the container for the session header
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var sessionEl = createElement('div');
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      list.appendChild(sessionEl);
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var sessionHeader = createDiv('session-header');
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sessionEl.appendChild(sessionHeader);
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Set up the container for the session children
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var sessionChildren = createDiv('session-children-container');
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sessionEl.appendChild(sessionChildren);
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var clientName = 'Client ' + clientNum;
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (client.name)
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        clientName = client.name;
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var iconStyle;
17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var deviceType = client.deviceType;
17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (deviceType == 'win' ||
17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          deviceType == 'macosx' ||
17932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          deviceType == 'linux' ||
17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          deviceType == 'chromeos' ||
17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          deviceType == 'other') {
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iconStyle = 'laptop';
17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (deviceType == 'phone') {
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iconStyle = 'phone';
17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (deviceType == 'tablet') {
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iconStyle = 'tablet';
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        console.error('Unknown sync device type found: ', deviceType);
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iconStyle = 'laptop';
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var headerList = [{
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'title': clientName,
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'userVisibleTimestamp': windows[0].userVisibleTimestamp,
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'iconStyle': iconStyle,
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'sessionTag': client.tag,
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }];
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var expando = createDiv();
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var expandoFunction = createExpandoFunction(expando, sessionChildren);
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      populateData(sessionHeader, SectionType.FOREIGN_SESSION_HEADER,
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          headerList, makeForeignSessionListEntry, expandoFunction);
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sessionHeader.appendChild(expando);
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Populate the session children container
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var openTabsList = new Array();
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (var winNum = 0; winNum < windows.length; winNum++) {
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        win = windows[winNum];
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var tabs = win.tabs;
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (var tabNum = 0; tabNum < tabs.length; tabNum++) {
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          var tab = tabs[tabNum];
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If this is the last tab in the window and there are more windows,
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // use a section divider.
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          var needSectionDivider =
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (tabNum + 1 == tabs.length) && (winNum + 1 < windows.length);
1829d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          tab.icon = tab.icon || 'chrome://favicon/size/16@1x/' + tab.url;
1830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          openTabsList.push({
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            timestamp: tab.timestamp,
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            title: tab.title,
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            url: tab.url,
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sessionTag: client.tag,
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            winNum: winNum,
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sessionId: tab.sessionId,
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            icon: tab.icon,
1839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            iconSize: 16,
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            divider: needSectionDivider ? 'section' : 'standard',
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          });
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var tabCallback = function(item, evt) {
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var buttonIndex = 0;
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var altKeyPressed = false;
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var ctrlKeyPressed = false;
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var metaKeyPressed = false;
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var shiftKeyPressed = false;
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (evt instanceof MouseEvent) {
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          buttonIndex = evt.button;
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          altKeyPressed = evt.altKey;
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ctrlKeyPressed = evt.ctrlKey;
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          metaKeyPressed = evt.metaKey;
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          shiftKeyPressed = evt.shiftKey;
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1857ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        chrome.send('openedForeignSession');
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome.send('openForeignSession', [String(item.sessionTag),
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            String(item.winNum), String(item.sessionId), buttonIndex,
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            altKeyPressed, ctrlKeyPressed, metaKeyPressed, shiftKeyPressed]);
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      populateData(sessionChildren, SectionType.FOREIGN_SESSION, openTabsList,
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          makeListEntryItem, tabCallback);
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the dominant favicon color for a given index.
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} index The index of the favicon whose dominant color is
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     being specified.
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} color The string encoded color.
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function setFaviconDominantColor(index, color) {
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var colorstrips = document.getElementsByClassName('colorstrip-' + index);
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0; i < colorstrips.length; i++)
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      colorstrips[i].style.background = color;
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var id = 'fold_' + index;
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var fold = $(id);
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!fold)
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var zoom = window.getComputedStyle(fold).zoom;
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var scale = 1 / window.getComputedStyle(fold).zoom;
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The width/height of the canvas.  Set to 24 so it looks good across all
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // resolutions.
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var cw = 24;
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var ch = 24;
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get the fold canvas and create a path for the fold shape
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var ctx = document.getCSSCanvasContext(
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        '2d', 'fold_' + index, cw * scale, ch * scale);
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.beginPath();
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.moveTo(0, 0);
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ctx.lineTo(0, ch * 0.75 * scale);
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.quadraticCurveTo(
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        0, ch * scale,
18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cw * .25 * scale, ch * scale);
19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ctx.lineTo(cw * scale, ch * scale);
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.closePath();
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a gradient for the fold and fill it
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var gradient = ctx.createLinearGradient(cw * scale, 0, 0, ch * scale);
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (color.indexOf('#') == 0) {
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var r = parseInt(color.substring(1, 3), 16);
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var g = parseInt(color.substring(3, 5), 16);
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var b = parseInt(color.substring(5, 7), 16);
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gradient.addColorStop(0, 'rgba(' + r + ', ' + g + ', ' + b + ', 0.6)');
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // assume the color is in the 'rgb(#, #, #)' format
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var rgbBase = color.substring(4, color.length - 1);
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gradient.addColorStop(0, 'rgba(' + rgbBase + ', 0.6)');
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gradient.addColorStop(1, color);
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.fillStyle = gradient;
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.fill();
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stroke the fold
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.lineWidth = Math.floor(scale);
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.strokeStyle = color;
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.stroke();
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.strokeStyle = 'rgba(0, 0, 0, 0.1)';
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx.stroke();
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Finds the list element corresponding to the given name.
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} name The name prefix of the DOM element (<prefix>_list).
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Element} The list element corresponding with the name.
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function findList(name) {
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return $(name + '_list');
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Render the given data into the given list, and hide or show the entire
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * container based on whether there are any elements.  The decorator function
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * is used to create the element to be inserted based on the given data
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * object.
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {holder} The dom element that the generated list items will be put
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     into.
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {SectionType} section The section that data is for.
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} data The data to be populated.
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, boolean)} decorator The function that will
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     handle decorating each item in the data.
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {function(Object, Object)} opt_clickCallback The function that is
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     called when the item is clicked.
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function populateData(holder, section, data, decorator,
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      opt_clickCallback) {
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Empty other items in the list, if present.
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    holder.innerHTML = '';
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var fragment = document.createDocumentFragment();
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data || data.length == 0) {
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fragment.innerHTML = '';
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.forEach(function(item) {
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var el = decorator(item, opt_clickCallback);
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.setAttribute(SECTION_KEY, section);
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.id = section + fragment.childNodes.length;
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fragment.appendChild(el);
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      });
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    holder.appendChild(fragment);
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (holder.classList.contains(GRID_CSS_CLASS))
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      centerGrid(holder);
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    centerEmptySections(holder);
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Given an element containing a list of child nodes arranged in
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * a grid, this will center the grid in the window based on the
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * remaining space.
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} el Container holding the grid cell items.
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function centerGrid(el) {
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var childEl = el.firstChild;
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!childEl)
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find the element to actually set the margins on.
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var toCenter = el;
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var curEl = toCenter;
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (curEl && curEl.classList) {
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (curEl.classList.contains(GRID_CENTER_CSS_CLASS)) {
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        toCenter = curEl;
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curEl = curEl.parentNode;
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var setItemMargins = el.classList.contains(GRID_SET_ITEM_MARGINS);
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var itemWidth = getItemWidth(childEl, setItemMargins);
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var windowWidth = document.documentElement.offsetWidth;
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (itemWidth >= windowWidth) {
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      toCenter.style.paddingLeft = '0';
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      toCenter.style.paddingRight = '0';
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var numColumns = el.getAttribute(GRID_COLUMNS);
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (numColumns) {
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        numColumns = parseInt(numColumns);
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        numColumns = Math.floor(windowWidth / itemWidth);
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (setItemMargins) {
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // In this case, try to size each item to fill as much space as
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // possible.
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var gutterSize =
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (windowWidth - itemWidth * numColumns) / (numColumns + 1);
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var childLeftMargin = Math.round(gutterSize / 2);
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var childRightMargin = Math.floor(gutterSize - childLeftMargin);
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var children = el.childNodes;
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (var i = 0; i < children.length; i++) {
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          children[i].style.marginLeft = childLeftMargin + 'px';
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          children[i].style.marginRight = childRightMargin + 'px';
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        itemWidth += childLeftMargin + childRightMargin;
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var remainder = windowWidth - itemWidth * numColumns;
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var leftPadding = Math.round(remainder / 2);
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var rightPadding = Math.floor(remainder - leftPadding);
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      toCenter.style.paddingLeft = leftPadding + 'px';
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      toCenter.style.paddingRight = rightPadding + 'px';
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (toCenter.classList.contains(GRID_SET_TOP_MARGIN_CLASS)) {
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var childStyle = window.getComputedStyle(childEl);
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var childLeftPadding = parseInt(
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            childStyle.getPropertyValue('padding-left'));
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        toCenter.style.paddingTop =
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (childLeftMargin + childLeftPadding + leftPadding) + 'px';
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Finds and centers all child grid elements for a given node (the grids
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * do not need to be direct descendants and can reside anywhere in the node
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * hierarchy).
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} el The node containing the grid child nodes.
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function centerChildGrids(el) {
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var grids = el.getElementsByClassName(GRID_CSS_CLASS);
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0; i < grids.length; i++)
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      centerGrid(grids[i]);
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Finds and vertically centers all 'empty' elements for a given node (the
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * 'empty' elements do not need to be direct descendants and can reside
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * anywhere in the node hierarchy).
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} el The node containing the 'empty' child nodes.
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function centerEmptySections(el) {
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (el.classList &&
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.classList.contains(CENTER_EMPTY_CONTAINER_CSS_CLASS)) {
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      centerEmptySection(el);
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var empties = el.getElementsByClassName(CENTER_EMPTY_CONTAINER_CSS_CLASS);
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0; i < empties.length; i++) {
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      centerEmptySection(empties[i]);
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Set the top of the given element to the top of the parent and set the
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * height to (bottom of document - top).
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Element} el Container holding the centered content.
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function centerEmptySection(el) {
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var parent = el.parentNode;
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var top = parent.offsetTop;
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var bottom = (
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        document.documentElement.offsetHeight - getButtonBarPadding());
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.style.height = (bottom - top) + 'px';
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.style.top = top + 'px';
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Finds the index of the panel specified by its prefix.
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} The string prefix for the panel.
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {number} The index of the panel.
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function getPaneIndex(panePrefix) {
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var pane = $(panePrefix + '_container');
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pane != null) {
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var index = panes.indexOf(pane);
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index >= 0)
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return index;
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Finds the index of the panel specified by location hash.
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {number} The index of the panel.
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function getPaneIndexFromHash() {
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var paneIndex;
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window.location.hash == '#bookmarks') {
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paneIndex = getPaneIndex('bookmarks');
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (window.location.hash == '#bookmark_shortcut') {
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paneIndex = getPaneIndex('bookmarks');
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (window.location.hash == '#most_visited') {
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paneIndex = getPaneIndex('most_visited');
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (window.location.hash == '#open_tabs') {
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paneIndex = getPaneIndex('open_tabs');
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (window.location.hash == '#incognito') {
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paneIndex = getPaneIndex('incognito');
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Couldn't find a good section
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paneIndex = -1;
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return paneIndex;
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Selects a pane from the top level list (Most Visited, Bookmarks, etc...).
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} paneIndex The index of the pane to be selected.
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {boolean} Whether the selected pane has changed.
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function scrollToPane(paneIndex) {
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var pane = panes[paneIndex];
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pane == currentPane)
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var newHash = '#' + sectionPrefixes[paneIndex];
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If updated hash matches the current one in the URL, we need to call
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // updatePaneOnHash directly as updating the hash to the same value will
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not trigger the 'hashchange' event.
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bookmarkShortcutMode || newHash == document.location.hash)
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updatePaneOnHash();
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    computeDynamicLayout();
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promoUpdateImpressions(sectionPrefixes[paneIndex]);
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the pane based on the current hash.
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updatePaneOnHash() {
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var paneIndex = getPaneIndexFromHash();
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var pane = panes[paneIndex];
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (currentPane)
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      currentPane.classList.remove('selected');
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pane.classList.add('selected');
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    currentPane = pane;
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    currentPaneIndex = paneIndex;
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    document.body.scrollTop = 0;
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var panelPrefix = sectionPrefixes[paneIndex];
2161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var title = templateData[panelPrefix + '_document_title'];
2162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!title)
2163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      title = templateData['title'];
2164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    document.title = title;
2165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sendNTPTitleLoadedNotification();
2167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO (dtrainor): Could potentially add logic to reset the bookmark state
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if they are moving to that pane.  This logic was in there before, but
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // was removed due to the fact that we have to go to this pane as part of
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the history navigation.
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Adds a top level section to the NTP.
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} panelPrefix The prefix of the element IDs corresponding
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     to the container of the content.
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {boolean=} opt_canBeDefault Whether this section can be marked as
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     the default starting point for subsequent instances of the NTP.  The
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     default value for this is true.
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function addMainSection(panelPrefix) {
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var paneEl = $(panelPrefix + '_container');
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var paneIndex = panes.push(paneEl) - 1;
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sectionPrefixes.push(panelPrefix);
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Handles the dynamic layout of the components on the new tab page.  Only
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * layouts that require calculation based on the screen size should go in
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * this function as it will be called during all resize changes
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * (orientation, keyword being displayed).
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function computeDynamicLayout() {
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update the scrolling titles to ensure they are not in a now invalid
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // scroll position.
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var titleScrollers =
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        document.getElementsByClassName('section-title-wrapper');
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0, len = titleScrollers.length; i < len; i++) {
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var titleEl =
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          titleScrollers[i].getElementsByClassName('section-title')[0];
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handleTitleScroll(
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          titleScrollers[i],
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          titleEl.offsetLeft);
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updateMostVisitedStyle();
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updateMostVisitedHeight();
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The centering of the 'recently closed' section is different depending on
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * the orientation of the device.  In landscape, it should be left-aligned
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * with the 'most used' section.  In portrait, it should be centered in the
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * screen.
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updateMostVisitedStyle() {
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isTablet()) {
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updateMostVisitedStyleTablet();
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updateMostVisitedStylePhone();
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the style of the most visited pane for the phone.
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updateMostVisitedStylePhone() {
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var mostVisitedList = $('most_visited_list');
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var childEl = mostVisitedList.firstChild;
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!childEl)
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 'natural' height and width of the thumbnail
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var thumbHeight = 72;
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var thumbWidth = 108;
2237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    var labelHeight = 25;
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var labelWidth = thumbWidth + 20;
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var labelLeft = (thumbWidth - labelWidth) / 2;
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var itemHeight = thumbHeight + labelHeight;
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // default vertical margin between items
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var itemMarginTop = 0;
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var itemMarginBottom = 0;
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var itemMarginLeft = 20;
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var itemMarginRight = 20;
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var listHeight = 0;
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var screenHeight =
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        document.documentElement.offsetHeight -
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        getButtonBarPadding();
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isPortrait()) {
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mostVisitedList.setAttribute(GRID_COLUMNS, '2');
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listHeight = screenHeight * .85;
2257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // Ensure that listHeight is not too small and not too big.
2258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      listHeight = Math.max(listHeight, (itemHeight * 3) + 20);
2259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      listHeight = Math.min(listHeight, 420);
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Size for 3 rows (4 gutters)
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      itemMarginTop = (listHeight - (itemHeight * 3)) / 4;
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mostVisitedList.setAttribute(GRID_COLUMNS, '3');
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listHeight = screenHeight;
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the screen height is less than targetHeight, scale the size of the
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // thumbnails such that the margin between the thumbnails remains
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // constant.
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var targetHeight = 220;
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (screenHeight < targetHeight) {
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var targetRemainder = targetHeight - 2 * (thumbHeight + labelHeight);
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var scale = (screenHeight - 2 * labelHeight -
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            targetRemainder) / (2 * thumbHeight);
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // update values based on scale
2275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        thumbWidth = Math.round(thumbWidth * scale);
2276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        thumbHeight = Math.round(thumbHeight * scale);
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        labelWidth = thumbWidth + 20;
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        itemHeight = thumbHeight + labelHeight;
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // scale the vertical margin such that the items fit perfectly on the
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // screen
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var remainder = screenHeight - (2 * itemHeight);
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var margin = (remainder / 2);
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margin = margin > 24 ? 24 : margin;
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      itemMarginTop = Math.round(margin / 2);
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      itemMarginBottom = Math.round(margin - itemMarginTop);
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mostVisitedList.style.minHeight = listHeight + 'px';
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] .thumbnail-cell',
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'height', itemHeight + 'px');
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] #most_visited_list .thumbnail',
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'height', thumbHeight + 'px');
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] #most_visited_list .thumbnail',
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'width', thumbWidth + 'px');
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule(
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'body[device="phone"] #most_visited_list .thumbnail-container',
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'height', thumbHeight + 'px');
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule(
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'body[device="phone"] #most_visited_list .thumbnail-container',
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'width', thumbWidth + 'px');
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] #most_visited_list .title',
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'width', labelWidth + 'px');
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] #most_visited_list .title',
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'left', labelLeft + 'px');
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] #most_visited_list .inner-border',
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'height', thumbHeight - 2 + 'px');
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] #most_visited_list .inner-border',
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'width', thumbWidth - 2 + 'px');
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] .thumbnail-cell',
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'margin-left', itemMarginLeft + 'px');
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] .thumbnail-cell',
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'margin-right', itemMarginRight + 'px');
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] .thumbnail-cell',
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'margin-top', itemMarginTop + 'px');
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modifyCssRule('body[device="phone"] .thumbnail-cell',
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'margin-bottom', itemMarginBottom + 'px');
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    centerChildGrids($('most_visited_container'));
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Updates the style of the most visited pane for the tablet.
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updateMostVisitedStyleTablet() {
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function setCenterIconGrid(el, set) {
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (set) {
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.classList.add(GRID_CENTER_CSS_CLASS);
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.classList.remove(GRID_CENTER_CSS_CLASS);
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.style.paddingLeft = '0px';
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        el.style.paddingRight = '0px';
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var isPortrait = document.documentElement.offsetWidth <
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        document.documentElement.offsetHeight;
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var mostVisitedContainer = $('most_visited_container');
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var mostVisitedList = $('most_visited_list');
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var recentlyClosedContainer = $('recently_closed_container');
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var recentlyClosedList = $('recently_closed_list');
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setCenterIconGrid(mostVisitedContainer, !isPortrait);
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setCenterIconGrid(mostVisitedList, isPortrait);
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setCenterIconGrid(recentlyClosedContainer, isPortrait);
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isPortrait) {
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recentlyClosedList.classList.add(GRID_CSS_CLASS);
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recentlyClosedList.classList.remove(GRID_CSS_CLASS);
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make the recently closed list visually left align with the most recently
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // closed items in landscape mode.  It will be reset by the grid centering
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in portrait mode.
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!isPortrait)
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recentlyClosedContainer.style.paddingLeft = '14px';
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * This handles updating some of the spacing to make the 'recently closed'
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * section appear at the bottom of the page.
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updateMostVisitedHeight() {
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!isTablet())
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subtract away height of button bar
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var windowHeight = document.documentElement.offsetHeight;
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var padding = parseInt(window.getComputedStyle(document.body)
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .getPropertyValue('padding-bottom'));
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $('most_visited_container').style.minHeight =
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (windowHeight - padding) + 'px';
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called by the native toolbar to open a different section. This handles
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * updating the hash url which in turns makes a history entry.
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} section The section to switch to.
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var openSection = function(section) {
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!scrollToPane(getPaneIndex(section)))
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update the url so the native toolbar knows the pane has changed and
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to create a history entry.
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    document.location.hash = '#' + section;
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /////////////////////////////////////////////////////////////////////////////
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NTP Scoped Window Event Listeners.
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /////////////////////////////////////////////////////////////////////////////
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Handles history on pop state changes.
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function onPopStateHandler(event) {
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event.state != null) {
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var evtState = event.state;
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Navigate back to the previously selected panel and ensure the same
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // bookmarks are loaded.
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var selectedPaneIndex = evtState.selectedPaneIndex == undefined ?
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          0 : evtState.selectedPaneIndex;
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scrollToPane(selectedPaneIndex);
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setCurrentBookmarkFolderData(evtState.folderId);
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // When loading the page, replace the default state with one that
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // specifies the default panel loaded via localStorage as well as the
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // default bookmark folder.
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      history.replaceState(
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {folderId: bookmarkFolderId, selectedPaneIndex: currentPaneIndex},
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          null, null);
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Handles window resize events.
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function windowResizeHandler() {
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Scroll to the current pane to refactor all the margins and offset.
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrollToPane(currentPaneIndex);
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    computeDynamicLayout();
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Center the padding for each of the grid views.
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    centerChildGrids(document);
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    centerEmptySections(document);
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * We implement the context menu ourselves.
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function contextMenuHandler(evt) {
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var section = SectionType.UNKNOWN;
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contextMenuUrl = null;
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contextMenuItem = null;
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The node with a menu have been tagged with their section and url.
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Let's find these tags.
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var node = evt.target;
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (node) {
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (section == SectionType.UNKNOWN &&
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          node.getAttribute &&
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          node.getAttribute(SECTION_KEY) != null) {
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        section = node.getAttribute(SECTION_KEY);
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (contextMenuUrl != null)
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (contextMenuUrl == null) {
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contextMenuUrl = node.getAttribute(CONTEXT_MENU_URL_KEY);
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contextMenuItem = node.contextMenuItem;
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (section != SectionType.UNKNOWN)
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node = node.parentNode;
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var menuOptions;
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (section == SectionType.BOOKMARKS &&
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !contextMenuItem.folder && !isIncognito) {
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menuOptions = [
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.BOOKMARK_OPEN_IN_NEW_TAB,
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementopeninnewtab
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ]
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
24669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      if (isIncognitoEnabled) {
24679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        menuOptions.push([
24689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch          ContextMenuItemIds.BOOKMARK_OPEN_IN_INCOGNITO_TAB,
24699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch          templateData.elementopeninincognitotab
24709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        ]);
24719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      }
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (contextMenuItem.editable) {
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        menuOptions.push(
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            [ContextMenuItemIds.BOOKMARK_EDIT, templateData.bookmarkedit],
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            [ContextMenuItemIds.BOOKMARK_DELETE, templateData.bookmarkdelete]);
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (contextMenuUrl.search('chrome://') == -1 &&
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          contextMenuUrl.search('about://') == -1) {
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        menuOptions.push([
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.BOOKMARK_SHORTCUT,
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.bookmarkshortcut
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ]);
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (section == SectionType.BOOKMARKS &&
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               !contextMenuItem.folder &&
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               isIncognito) {
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menuOptions = [
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.BOOKMARK_OPEN_IN_INCOGNITO_TAB,
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementopeninincognitotab
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ]
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (section == SectionType.BOOKMARKS &&
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               contextMenuItem.folder &&
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               contextMenuItem.editable &&
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               !isIncognito) {
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menuOptions = [
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [ContextMenuItemIds.BOOKMARK_EDIT, templateData.editfolder],
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [ContextMenuItemIds.BOOKMARK_DELETE, templateData.deletefolder]
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (section == SectionType.MOST_VISITED) {
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menuOptions = [
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.MOST_VISITED_OPEN_IN_NEW_TAB,
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementopeninnewtab
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ],
25079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      ];
25089ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      if (isIncognitoEnabled) {
25099ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        menuOptions.push([
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.MOST_VISITED_OPEN_IN_INCOGNITO_TAB,
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementopeninincognitotab
25129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        ]);
25139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      }
25149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      menuOptions.push(
25159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        [ContextMenuItemIds.MOST_VISITED_REMOVE, templateData.elementremove]);
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (section == SectionType.RECENTLY_CLOSED) {
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menuOptions = [
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.RECENTLY_CLOSED_OPEN_IN_NEW_TAB,
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementopeninnewtab
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ],
25229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      ];
25239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      if (isIncognitoEnabled) {
25249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        menuOptions.push([
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.RECENTLY_CLOSED_OPEN_IN_INCOGNITO_TAB,
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementopeninincognitotab
25279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        ]);
25289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      }
25299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      menuOptions.push(
25309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        [ContextMenuItemIds.RECENTLY_CLOSED_REMOVE, templateData.removeall]);
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (section == SectionType.FOREIGN_SESSION_HEADER) {
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menuOptions = [
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.FOREIGN_SESSIONS_REMOVE,
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementremove
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ]
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (section == SectionType.PROMO_VC_SESSION_HEADER) {
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menuOptions = [
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContextMenuItemIds.PROMO_VC_SESSION_REMOVE,
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          templateData.elementremove
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ]
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (menuOptions)
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome.send('showContextMenu', menuOptions);
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return an object with all the exports
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return {
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmarks: bookmarks,
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmarkChanged: bookmarkChanged,
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clearPromotions: clearPromotions,
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    init: init,
25599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    setIncognitoEnabled: setIncognitoEnabled,
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    onCustomMenuSelected: onCustomMenuSelected,
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    openSection: openSection,
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setFaviconDominantColor: setFaviconDominantColor,
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setForeignSessions: setForeignSessions,
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setIncognitoMode: setIncognitoMode,
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setMostVisitedPages: setMostVisitedPages,
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setPromotions: setPromotions,
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setRecentlyClosedTabs: setRecentlyClosedTabs,
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setSyncEnabled: setSyncEnabled,
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snapshots: snapshots
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//Utility Functions.
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A best effort approach for checking simple data object equality.
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {?} val1 The first value to check equality for.
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {?} val2 The second value to check equality for.
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether the two objects are equal(ish).
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function equals(val1, val2) {
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (typeof val1 != 'object' || typeof val2 != 'object')
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return val1 === val2;
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Object and array equality checks.
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var keyCountVal1 = 0;
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var key in val1) {
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(key in val2) || !equals(val1[key], val2[key]))
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyCountVal1++;
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var keyCountVal2 = 0;
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var key in val2)
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyCountVal2++;
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (keyCountVal1 != keyCountVal2)
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alias for document.getElementById.
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} id The ID of the element to find.
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLElement} The found element or null if not found.
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function $(id) {
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return document.getElementById(id);
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether the device is currently in portrait mode.
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function isPortrait() {
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return document.documentElement.offsetWidth <
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.documentElement.offsetHeight;
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Determine if the page should be formatted for tablets.
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} true if the device is a tablet, false otherwise.
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function isTablet() {
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return document.body.getAttribute('device') == 'tablet';
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Determine if the page should be formatted for phones.
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} true if the device is a phone, false otherwise.
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function isPhone() {
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return document.body.getAttribute('device') == 'phone';
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Get the page X coordinate of a touch event.
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {TouchEvent} evt The touch event triggered by the browser.
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The page X coordinate of the touch event.
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function getTouchEventX(evt) {
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (evt.touches[0] || e.changedTouches[0]).pageX;
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Get the page Y coordinate of a touch event.
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {TouchEvent} evt The touch event triggered by the browser.
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The page Y coordinate of the touch event.
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function getTouchEventY(evt) {
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (evt.touches[0] || e.changedTouches[0]).pageY;
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Element} el The item to get the width of.
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} excludeMargin If true, exclude the width of the margin.
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The total width of a given item.
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function getItemWidth(el, excludeMargin) {
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var elStyle = window.getComputedStyle(el);
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var width = el.offsetWidth;
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!width || width == 0) {
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width = parseInt(elStyle.getPropertyValue('width'));
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width +=
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parseInt(elStyle.getPropertyValue('border-left-width')) +
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parseInt(elStyle.getPropertyValue('border-right-width'));
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width +=
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parseInt(elStyle.getPropertyValue('padding-left')) +
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parseInt(elStyle.getPropertyValue('padding-right'));
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!excludeMargin) {
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width += parseInt(elStyle.getPropertyValue('margin-left')) +
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parseInt(elStyle.getPropertyValue('margin-right'));
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return width;
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The padding height of the body due to the button bar
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function getButtonBarPadding() {
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var body = document.getElementsByTagName('body')[0];
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var style = window.getComputedStyle(body);
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return parseInt(style.getPropertyValue('padding-bottom'));
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Modify a css rule
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} selector The selector for the rule (passed to findCssRule())
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} property The property to update
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} value The value to update the property to
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} true if the rule was updated, false otherwise.
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function modifyCssRule(selector, property, value) {
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var rule = findCssRule(selector);
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!rule)
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule.style[property] = value;
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find a particular CSS rule.  The stylesheets attached to the document
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are traversed in reverse order.  The rules in each stylesheet are also
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * traversed in reverse order.  The first rule found to match the selector
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is returned.
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} selector The selector for the rule.
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Object} The rule if one was found, null otherwise
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function findCssRule(selector) {
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var styleSheets = document.styleSheets;
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = styleSheets.length - 1; i >= 0; i--) {
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var styleSheet = styleSheets[i];
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var rules = styleSheet.cssRules;
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rules == null)
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (j = rules.length - 1; j >= 0; j--) {
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rules[j].selectorText == selector)
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return rules[j];
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NTP Entry point.
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles initializing the UI when the page has finished loading.
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)window.addEventListener('DOMContentLoaded', function(evt) {
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp.init();
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  $('content-area').style.display = 'block';
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
2734