Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2222)

Unified Diff: docs/tab_helpers.md

Issue 1324453005: Convert TabHelper design doc to Markdown. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/tab_helpers.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: docs/tab_helpers.md
diff --git a/docs/tab_helpers.md b/docs/tab_helpers.md
new file mode 100644
index 0000000000000000000000000000000000000000..c68218b3370c54ada9a48a83db7310d4e5c24d40
--- /dev/null
+++ b/docs/tab_helpers.md
@@ -0,0 +1,119 @@
+# Tab Helpers
+
+The `content/` layer of Chromium has a class called `WebContents`, which is one
+of the most basic building blocks of all of Chromium. This document describes
+how `WebContents`es are used to build tabs in browser windows.
+
+[TOC]
+
+## Introduction
+
+What is a "tab helper"? It is a `WebContentsObserver` owned by the `WebContents`
+itself. Let's break that down.
+
+## `WebContentsObserver`
+
+`WebContentsObserver` is a
+[simple interface](https://code.google.com/p/chromium/codesearch#chromium/src/content/public/browser/web_contents_observer.h&q=webcontentsobserver)
+that allows an object to observe events in the life of a `WebContents`. As an
+example, if we look at the `TabStripModel`, there are times when it need to
+watch out for WebContents being deleted. So it creates a
+[DeletionObserver](https://code.google.com/p/chromium/codesearch#chromium/src/chrome/browser/ui/tabs/tab_strip_model.cc&q=DeletionObserver).
+The `DeletionObserver` overrides `WebContentsDestroyed()`, and when a
+`WebContents` gets destroyed, the callback is called and the `DeletionObserver`
+processes the message. Note that `DeletionObserver` is not owned by the
+`WebContents`. It is owned indirectly by the `TabStripModel`.
+
+## `SupportsUserData` and `WebContentsUserData`
+
+There is a mechanism used in Chromium called
+[`SupportsUserData`](https://code.google.com/p/chromium/codesearch#chromium/src/base/supports_user_data.h&q=SupportsUserData)
+that allows attaching of arbitrary objects to an object. The mechanism is
+simple: host objects derive from `SupportsUserData`, and owned objects derive
+from `SupportsUserData::Data`. There are three calls to attach and detach the
+data.
+
+`WebContents` derives from `SupportsUserData`, so that mechanism works for
+attaching objects to a `WebContents`, but the `SupportsUserData` mechanism is a
+bit low-level. A higher level abstraction is
+[`WebContentsUserData`](https://code.google.com/p/chromium/codesearch#chromium/src/content/public/browser/web_contents_user_data.h&q=WebContentsUserData),
+which is easy to derive from and has easy-to-use functionality in
+`CreateForWebContents()` and `FromWebContents()`.
+
+## Adding a feature to a browser tab
+
+Let's combine `WebContentsObserver` and `WebContentsUserData` together, to log
+whenever the title of a tab changes.
+
+```
+class TitleLoggerTabHelper
+ : public content::WebContentsObserver,
+ public content::WebContentsUserData<TitleLoggerTabHelper> {
+ public:
+ ~TitleLoggerTabHelper() override;
+
+ // content::WebContentsObserver
+ void TitleWasSet(NavigationEntry* entry, bool explicit_set) override {
+ LOG(INFO) << "Title: " << entry->GetTitle();
+ }
+
+ private:
+ explicit TitleLoggerTabHelper(content::WebContents* web_contents);
+ friend class content::WebContentsUserData<TitleLoggerTabHelper>;
+
+ DISALLOW_COPY_AND_ASSIGN(TitleLoggerTabHelper);
+};
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(TitleLoggerTabHelper);
+```
+
+We want each tab to have this `WebContentsObserver` attached to it, so that it
+will properly handle the events it's looking for, and when the tab goes away,
+then this tab helper will go away too.
+
+But how do you hook in to browser tab creation? How can we attach this tab
+helper to the `WebContents`es that are used for the browser tabs?
+
+## AttachTabHelpers
+
+There is a function called
+[`AttachTabHelpers()`](https://code.google.com/p/chromium/codesearch#chromium/src/chrome/browser/ui/tab_helpers.cc&q=AttachTabHelpers).
+Whenever a `WebContents` is created for use as a browser tab,
+`AttachTabHelpers()` is called. Every tab helper from around Chromium,
+from ContentSettings to Favicons to History to Prefs, all take this opportunity
+to hook into those `WebContents` used as tabs.
+
+If you are writing a feature that needs to deal with browser tabs, this is where
+you go. Create a tab helper, and add it (in alphabetical order, please!) to
+`AttachTabHelpers()`. Note, though, that you are _never_ allowed to call
+`AttachTabHelpers()` yourself. `AttachTabHelpers()` is only for `WebContents`
+that are in browser tabs, and all of those code paths are already written.
+
+## Reusing tab helpers with non-browser tab `WebContents`es
+
+Sometimes it's useful to re-use tab helpers for `WebContents`es that aren't
+browser tabs. For example, the Chrome Apps code wants to be able to print, and
+wants to use the printing code that browser tabs use. So in
+[`ChromeAppDelegate::InitWebContents()`](https://code.google.com/p/chromium/codesearch#chromium/src/chrome/browser/ui/apps/chrome_app_delegate.cc&q=ChromeAppDelegate::InitWebContents)
+we see that whenever the Apps code creates a new `WebContents`, it attaches a
+carefully-chosen subset of tab helpers, including two printing ones.
+
+You can do that too. If you are creating a `WebContents`, make a very deliberate
+decision about which tab helpers you need. Chances are, you don't need them all;
+you probably only need a handful. In fact, most tab helpers assume they are
+attached to browser tabs, so only add the bare minimum.
+
+## Not every `WebContents` has every tab helper
+
+The other consequence of this design is that you can't make the assumption that
+an arbitrary `WebContents` will have an arbitrary tab helper. The
+`WebContents`es used as browser tabs likely will have most tab helpers (though
+not necessarily all of them!) but a `WebContents` only has a tab helper if it is
+installed on it.
+
+The deeper (false and dangerous) assumption is that every `WebContents` is a
+browser tab. Do not assume that either!
+
+If your code handles `WebContents`es, be aware of their source. It is extremely
+rare to have to be able to handle arbitrary `WebContents`es. Know where they
+come from and what tab helpers are on them, and you'll be fine.
« no previous file with comments | « chrome/browser/ui/tab_helpers.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698