tree: 08c3448ad66c0a3e120c4c71a25e5d2e9eafac17 [path history] [tgz]
  4. actions.html
  5. actions.js
  6. api_listener.html
  7. api_listener.js
  8. app.html
  9. app.js
  10. bookmarks.html
  11. command_manager.html
  12. command_manager.js
  13. constants.html
  14. constants.js
  15. debouncer.html
  16. debouncer.js
  17. dialog_focus_manager.html
  18. dialog_focus_manager.js
  19. dnd_manager.html
  20. dnd_manager.js
  21. edit_dialog.html
  22. edit_dialog.js
  23. folder_node.html
  24. folder_node.js
  25. images/
  26. item.html
  27. item.js
  28. list.html
  29. list.js
  30. mouse_focus_behavior.html
  31. mouse_focus_behavior.js
  32. reducers.html
  33. reducers.js
  34. router.html
  35. router.js
  36. shared_style.html
  37. shared_vars.html
  38. store.html
  39. store.js
  40. store_client.html
  41. store_client.js
  42. strings.html
  43. toast_manager.html
  44. toast_manager.js
  45. toolbar.html
  46. toolbar.js
  47. types.js
  48. util.html
  49. util.js

Bookmark Manager

The bookmark manager (BMM) is a WebUI surface with a large amount of functionality for managing bookmarks across a relatively simple UI. This document serves as an overview of the page, both in terms of the page features, as well as the code design built up to support it.

Major features

The following are some of the main features of the BMM which impact the design of the code:

  • Real-time updates: The display updates in real-time in response to any change to the bookmark model, whether from the page itself or from any other part of the browser UI.

  • Item selection: It is possible to select items using either the mouse or keyboard, using ctrl/shift in much the same way as with a powerful file browser like Windows Explorer.

  • Contextual commands: All viewing/editing commands adapt to the current selection. Most commands have corresponding keyboard shortcuts.

  • Drag and drop: It is possible to drag bookmarks to move them between folders. This works within the BMM, as well as between native UI and the BMM, and between two different BMM instances from different Chrome profiles.

  • Policy support: Several policies are respected:

Data-flow model

Full design document

The BMM uses a one-way data flow model that is somewhat different to other Polymer WebUI pages. This model is inspired by Redux, with a simple layer which binds it to Polymer UI components. Designing our data flow in this way has a few primary benefits:

  • We have a single source of truth for the state of the page
  • We have a well-defined interface for making changes to the state of the page
  • UI components are able to directly read whatever state they need, removing the need for a chain of tedious, highly-coupled Polymer bindings to manage state.

The following is a brief overview of how the data-flow model works. Note that this model is only used for front-end Polymer UI, and is entirely separate to the backend BookmarkModel in C++.


store.js provides a singleton class (bookmarks.Store) which gives access to a read-only state tree for the entire page (

Any Polymer UI element which wants to be able to data-bind values from the global state should add the behavior bookmarks.StoreClient (in store_client.js). This behavior allows elements to watch particular values in the store, and be automatically updated when they change.


Actions are the only way to modify the state tree. An Action is a plain Javascript object which describes a modification that should be made to the state tree. All Action objects are created by functions in actions.js.

To actually modify the state, call Store.dispatch(action) (or StoreClient.dispatch(action)). This tells the store to process the action and notify UI elements about what has changed.

Changes to the persistent bookmarks backend are made by calling into the bookmarks extension API. These then call back to the BMM through chrome.bookmarks event listeners, which dispatch actions to change the Javascript bookmark model, updating the page.

Note: There's also limited support for Actions which are processed asynchronously. See dispatchAsync for details, but this probably needs more work before they are generally useful.


Reducers describe how an action affects the page state. These are pure functions located in reducers.js which take a state and an action, and return a new state.

Importantly, reducers must never modify any part of the input state: instead, they return new objects for any part of the state tree that has changed. By doing this, it is possible for StoreClient to quickly check for what has changed using ==, and only notify Polymer about things that have actually changed. Plus, these functions are easier to test and debug!

Context menus and keyboard shortcuts

Full design document

Context menus and keyboard shortcuts are controlled by the CommandManager, located in command_manager.js. This includes all logic for commands which open/edit bookmarks, including:

  • Determining which commands should appear in the context menu (and whether they are enabled or disabled).
  • Triggering commands on keyboard shortcuts
  • Showing appropriate UI (such as confirmation dialogs, toasts) when the command is executed.

An enum of all possible commands is defined in constants.js.