diff options
author | mad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-15 23:44:53 +0000 |
---|---|---|
committer | mad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-15 23:44:53 +0000 |
commit | a04e82bfb87e06462b018ab05053319e41c1db00 (patch) | |
tree | 9db9f906ce8d995483487466fd174680848abdac /chrome | |
parent | 70fe277044e7768cfe91375749b33cb94ae00981 (diff) | |
download | chromium_src-a04e82bfb87e06462b018ab05053319e41c1db00.zip chromium_src-a04e82bfb87e06462b018ab05053319e41c1db00.tar.gz chromium_src-a04e82bfb87e06462b018ab05053319e41c1db00.tar.bz2 |
Implement separate area of the history page for full list of other devices.
BUG=154655
TEST=Open the history page and play with it...
Review URL: https://chromiumcodereview.appspot.com/12390024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188507 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/generated_resources.grd | 4 | ||||
-rw-r--r-- | chrome/browser/browser_resources.grd | 1 | ||||
-rw-r--r-- | chrome/browser/resources/history/history.html | 13 | ||||
-rw-r--r-- | chrome/browser/resources/history/other_devices.css | 84 | ||||
-rw-r--r-- | chrome/browser/resources/history/other_devices.js | 525 | ||||
-rw-r--r-- | chrome/browser/resources/uber/uber_shared.css | 4 | ||||
-rw-r--r-- | chrome/browser/ui/webui/history_ui.cc | 41 | ||||
-rw-r--r-- | chrome/browser/ui/webui/history_ui.h | 3 |
8 files changed, 657 insertions, 18 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 3483a18..698e615 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -11279,6 +11279,10 @@ experiment id: "<ph name="EXPERIMENT_ID">$5<ex>ar1</ex></ph>" desc="In the 'Other Sessions' menu on the New Tab Page, the label for the command to open all tabs and windows from a session."> Open all </message> + <message name="IDS_OTHER_DEVICES_X_MORE" + desc="In the 'Other Sessions' section of the history page, the label for showing that X more tabs are available for a session."> + <ph name="NUM_TABS_MORE">$1<ex>42</ex></ph> more... + </message> <message name="IDS_NEW_TAB_OTHER_SESSIONS_COLLAPSE_SESSION" desc="In the 'Other Sessions' menu on the New Tab Page, the label for the command to collapse (hide) the list of windows and tabs in a session."> Collapse list diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index efcdf9f..3e4c478 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -122,6 +122,7 @@ <include name="IDR_HELP_JS" file="resources\help\help.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_HISTORY_HTML" file="resources\history\history.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_HISTORY_JS" file="resources\history\history.js" flattenhtml="true" type="BINDATA" /> + <include name="IDR_OTHER_DEVICES_JS" file="resources\history\other_devices.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_INSPECT_CSS" file="resources\inspect\inspect.css" flattenhtml="true" type="BINDATA" /> <include name="IDR_INSPECT_HTML" file="resources\inspect\inspect.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_INSPECT_JS" file="resources\inspect\inspect.js" flattenhtml="true" type="BINDATA" /> diff --git a/chrome/browser/resources/history/history.html b/chrome/browser/resources/history/history.html index a4124fa..b93dc11 100644 --- a/chrome/browser/resources/history/history.html +++ b/chrome/browser/resources/history/history.html @@ -16,6 +16,9 @@ <link rel="stylesheet" href="../uber/uber_shared.css"> </if> <link rel="stylesheet" href="history.css"> +<if expr="not pp_ifdef('android')"> +<link rel="stylesheet" href="other_devices.css"> +</if> <script src="chrome://resources/js/event_tracker.js"></script> <script src="chrome://resources/js/cr.js"></script> @@ -25,10 +28,17 @@ <script src="chrome://resources/js/cr/ui/menu.js"></script> <script src="chrome://resources/js/cr/ui/position_util.js"></script> <script src="chrome://resources/js/cr/ui/menu_button.js"></script> +<script src="chrome://resources/js/cr/ui/context_menu_button.js"></script> +<script src="chrome://resources/js/cr/event_target.js"></script> +<script src="chrome://resources/js/cr/ui/context_menu_handler.js"></script> + <script src="chrome://resources/js/load_time_data.js"></script> <script src="chrome://resources/js/util.js"></script> <script src="chrome://history-frame/history.js"></script> +<if expr="not pp_ifdef('android')"> +<script src="chrome://history-frame/other_devices.js"></script> +</if> </head> @@ -74,6 +84,9 @@ </label> </div> </div> +<if expr="not pp_ifdef('android')"> + <div id="other-devices" class="other-devices"></div> +</if> <div id="editing-controls"> <button id="clear-browsing-data" i18n-content="clearAllHistory"></button> <button id="remove-selected" disabled="disabled" diff --git a/chrome/browser/resources/history/other_devices.css b/chrome/browser/resources/history/other_devices.css new file mode 100644 index 0000000..4163e12 --- /dev/null +++ b/chrome/browser/resources/history/other_devices.css @@ -0,0 +1,84 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +.other-devices { + width: 738px; /* Same as body.uber-frame header max-width */ +} + +.devices-row { + float: left; +} + +.device { + float: left; + width: 246px; /* 1/3 of body.uber-frame header max-width */ +} + +.device h3 { + font-weight: bold; + margin-top: 8px; +} + +.device-timestamp { + color: rgb(151, 156, 160); + font-weight: normal; +} + +.device-tab-entry { + -webkit-margin-end: 8px; + -webkit-margin-start: 0; + -webkit-padding-end: 0; + -webkit-padding-start: 22px; + background: no-repeat 0 50%; + background-color: transparent !important; + background-size: 16px 16px; + box-sizing: border-box; + display: block; + line-height: 1.5em; + margin-bottom: 0.5em; + margin-top: 0.5em; + max-width: 450px; + outline: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.device-tab-entry:not(:hover), +.device-tab-entry:not(:focus) { + text-decoration: none; +} + +.device-tab-entry:hover, +.device-tab-entry:focus { + text-decoration: underline; +} + +.device-tab-entry:active, +.device-tab-entry:visited, +.device-tab-entry:link { + color: rgb(48, 57, 66); + text-decoration: none; +} + +.device-show-more-tabs:not(:hover), +.device-show-more-tabs:not(:focus) { + text-decoration: none; +} + +.device-show-more-tabs:hover, +.device-show-more-tabs:focus { + text-decoration: underline; +} + +.device-show-more-tabs, +.device-show-more-tabs:active, +.device-show-more-tabs:visited, +.device-show-more-tabs:link { + color: rgb(151, 156, 160); +} + +.other-devices-bottom { + clear: both; +} diff --git a/chrome/browser/resources/history/other_devices.js b/chrome/browser/resources/history/other_devices.js new file mode 100644 index 0000000..a9eecf3 --- /dev/null +++ b/chrome/browser/resources/history/other_devices.js @@ -0,0 +1,525 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview The section of the history page that shows tabs from sessions + on other devices. + */ + +/////////////////////////////////////////////////////////////////////////////// +// Globals: +/** @const */ var MAX_NUM_COLUMNS = 3; +/** @const */ var NB_ENTRIES_FIRST_ROW_COLUMN = 6; +/** @const */ var NB_ENTRIES_OTHER_ROWS_COLUMN = 0; + +// Histogram buckets for UMA tracking of menu usage. +// Using the same values as the Other Devices button in the NTP. +/** @const */ var HISTOGRAM_EVENT = { + INITIALIZED: 0, + SHOW_MENU: 1, + LINK_CLICKED: 2, + LINK_RIGHT_CLICKED: 3, + SESSION_NAME_RIGHT_CLICKED: 4, + SHOW_SESSION_MENU: 5, + COLLAPSE_SESSION: 6, + EXPAND_SESSION: 7, + OPEN_ALL: 8, + LIMIT: 9 // Should always be the last one. +}; + +/** + * Record an event in the UMA histogram. + * @param {number} eventId The id of the event to be recorded. + * @private + */ +function recordUmaEvent_(eventId) { + chrome.send('metricsHandler:recordInHistogram', + ['HistoryPage.OtherDevicesMenu', eventId, HISTOGRAM_EVENT.LIMIT]); +} + +/////////////////////////////////////////////////////////////////////////////// +// DeviceContextMenuController: + +/** + * Controller for the context menu for device names in the list of sessions. + * This class is designed to be used as a singleton. Also copied from existing + * other devices button in NTP. + * TODO(mad): Should we extract/reuse/share with ntp4/other_sessions.js? + * + * @constructor + */ +function DeviceContextMenuController() { + this.__proto__ = DeviceContextMenuController.prototype; + this.initialize(); +} +cr.addSingletonGetter(DeviceContextMenuController); + +// DeviceContextMenuController, Public: --------------------------------------- + +/** + * Initialize the context menu for device names in the list of sessions. + */ +DeviceContextMenuController.prototype.initialize = function() { + var menu = new cr.ui.Menu; + cr.ui.decorate(menu, cr.ui.Menu); + this.menu = menu; + this.collapseItem_ = this.appendMenuItem_('collapseSessionMenuItemText'); + this.collapseItem_.addEventListener('activate', + this.onCollapseOrExpand_.bind(this)); + this.expandItem_ = this.appendMenuItem_('expandSessionMenuItemText'); + this.expandItem_.addEventListener('activate', + this.onCollapseOrExpand_.bind(this)); + this.openAllItem_ = this.appendMenuItem_('restoreSessionMenuItemText'); + this.openAllItem_.addEventListener('activate', + this.onOpenAll_.bind(this)); +}; + +/** + * Set the session data for the session the context menu was invoked on. + * This should never be called when the menu is visible. + * @param {Object} session The model object for the session. + */ +DeviceContextMenuController.prototype.setSession = function(session) { + this.session_ = session; + this.updateMenuItems_(); +}; + +// DeviceContextMenuController, Private: -------------------------------------- + +/** + * Appends a menu item to |this.menu|. + * @param {string} textId The ID for the localized string that acts as + * the item's label. + * @return {Element} The button used for a given menu option. + * @private + */ +DeviceContextMenuController.prototype.appendMenuItem_ = function(textId) { + var button = document.createElement('button'); + this.menu.appendChild(button); + cr.ui.decorate(button, cr.ui.MenuItem); + button.textContent = loadTimeData.getString(textId); + return button; +}; + +/** + * Handler for the 'Collapse' and 'Expand' menu items. + * @param {Event} e The activation event. + * @private + */ +DeviceContextMenuController.prototype.onCollapseOrExpand_ = function(e) { + this.session_.collapsed = !this.session_.collapsed; + this.updateMenuItems_(); + chrome.send('setForeignSessionCollapsed', + [this.session_.tag, this.session_.collapsed]); + chrome.send('getForeignSessions'); // Refresh the list. + + var eventId = this.session_.collapsed ? + HISTOGRAM_EVENT.COLLAPSE_SESSION : HISTOGRAM_EVENT.EXPAND_SESSION; + recordUmaEvent_(eventId); +}; + +/** + * Handler for the 'Open all' menu item. + * @param {Event} e The activation event. + * @private + */ +DeviceContextMenuController.prototype.onOpenAll_ = function(e) { + chrome.send('openForeignSession', [this.session_.tag]); + recordUmaEvent_(HISTOGRAM_EVENT.OPEN_ALL); +}; + +/** + * Set the visibility of the Expand/Collapse menu items based on the state + * of the session that this menu is currently associated with. + * @private + */ +DeviceContextMenuController.prototype.updateMenuItems_ = function() { + this.collapseItem_.hidden = this.session_.collapsed; + this.expandItem_.hidden = !this.session_.collapsed; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Device: + +/** + * Class to hold all the information about a device entry and generate a DOM + * node for it. + * @param {Object} session An object containing the device's session data. + * @param {DevicesView} view The view object this entry belongs to. + * @constructor + */ +function Device(session, view) { + this.view_ = view; + this.session_ = session; + this.searchText_ = view.getSearchText(); +} + +// Device, Public: ------------------------------------------------------------ + +/** + * Get the DOM node to display this device. + * @param {int} maxNumTabs The maximum number of tabs to display. + * @param {int} row The row in which this device is displayed. + * @return {Object} A DOM node to draw the device. + */ +Device.prototype.getDOMNode = function(maxNumTabs, row) { + var deviceDiv = createElementWithClassName('div', 'device'); + this.row_ = row; + if (!this.session_) + return deviceDiv; + + // Name heading + var heading = document.createElement('h3'); + heading.textContent = this.session_.name; + heading.sessionData_ = this.session_; + deviceDiv.appendChild(heading); + + // Keep track of the drop down that triggered the menu, so we know + // which element to apply the command to. + var session = this.session_; + function handleDropDownFocus(e) { + DeviceContextMenuController.getInstance().setSession(session); + } + heading.addEventListener('contextmenu', handleDropDownFocus); + + var dropDownButton = new cr.ui.ContextMenuButton; + dropDownButton.classList.add('drop-down'); + dropDownButton.addEventListener('mousedown', handleDropDownFocus); + dropDownButton.addEventListener('focus', handleDropDownFocus); + heading.appendChild(dropDownButton); + + var timeSpan = createElementWithClassName('div', 'device-timestamp'); + timeSpan.textContent = this.session_.modifiedTime; + heading.appendChild(timeSpan); + + cr.ui.contextMenuHandler.setContextMenu( + heading, DeviceContextMenuController.getInstance().menu); + if (!this.session_.collapsed) + deviceDiv.appendChild(this.createSessionContents_(maxNumTabs)); + + return deviceDiv; +}; + +/** + * Marks tabs as hidden or not in our session based on the given searchText. + * @param {string} searchText The search text used to filter the content. + */ +Device.prototype.setSearchText = function(searchText) { + this.searchText_ = searchText.toLowerCase(); + for (var i = 0; i < this.session_.windows.length; i++) { + var win = this.session_.windows[i]; + var foundMatch = false; + for (var j = 0; j < win.tabs.length; j++) { + var tab = win.tabs[j]; + if (tab.title.toLowerCase().indexOf(this.searchText_) != -1) { + foundMatch = true; + tab.hidden = false; + } else { + tab.hidden = true; + } + } + win.hidden = !foundMatch; + } +}; + +// Device, Private ------------------------------------------------------------ + +/** + * Create the DOM tree representing the tabs and windows of this device. + * @param {int} maxNumTabs The maximum number of tabs to display. + * @return {Element} A single div containing the list of tabs & windows. + * @private + */ +Device.prototype.createSessionContents_ = function(maxNumTabs) { + var contents = createElementWithClassName('div', 'device-contents'); + + var sessionTag = this.session_.tag; + var numTabsShown = 0; + var numTabsHidden = 0; + for (var i = 0; i < this.session_.windows.length; i++) { + var win = this.session_.windows[i]; + if (win.hidden) + continue; + + // Show a separator between multiple windows in the same session. + if (i > 0 && numTabsShown < maxNumTabs) + contents.appendChild(document.createElement('hr')); + + for (var j = 0; j < win.tabs.length; j++) { + var tab = win.tabs[j]; + if (tab.hidden) + continue; + + if (numTabsShown < maxNumTabs) { + numTabsShown++; + var a = createElementWithClassName('a', 'device-tab-entry'); + a.href = tab.url; + a.style.backgroundImage = + getFaviconImageSet(tab.url, 16, /* session-favicon */ true); + this.addHighlightedText_(a, tab.title); + // Add a tooltip, since it might be ellipsized. The ones that are not + // necessary will be removed once added to the document, so we can + // compute sizes. + a.title = tab.title; + a.addEventListener('click', function(e) { + recordUmaEvent_(HISTOGRAM_EVENT.LINK_CLICKED); + chrome.send( + 'openForeignSession', + [sessionTag, String(win.sessionId), String(tab.sessionId), + e.button, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey]); + e.preventDefault(); + }); + contents.appendChild(a); + } else { + numTabsHidden++; + } + } + } + + if (numTabsHidden > 0) { + var a = createElementWithClassName('a', 'device-show-more-tabs'); + a.addEventListener('click', this.view_.increaseRowHeight.bind( + this.view_, this.row_, numTabsHidden)); + var xMore = loadTimeData.getString('xMore'); + a.appendChild(document.createTextNode(xMore.replace('$1', numTabsHidden))); + contents.appendChild(a); + } + + return contents; +}; + +/** + * Add child text nodes to a node such that occurrences of this.searchText_ are + * highlighted. + * @param {Node} node The node under which new text nodes will be made as + * children. + * @param {string} content Text to be added beneath |node| as one or more + * text nodes. + * @private + */ +Device.prototype.addHighlightedText_ = function(node, content) { + var endOfPreviousMatch = 0; + if (this.searchText_) { + var lowerContent = content.toLowerCase(); + var searchTextLenght = this.searchText_.length; + var newMatch = lowerContent.indexOf(this.searchText_, 0); + while (newMatch != -1) { + if (newMatch > endOfPreviousMatch) { + node.appendChild(document.createTextNode( + content.slice(endOfPreviousMatch, newMatch))); + } + endOfPreviousMatch = newMatch + searchTextLenght; + // Mark the highlighted text in bold. + var b = document.createElement('b'); + b.textContent = content.substring(newMatch, endOfPreviousMatch); + node.appendChild(b); + newMatch = lowerContent.indexOf(this.searchText_, endOfPreviousMatch); + } + } + if (endOfPreviousMatch < content.length) { + node.appendChild(document.createTextNode( + content.slice(endOfPreviousMatch))); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// DevicesView: + +/** + * Functions and state for populating the page with HTML. + * @constructor + */ +function DevicesView() { + this.devices_ = []; // List of individual devices. + this.resultDiv_ = $('other-devices'); + this.searchText_ = ''; + this.rowHeights_ = [NB_ENTRIES_FIRST_ROW_COLUMN]; + this.updateSignInState(loadTimeData.getBoolean('isUserSignedIn')); + recordUmaEvent_(HISTOGRAM_EVENT.INITIALIZED); +} + +// DevicesView, public: ------------------------------------------------------- + +/** + * Updates our sign in state by clearing the view is not signed in or sending + * a request to get the data to display otherwise. + * @param {boolean} signedIn Whether the user is signed in or not. + */ +DevicesView.prototype.updateSignInState = function(signedIn) { + if (signedIn) + chrome.send('getForeignSessions'); + else + this.clearDOM(); +}; + +/** + * Resets the view sessions. + * @param {Object} sessionList The sessions to add. + */ +DevicesView.prototype.setSessionList = function(sessionList) { + this.devices_ = []; + for (var i = 0; i < sessionList.length; i++) + this.devices_.push(new Device(sessionList[i], this)); + this.displayResults_(); +}; + + +/** + * Sets the current search text. + * @param {string} searchText The text to search. + */ +DevicesView.prototype.setSearchText = function(searchText) { + if (this.searchText_ != searchText) { + this.searchText_ = searchText; + for (var i = 0; i < this.devices_.length; i++) + this.devices_[i].setSearchText(searchText); + this.displayResults_(); + } +}; + +/** + * @return {string} The current search text. + */ +DevicesView.prototype.getSearchText = function() { + return this.searchText_; +}; + +/** + * Clears the DOM content of the view. + */ +DevicesView.prototype.clearDOM = function() { + while (this.resultDiv_.hasChildNodes()) { + this.resultDiv_.removeChild(this.resultDiv_.lastChild); + } +}; + +/** + * Increase the height of a row by the given amount. + * @param {int} row The row number. + * @param {int} height The extra height to add to the givent row. + */ +DevicesView.prototype.increaseRowHeight = function(row, height) { + for (var i = this.rowHeights_.length; i <= row; i++) + this.rowHeights_.push(NB_ENTRIES_OTHER_ROWS_COLUMN); + this.rowHeights_[row] += height; + this.displayResults_(); +}; + +// DevicesView, Private ------------------------------------------------------- + +/** + * Update the page with results. + * @private + */ +DevicesView.prototype.displayResults_ = function() { + this.clearDOM(); + var resultsFragment = document.createDocumentFragment(); + if (this.devices_.length == 0) + return; + + // We'll increase to 0 as we create the first row. + var rowIndex = -1; + // We need to access the last row and device when we get out of the loop. + var currentRowElement; + // This is only set when changing rows, yet used on all device columns. + var maxNumTabs; + for (var i = 0; i < this.devices_.length; i++) { + var device = this.devices_[i]; + // Should we start a new row? + if (i % MAX_NUM_COLUMNS == 0) { + if (currentRowElement) + resultsFragment.appendChild(currentRowElement); + currentRowElement = createElementWithClassName('div', 'devices-row'); + rowIndex++; + if (rowIndex < this.rowHeights_.length) + maxNumTabs = this.rowHeights_[rowIndex]; + else + maxNumTabs = 0; + } + + currentRowElement.appendChild(device.getDOMNode(maxNumTabs, rowIndex)); + } + if (currentRowElement) + resultsFragment.appendChild(currentRowElement); + + this.resultDiv_.appendChild(resultsFragment); + // Remove the tootltip on all lines that don't need it. It's easier to + // remove them here, after adding them all above, since we have the data + // handy above, but we don't have the width yet. Whereas here, we have the + // width, and the nodeValue could contain sub nodes for highlighting, which + // makes it harder to extract the text data here. + tabs = document.getElementsByClassName('device-tab-entry'); + for (var i = 0; i < tabs.length; i++) { + if (tabs[i].scrollWidth <= tabs[i].clientWidth) + tabs[i].title = ''; + } + + this.resultDiv_.appendChild( + createElementWithClassName('div', 'other-devices-bottom')); +}; + +// We must use this namespace to reuse the handler code for foreign session and +// login. +cr.define('ntp', function() { + 'use strict'; + + /** + * Sets the menu model data. An empty list means that either there are no + * foreign sessions, or tab sync is disabled for this profile. + * |isTabSyncEnabled| makes it possible to distinguish between the cases. + * + * @param {Array} sessionList Array of objects describing the sessions + * from other devices. + * @param {boolean} isTabSyncEnabled Is tab sync enabled for this profile? + */ + function setForeignSessions(sessionList, isTabSyncEnabled) { + // The other devices is shown iff tab sync is enabled. + if (isTabSyncEnabled) + devicesView.setSessionList(sessionList); + else + devicesView.clearDOM(); + } + + /** + * Called when this element is initialized, and from the new tab page when + * the user's signed in state changes, + * @param {string} header The first line of text (unused here). + * @param {string} subHeader The second line of text (unused here). + * @param {string} iconURL The url for the login status icon. If this is null + then the login status icon is hidden (unused here). + * @param {boolean} isUserSignedIn Is the user currently signed in? + */ + function updateSignInState(header, subHeader, iconURL, isUserSignedIn) { + if (devicesView) + devicesView.updateSignInState(isUserSignedIn); + } + + return { + setForeignSessions: setForeignSessions, + updateLogin: updateSignInState + }; +}); + +/////////////////////////////////////////////////////////////////////////////// +// Document Functions: +/** + * Window onload handler, sets up the other devices view. + */ +function load() { + devicesView = new DevicesView(); + + // Create the context menu that appears when the user right clicks + // on a device name or hit click on the button besides the device name + document.body.appendChild(DeviceContextMenuController.getInstance().menu); + + var doSearch = function(e) { + devicesView.setSearchText($('search-field').value); + }; + $('search-field').addEventListener('search', doSearch); + $('search-button').addEventListener('click', doSearch); +} + +// Add handlers to HTML elements. +document.addEventListener('DOMContentLoaded', load); diff --git a/chrome/browser/resources/uber/uber_shared.css b/chrome/browser/resources/uber/uber_shared.css index 34da968..64d2bbd 100644 --- a/chrome/browser/resources/uber/uber_shared.css +++ b/chrome/browser/resources/uber/uber_shared.css @@ -33,7 +33,9 @@ body.uber-frame header { /* <section>s in options currently amount to 638px total, broken up into * 600px max-width + 18px -webkit-padding-start + 20px -webkit-margin-end * so we mirror this value here so the headers match width and horizontal - * alignment when scrolling sideways. */ + * alignment when scrolling sideways. + * other-devices.css' .device width depends on this, please keep in sync. + */ max-width: 738px; min-width: 600px; position: fixed; diff --git a/chrome/browser/ui/webui/history_ui.cc b/chrome/browser/ui/webui/history_ui.cc index 13c89fb..b07e178 100644 --- a/chrome/browser/ui/webui/history_ui.cc +++ b/chrome/browser/ui/webui/history_ui.cc @@ -14,10 +14,9 @@ #include "base/memory/singleton.h" #include "base/message_loop.h" #include "base/metrics/histogram.h" +#include "base/prefs/pref_service.h" #include "base/string16.h" -#include "base/string_piece.h" #include "base/strings/string_number_conversions.h" -#include "base/threading/thread.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" @@ -29,30 +28,26 @@ #include "chrome/browser/history/history_types.h" #include "chrome/browser/history/web_history_service.h" #include "chrome/browser/history/web_history_service_factory.h" +#include "chrome/browser/instant/search.h" #include "chrome/browser/managed_mode/managed_mode_url_filter.h" #include "chrome/browser/managed_mode/managed_user_service.h" #include "chrome/browser/managed_mode/managed_user_service_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/webui/favicon_source.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" #include "chrome/common/time_format.h" #include "chrome/common/url_constants.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/url_data_source.h" -#include "content/public/browser/user_metrics.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "grit/browser_resources.h" -#include "grit/chromium_strings.h" #include "grit/generated_resources.h" -#include "grit/locale_settings.h" #include "grit/theme_resources.h" #include "net/base/escape.h" #include "sync/protocol/history_delete_directive_specifics.pb.h" @@ -62,13 +57,14 @@ #if defined(OS_ANDROID) #include "chrome/browser/ui/android/tab_model/tab_model.h" #include "chrome/browser/ui/android/tab_model/tab_model_list.h" +#else +#include "chrome/browser/ui/webui/ntp/foreign_session_handler.h" +#include "chrome/browser/ui/webui/ntp/ntp_login_handler.h" #endif -using content::UserMetricsAction; -using content::WebContents; - static const char kStringsJsFile[] = "strings.js"; static const char kHistoryJsFile[] = "history.js"; +static const char kOtherDevicesJsFile[] = "other_devices.js"; // The amount of time to wait for a response from the WebHistoryService. static const int kWebHistoryTimeoutSeconds = 3; @@ -97,6 +93,15 @@ const char kIncognitoModeShortcut[] = "(Shift+Ctrl+N)"; content::WebUIDataSource* CreateHistoryUIHTMLSource(Profile* profile) { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIHistoryFrameHost); + source->AddBoolean("isUserSignedIn", + !profile->GetPrefs()->GetString(prefs::kGoogleServicesUsername).empty()); + source->AddLocalizedString("collapseSessionMenuItemText", + IDS_NEW_TAB_OTHER_SESSIONS_COLLAPSE_SESSION); + source->AddLocalizedString("expandSessionMenuItemText", + IDS_NEW_TAB_OTHER_SESSIONS_EXPAND_SESSION); + source->AddLocalizedString("restoreSessionMenuItemText", + IDS_NEW_TAB_OTHER_SESSIONS_OPEN_ALL); + source->AddLocalizedString("xMore", IDS_OTHER_DEVICES_X_MORE); source->AddLocalizedString("loading", IDS_HISTORY_LOADING); source->AddLocalizedString("title", IDS_HISTORY_TITLE); source->AddLocalizedString("newest", IDS_HISTORY_NEWEST); @@ -148,6 +153,7 @@ content::WebUIDataSource* CreateHistoryUIHTMLSource(Profile* profile) { switches::kHistoryEnableGroupByDomain)); source->SetJsonPath(kStringsJsFile); source->AddResourcePath(kHistoryJsFile, IDR_HISTORY_JS); + source->AddResourcePath(kOtherDevicesJsFile, IDR_OTHER_DEVICES_JS); source->SetDefaultResource(IDR_HISTORY_HTML); source->SetUseJsonJSFormatV2(); source->DisableDenyXFrameOptions(); @@ -1085,10 +1091,17 @@ void BrowsingHistoryHandler::Observe( HistoryUI::HistoryUI(content::WebUI* web_ui) : WebUIController(web_ui) { web_ui->AddMessageHandler(new BrowsingHistoryHandler()); +// Android deals with foreign sessions differently. +#if !defined(OS_ANDROID) + if (chrome::search::IsInstantExtendedAPIEnabled()) { + web_ui->AddMessageHandler(new browser_sync::ForeignSessionHandler()); + web_ui->AddMessageHandler(new NTPLoginHandler()); + } +#endif // !defined(OS_ANDROID) + // Set up the chrome://history-frame/ source. - content::WebUIDataSource::Add( - Profile::FromWebUI(web_ui), - CreateHistoryUIHTMLSource(Profile::FromWebUI(web_ui))); + Profile* profile = Profile::FromWebUI(web_ui); + content::WebUIDataSource::Add(profile, CreateHistoryUIHTMLSource(profile)); } // static diff --git a/chrome/browser/ui/webui/history_ui.h b/chrome/browser/ui/webui/history_ui.h index b73b773..0d17f2a 100644 --- a/chrome/browser/ui/webui/history_ui.h +++ b/chrome/browser/ui/webui/history_ui.h @@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_UI_WEBUI_HISTORY_UI_H_ #define CHROME_BROWSER_UI_WEBUI_HISTORY_UI_H_ -#include <string> - #include "base/string16.h" #include "base/timer.h" #include "base/values.h" @@ -17,7 +15,6 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_message_handler.h" -#include "ui/base/layout.h" class BookmarkModel; class ManagedUserService; |