diff --git a/chrome/VERSION b/chrome/VERSION index dbc9ac2..1b425bc 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=57 MINOR=0 -BUILD=2967 +BUILD=2968 PATCH=0
diff --git a/chrome/app/bookmarks_strings.grdp b/chrome/app/bookmarks_strings.grdp index 28f325e..d22fc9f 100644 --- a/chrome/app/bookmarks_strings.grdp +++ b/chrome/app/bookmarks_strings.grdp
@@ -320,6 +320,36 @@ </message> <!-- End of Bookmarks Manager strings. --> + <!-- Begin of material design Bookmarks Manager strings. --> + <message name="IDS_MD_BOOKMARK_MANAGER_TITLE" desc="Title of the bookmark manager window."> + Bookmarks + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_CLEAR_SEARCH" desc="Title of the button in the bookmark manager that stops a search."> + Clear search + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_MENU_ADD_BOOKMARK" desc="Title of the bookmark toolbar dropdown menu item that adds a new bookmark."> + Add new bookmark + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_MENU_ADD_FOLDER" desc="Title of the bookmark toolbar dropdown menu item that adds a new folder."> + Add new folder + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_MENU_BULK_EDIT" desc="Title of the bookmark toolbar dropdown menu item that enters bulk edit mode."> + Bulk edit + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_MENU_COPY_URL" desc="Title of the bookmark dropdown menu item that copies the url of the bookmark."> + Copy URL + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_MENU_EXPORT" desc="Title of the bookmark toolbar dropdown menu item that exports bookmarks."> + Export Bookmarks + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_MENU_IMPORT" desc="Title of the bookmark toolbar dropdown menu item that imports bookmarks."> + Import Bookmarks + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_MENU_SORT" desc="Title of the bookmark toolbar dropdown menu item that sorts bookmarks by title."> + Sort by title + </message> + <!-- End of material design Bookmarks Manager strings. --> + <!-- Begin of Bookmarks Menu (in the Main Menu) strings. --> <message name="IDS_BOOKMARKS_MENU" desc="The title of the Bookmarks menu in the Main menu and in the Mac menu bar."> &Bookmarks
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index f6afde1f..dfaec5e 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -244,7 +244,15 @@ <if expr="not is_android and not is_ios"> <!-- MD Bookmarks. --> + <include name="IDR_MD_BOOKMARKS_APP_HTML" file="resources\md_bookmarks\app.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_APP_JS" file="resources\md_bookmarks\app.js" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_BOOKMARKS_HTML" file="resources\md_bookmarks\bookmarks.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_SHARED_STYLE_HTML" file="resources\md_bookmarks\shared_style.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_SHARED_VARS_HTML" file="resources\md_bookmarks\shared_vars.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_STORE_HTML" file="resources\md_bookmarks\store.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_STORE_JS" file="resources\md_bookmarks\store.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_TOOLBAR_HTML" file="resources\md_bookmarks\toolbar.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_TOOLBAR_JS" file="resources\md_bookmarks\toolbar.js" type="BINDATA" /> <!-- MD History. --> <include name="IDR_MD_HISTORY_CONSTANTS_HTML" file="resources\md_history\constants.html" type="BINDATA" />
diff --git a/chrome/browser/resources/md_bookmarks/app.html b/chrome/browser/resources/md_bookmarks/app.html new file mode 100644 index 0000000..7f77774 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/app.html
@@ -0,0 +1,43 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://bookmarks/shared_vars.html"> +<link rel="import" href="chrome://bookmarks/store.html"> +<link rel="import" href="chrome://bookmarks/toolbar.html"> + +<dom-module id="bookmarks-app"> + <template> + <style> + :host { + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + } + + #main-container { + display: flex; + flex-direction: row; + flex-grow: 1; + overflow: auto; + } + + bookmarks-sidebar { + flex: 0 0 var(--sidebar-width); + } + + bookmarks-list { + flex: 1; + } + </style> + <bookmarks-toolbar></bookmarks-toolbar> + <div id="main-container"> + <bookmarks-sidebar root-folders="[[rootNode.children]]"> + </bookmarks-sidebar> + <bookmarks-list selected-node="[[selectedNode]]"></bookmarks-list> + </div> + <bookmarks-store selected-id="{{selectedId}}" + selected-node="{{selectedNode}}" + root-node="{{rootNode}}"> + </bookmarks-store> + </template> + <script src="chrome://bookmarks/app.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/app.js b/chrome/browser/resources/md_bookmarks/app.js new file mode 100644 index 0000000..0d79074a --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/app.js
@@ -0,0 +1,23 @@ +// Copyright 2016 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. + +Polymer({ + is: 'bookmarks-app', + + properties: { + selectedId: String, + + /** @type {BookmarkTreeNode} */ + selectedNode: Object, + + /** @type {BookmarkTreeNode} */ + rootNode: Object, + }, + + /** @override */ + attached: function() { + /** @type {BookmarksStoreElement} */ (this.$$('bookmarks-store')) + .initializeStore(); + }, +});
diff --git a/chrome/browser/resources/md_bookmarks/bookmarks.html b/chrome/browser/resources/md_bookmarks/bookmarks.html index 0176d89..1c2bc82c 100644 --- a/chrome/browser/resources/md_bookmarks/bookmarks.html +++ b/chrome/browser/resources/md_bookmarks/bookmarks.html
@@ -3,11 +3,19 @@ <head> <meta charset="utf8"> <title>$i18n{title}</title> - <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> + <link rel="import" href="chrome://bookmarks/app.html"> + <style> + html, + body { + background: var(--md-background-color); + height: 100%; + margin: 0; + } + </style> </head> <body> + <bookmarks-app></bookmarks-app> </body> - </html>
diff --git a/chrome/browser/resources/md_bookmarks/shared_style.html b/chrome/browser/resources/md_bookmarks/shared_style.html new file mode 100644 index 0000000..fee4fc7 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/shared_style.html
@@ -0,0 +1,32 @@ +<link rel="import" href="chrome://bookmarks/shared_vars.html"> + +<dom-module id="shared-style"> + <template> + <style> + [hidden] { + display: none !important; + } + + button.more-vert-button { + height: 36px; + padding: 8px; + width: 36px; + } + + button.more-vert-button div { + border: 2px solid var(--secondary-text-color); + border-radius: 2px; + margin: 1px 8px; + pointer-events: none; + transform: scale(0.8); + } + + hr { + background: rgba(0, 0, 0, 0.11); + border-width: 0; + height: 1px; + margin: 8px 0; + } + </style> + </template> +</dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/shared_vars.html b/chrome/browser/resources/md_bookmarks/shared_vars.html new file mode 100644 index 0000000..5ed9116 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/shared_vars.html
@@ -0,0 +1,11 @@ +<style is="custom-style"> + :root { + --card-max-width: 960px; + --card-min-width: 550px; + --folder-active-color: #4285f4; + --folder-inactive-color: #5a5a5a; + --primary-text-color: #333; + --secondary-text-color: #757575; + --sidebar-width: 256px; + }; +</style>
diff --git a/chrome/browser/resources/md_bookmarks/store.html b/chrome/browser/resources/md_bookmarks/store.html new file mode 100644 index 0000000..b4e40e4 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/store.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<script src="chrome://bookmarks/store.js"></script>
diff --git a/chrome/browser/resources/md_bookmarks/store.js b/chrome/browser/resources/md_bookmarks/store.js new file mode 100644 index 0000000..7a9817817 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/store.js
@@ -0,0 +1,138 @@ +// Copyright 2016 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. + +Polymer({ + is: 'bookmarks-store', + + properties: { + /** @type {BookmarkTreeNode} */ + rootNode: { + type: Object, + notify: true, + }, + + selectedId: { + type: String, + observer: 'updateSelectedNode_', + notify: true, + }, + + /** @type {BookmarkTreeNode} */ + selectedNode: { + type: Object, + notify: true, + readOnly: true, + }, + + idToNodeMap_: Object, + }, + + /** @private {Object} */ + documentListeners_: null, + + /** @override */ + attached: function() { + this.documentListeners_ = { + 'selected-folder-changed': this.onSelectedFolderChanged_.bind(this), + 'folder-open-changed': this.onFolderOpenChanged_.bind(this), + }; + for (var event in this.documentListeners_) + document.addEventListener(event, this.documentListeners_[event]); + }, + + /** @override */ + detached: function() { + for (var event in this.documentListeners_) + document.removeEventListener(event, this.documentListeners_[event]); + }, + + /** + * Initializes the store with data from the bookmarks API. + * Called by app on attached. + */ + initializeStore: function() { + chrome.bookmarks.getTree(function(results) { + this.setupStore_(results[0]); + }.bind(this)); + }, + + /** + * @param {BookmarkTreeNode} rootNode + * @private + */ + setupStore_: function(rootNode) { + this.rootNode = rootNode; + this.idToNodeMap_ = {}; + this.rootNode.path = 'rootNode'; + this.initNodes_(this.rootNode); + this.fire('selected-folder-changed', this.rootNode.children[0].id); + }, + + /** + * Selects the folder specified by the event and deselects the previously + * selected folder. + * @param {CustomEvent} e + * @private + */ + onSelectedFolderChanged_: function(e) { + // Deselect the old folder if defined. + if (this.selectedId) + this.set(this.idToNodeMap_[this.selectedId].path + '.isSelected', false); + + var selectedId = /** @type {string} */ (e.detail); + var newFolder = this.idToNodeMap_[selectedId]; + this.set(newFolder.path + '.isSelected', true); + this.selectedId = selectedId; + }, + + /** + * Handles events that open and close folders. + * @param {CustomEvent} e + * @private + */ + onFolderOpenChanged_: function(e) { + var folder = this.idToNodeMap_[e.detail.id]; + this.set(folder.path + '.isOpen', e.detail.open); + if (!folder.isOpen && this.isAncestorOfSelected_(folder)) + this.fire('selected-folder-changed', folder.id); + }, + + /** + * @param {BookmarkTreeNode} folder + * @private + * @return {boolean} + */ + isAncestorOfSelected_: function(folder) { + return this.selectedNode.path.startsWith(folder.path); + }, + + /** @private */ + updateSelectedNode_: function() { + var selectedNode = this.idToNodeMap_[this.selectedId]; + this.linkPaths('selectedNode', selectedNode.path); + this._setSelectedNode(selectedNode); + }, + + /** + * Initializes the nodes in the bookmarks tree as follows: + * - Populates |idToNodeMap_| with a mapping of all node ids to their + * corresponding BookmarkTreeNode. + * - Stores the path from the store to a node inside the node. + * - Sets all the nodes to not selected and open by default. + * @param {BookmarkTreeNode} bookmarkNode + * @private + */ + initNodes_: function(bookmarkNode) { + this.idToNodeMap_[bookmarkNode.id] = bookmarkNode; + if (bookmarkNode.url) + return; + + bookmarkNode.isSelected = false; + bookmarkNode.isOpen = true; + for (var i = 0; i < bookmarkNode.children.length; i++) { + bookmarkNode.children[i].path = bookmarkNode.path + '.children.' + i; + this.initNodes_(bookmarkNode.children[i]); + } + }, +});
diff --git a/chrome/browser/resources/md_bookmarks/toolbar.html b/chrome/browser/resources/md_bookmarks/toolbar.html new file mode 100644 index 0000000..14cd1648 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/toolbar.html
@@ -0,0 +1,58 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> +<link rel="import" href="chrome://bookmarks/shared_style.html"> +<link rel="stylesheet" href="chrome://resources/css/md_colors.css"> + +<dom-module id="bookmarks-toolbar"> + <template> + <style include="shared-style"> + button.more-actions { + margin: 4px; + } + + button.more-vert-button div { + border-color: white; + } + + cr-toolbar { + --cr-toolbar-field-margin: var(--sidebar-width); + background: var(--md-toolbar-color); + } + </style> + <dialog is="cr-action-menu" id="dropdown"> + <button class="dropdown-item" on-tap="onBulkEditTap_"> + $i18n{menuBulkEdit} + </button> + <button class="dropdown-item" on-tap="onSortTap_"> + $i18n{menuSort} + </button> + <hr> + <button class="dropdown-item" on-tap="onAddBookmarkTap_"> + $i18n{menuAddBookmark} + </button> + <button class="dropdown-item" on-tap="onAddFolderTap_"> + $i18n{menuAddFolder} + </button> + <hr> + <button class="dropdown-item" on-tap="onImportTap_"> + $i18n{menuImport} + </button> + <button class="dropdown-item" on-tap="onExportTap_"> + $i18n{menuExport} + </button> + </dialog> + <cr-toolbar page-name="$i18n{title}" + clear-label="$i18n{clearSearch}" + search-prompt="$i18n{searchPrompt}"> + <button is="paper-icon-button-light" class="more-actions more-vert-button" + on-tap="onMenuButtonOpenTap_"> + <div></div> + <div></div> + <div></div> + </button> + </cr-toolbar> + </template> + <script src="chrome://bookmarks/toolbar.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/toolbar.js b/chrome/browser/resources/md_bookmarks/toolbar.js new file mode 100644 index 0000000..b1d982c --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/toolbar.js
@@ -0,0 +1,47 @@ +// Copyright 2016 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. + +Polymer({ + is: 'bookmarks-toolbar', + + /** + * @param {Event} e + * @private + */ + onMenuButtonOpenTap_: function(e) { + var menu = /** @type {!CrActionMenuElement} */ (this.$.dropdown); + menu.showAt(/** @type {!Element} */ (e.target)); + }, + + /** @private */ + onBulkEditTap_: function() { + this.closeDropdownMenu_(); + }, + + /** @private */ + onSortTap_: function() { + this.closeDropdownMenu_(); + }, + + /** @private */ + onAddBookmarkTap_: function() { + this.closeDropdownMenu_(); + }, + + /** @private */ + onAddImportTap_: function() { + this.closeDropdownMenu_(); + }, + + /** @private */ + onAddExportTap_: function() { + this.closeDropdownMenu_(); + }, + + /** @private */ + closeDropdownMenu_: function() { + var menu = /** @type {!CrActionMenuElement} */ (this.$.dropdown); + menu.close(); + } +});
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc index 54397ca..04542ba0 100644 --- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.h" +#include <algorithm> + +#include "base/strings/string16.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" @@ -12,16 +15,53 @@ #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "ui/base/l10n/l10n_util.h" namespace { +void AddLocalizedString(content::WebUIDataSource* source, + const std::string& message, + int id) { + base::string16 str = l10n_util::GetStringUTF16(id); + str.erase(std::remove(str.begin(), str.end(), '&'), str.end()); + source->AddString(message, str); +} + content::WebUIDataSource* CreateMdBookmarksUIHTMLSource(Profile* profile) { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIBookmarksHost); // Localized strings (alphabetical order). - source->AddLocalizedString("title", IDS_BOOKMARK_MANAGER_TITLE); + AddLocalizedString(source, "clearSearch", + IDS_MD_BOOKMARK_MANAGER_CLEAR_SEARCH); + AddLocalizedString(source, "menuAddBookmark", + IDS_MD_BOOKMARK_MANAGER_MENU_ADD_BOOKMARK); + AddLocalizedString(source, "menuAddFolder", + IDS_MD_BOOKMARK_MANAGER_MENU_ADD_FOLDER); + AddLocalizedString(source, "menuBulkEdit", + IDS_MD_BOOKMARK_MANAGER_MENU_BULK_EDIT); + AddLocalizedString(source, "menuCopyURL", + IDS_MD_BOOKMARK_MANAGER_MENU_COPY_URL); + AddLocalizedString(source, "menuDelete", IDS_DELETE); + AddLocalizedString(source, "menuEdit", IDS_EDIT); + AddLocalizedString(source, "menuExport", IDS_MD_BOOKMARK_MANAGER_MENU_EXPORT); + AddLocalizedString(source, "menuImport", IDS_MD_BOOKMARK_MANAGER_MENU_IMPORT); + AddLocalizedString(source, "menuSort", IDS_MD_BOOKMARK_MANAGER_MENU_SORT); + AddLocalizedString(source, "searchPrompt", + IDS_BOOKMARK_MANAGER_SEARCH_BUTTON); + AddLocalizedString(source, "title", IDS_MD_BOOKMARK_MANAGER_TITLE); + // Resources. + source->AddResourcePath("app.html", IDR_MD_BOOKMARKS_APP_HTML); + source->AddResourcePath("app.js", IDR_MD_BOOKMARKS_APP_JS); + source->AddResourcePath("shared_style.html", + IDR_MD_BOOKMARKS_SHARED_STYLE_HTML); + source->AddResourcePath("shared_vars.html", + IDR_MD_BOOKMARKS_SHARED_VARS_HTML); + source->AddResourcePath("store.html", IDR_MD_BOOKMARKS_STORE_HTML); + source->AddResourcePath("store.js", IDR_MD_BOOKMARKS_STORE_JS); + source->AddResourcePath("toolbar.html", IDR_MD_BOOKMARKS_TOOLBAR_HTML); + source->AddResourcePath("toolbar.js", IDR_MD_BOOKMARKS_TOOLBAR_JS); source->SetDefaultResource(IDR_MD_BOOKMARKS_BOOKMARKS_HTML); source->SetJsonPath("strings.js");
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index f0680de0..5dc9232 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -995,6 +995,7 @@ "data/webui/cr_elements/cr_elements_browsertest.js", "data/webui/extensions/cr_extensions_browsertest.js", "data/webui/history_browsertest.js", + "data/webui/md_bookmarks/md_bookmarks_browsertest.js", "data/webui/md_downloads/downloads_browsertest.js", "data/webui/md_history/md_history_browsertest.js", "data/webui/md_user_manager/user_manager_browsertest.js",
diff --git a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js new file mode 100644 index 0000000..e8469c9 --- /dev/null +++ b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js
@@ -0,0 +1,41 @@ +// Copyright 2016 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 Test suite for the Material Design bookmarks page. + */ +var ROOT_PATH = '../../../../../'; + +GEN_INCLUDE( + [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); +GEN('#include "base/command_line.h"'); + +function MaterialBookmarksBrowserTest() {} + +MaterialBookmarksBrowserTest.prototype = { + __proto__: PolymerTest.prototype, + + browsePreload: 'chrome://bookmarks', + + commandLineSwitches: [{switchName: 'enable-features', + switchValue: 'MaterialDesignBookmarks'}], + + extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ + 'test_util.js', + ]), +}; + +function MaterialBookmarksStoreTest() {} + +MaterialBookmarksStoreTest.prototype = { + __proto__: MaterialBookmarksBrowserTest.prototype, + + extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + 'store_test.js', + ]), +}; + +TEST_F('MaterialBookmarksStoreTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/md_bookmarks/store_test.js b/chrome/test/data/webui/md_bookmarks/store_test.js new file mode 100644 index 0000000..d92fe1d1 --- /dev/null +++ b/chrome/test/data/webui/md_bookmarks/store_test.js
@@ -0,0 +1,113 @@ +// Copyright 2016 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. + +suite('<bookmarks-store>', function() { + var store; + var TEST_TREE = { + id: '0', + children: [ + { + id: '1', + children: [ + {id: '2', url: 'link2'}, + {id: '3', children: []} + ] + }, + {id: '4', url: 'link4'}, + {id: '5', url: 'link5'} + ] + }; + + setup(function() { + store = document.createElement('bookmarks-store'); + store.isTesting_ = true; + replaceBody(store); + store.setupStore_(TEST_TREE); + }); + + test('initNodes inserts nodes into idToNodeMap', function(){ + assertEquals(TEST_TREE, store.idToNodeMap_['0']); + assertEquals(TEST_TREE.children[0], store.idToNodeMap_['1']); + assertEquals(TEST_TREE.children[0].children[0], store.idToNodeMap_['2']); + assertEquals(TEST_TREE.children[0].children[1], store.idToNodeMap_['3']); + assertEquals(TEST_TREE.children[1], store.idToNodeMap_['4']); + assertEquals(TEST_TREE.children[2], store.idToNodeMap_['5']); + }); + + test('changing selectedId changes the selectedNode', function(){ + store.selectedId = '0'; + assertEquals(TEST_TREE, store.selectedNode); + store.selectedId = '1'; + assertEquals(TEST_TREE.children[0], store.selectedNode); + store.selectedId = '2'; + assertEquals(TEST_TREE.children[0].children[0], store.selectedNode); + store.selectedId = '3'; + assertEquals(TEST_TREE.children[0].children[1], store.selectedNode); + store.selectedId = '4'; + assertEquals(TEST_TREE.children[1], store.selectedNode); + store.selectedId = '5'; + assertEquals(TEST_TREE.children[2], store.selectedNode); + }); + + test('correct paths generated for nodes', function() { + var TEST_PATHS = { + '0': 'rootNode', + '1': 'rootNode.children.0', + '2': 'rootNode.children.0.children.0', + '3': 'rootNode.children.0.children.1', + '4': 'rootNode.children.1', + '5': 'rootNode.children.2', + }; + + for (var id in store.idToNodeMap_) + assertEquals(TEST_PATHS[id], store.idToNodeMap_[id].path); + }); + + test('store updates on selected event', function() { + // First child of root is selected by default. + assertEquals('1', store.selectedId); + assertTrue(store.idToNodeMap_['1'].isSelected); + + // Selecting a selected folder doesn't deselect it. + store.fire('selected-folder-changed', '1'); + assertEquals('1', store.selectedId); + assertTrue(store.idToNodeMap_['1'].isSelected); + + // Select a deeply nested descendant. + store.fire('selected-folder-changed', '3'); + assertEquals('3', store.selectedId); + assertTrue(store.idToNodeMap_['3'].isSelected); + assertFalse(store.idToNodeMap_['1'].isSelected); + + // Select a folder in separate subtree. + store.fire('selected-folder-changed', '5'); + assertEquals('5', store.selectedId); + assertTrue(store.idToNodeMap_['5'].isSelected); + assertFalse(store.idToNodeMap_['3'].isSelected); + }); + + test('store updates on open and close', function() { + // All folders are open by default. + for (var id in store.idToNodeMap_) { + if (store.idToNodeMap_[id].url) + continue; + + assertTrue(store.idToNodeMap_[id].isOpen); + } + + // Closing a folder doesn't close any descendants. + store.fire('folder-open-changed', {id: '1', open: false}); + assertFalse(store.idToNodeMap_['1'].isOpen); + assertTrue(store.idToNodeMap_['3'].isOpen); + store.fire('folder-open-changed', {id: '1', open: true}); + + // Closing an ancestor folder of a selected folder selects the ancestor. + store.fire('selected-folder-changed', '3'); + store.fire('folder-open-changed', {id: '1', open: false}); + assertFalse(store.idToNodeMap_['1'].isOpen); + assertEquals('1', store.selectedId); + assertTrue(store.idToNodeMap_['1'].isSelected); + assertFalse(store.idToNodeMap_['3'].isSelected); + }); +});
diff --git a/chrome/test/data/webui/md_bookmarks/test_util.js b/chrome/test/data/webui/md_bookmarks/test_util.js new file mode 100644 index 0000000..84c1a6bb --- /dev/null +++ b/chrome/test/data/webui/md_bookmarks/test_util.js
@@ -0,0 +1,12 @@ +// Copyright 2016 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. + +/** + * Replace the current body of the test with a new element. + * @param {Element} element + */ +function replaceBody(element) { + PolymerTest.clearBody(); + document.body.appendChild(element); +}
diff --git a/net/spdy/spdy_http_utils.cc b/net/spdy/spdy_http_utils.cc index f285e84..e1cb9ef 100644 --- a/net/spdy/spdy_http_utils.cc +++ b/net/spdy/spdy_http_utils.cc
@@ -108,25 +108,6 @@ } } -void CreateSpdyHeadersFromHttpResponse( - const HttpResponseHeaders& response_headers, - SpdyHeaderBlock* headers) { - const std::string status_line = response_headers.GetStatusLine(); - std::string::const_iterator after_version = - std::find(status_line.begin(), status_line.end(), ' '); - // Get status code only. - std::string::const_iterator after_status = - std::find(after_version + 1, status_line.end(), ' '); - (*headers)[":status"] = std::string(after_version + 1, after_status); - - size_t iter = 0; - std::string raw_name, value; - while (response_headers.EnumerateHeaderLines(&iter, &raw_name, &value)) { - std::string name = base::ToLowerASCII(raw_name); - AddSpdyHeader(name, value, headers); - } -} - static_assert(HIGHEST - LOWEST < 4 && HIGHEST - MINIMUM_PRIORITY < 6, "request priority incompatible with spdy");
diff --git a/net/spdy/spdy_http_utils.h b/net/spdy/spdy_http_utils.h index 6989ad5..7181323 100644 --- a/net/spdy/spdy_http_utils.h +++ b/net/spdy/spdy_http_utils.h
@@ -17,7 +17,6 @@ class HttpResponseInfo; struct HttpRequestInfo; class HttpRequestHeaders; -class HttpResponseHeaders; // Convert a SpdyHeaderBlock into an HttpResponseInfo. // |headers| input parameter with the SpdyHeaderBlock. @@ -35,11 +34,6 @@ bool direct, SpdyHeaderBlock* headers); -// Create a SpdyHeaderBlock from HttpResponseHeaders. -NET_EXPORT void CreateSpdyHeadersFromHttpResponse( - const HttpResponseHeaders& response_headers, - SpdyHeaderBlock* headers); - // Create HttpRequestHeaders from SpdyHeaderBlock. NET_EXPORT void ConvertHeaderBlockToHttpRequestHeaders( const SpdyHeaderBlock& spdy_headers,
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index 30e0ebbe..ded653baa 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -1240,6 +1240,10 @@ if (!event.target.isComponentSelectionCollapsed()) return; + if (this.propertiesTreeOutline.element.shadowRoot.firstChild && + this.propertiesTreeOutline.element.shadowRoot.firstChild.isComponentSelectionCollapsed()) + return; + if (this._checkWillCancelEditing()) return;