Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /docs /tab_helpers.md
blob: 761077027d0354922907cdd0e2943db214603b0b [file] [log] [blame] [view]
avia41f7af2015-08-31 19:46:58[diff] [blame]1# Tab Helpers
2
3The`content/` layer ofChromium has aclass called`WebContents`, whichis one
4of the most basic building blocks of all ofChromium.This document describes
5how`WebContents`es are used to build tabsin browser windows.
6
dljames8f6142e2025-05-19 20:14:46[diff] [blame]7Tab helpers arein the process of being deprecated.When possible prefer touse
8TabFeatures overTabHelpers.
9See
Erik Chen50f7634b2024-04-29 21:14:22[diff] [blame]10[design principles](chrome_browser_design_principles.md).
11
avia41f7af2015-08-31 19:46:58[diff] [blame]12[TOC]
13
14## Introduction
15
16Whatis a"tab helper"?Itis a`WebContentsObserver` ownedby the`WebContents`
17itself.Let's break that down.
18
Elly Fong-Jones8ea0fc762021-01-06 19:14:23[diff] [blame]19## WebContentsObserver
avia41f7af2015-08-31 19:46:58[diff] [blame]20
21`WebContentsObserver` is a
Elly Fong-Jones8ea0fc762021-01-06 19:14:23[diff] [blame]22[simple interface](https://source.chromium.org/chromium/chromium/src/+/HEAD:content/public/browser/web_contents_observer.h)
avia41f7af2015-08-31 19:46:58[diff] [blame]23that allows an object to observe events in the life of a `WebContents`. As an
24example, if we look at the `TabStripModel`, there are times when it need to
25watch out for WebContents being deleted. So it creates a
Elly Fong-Jones8ea0fc762021-01-06 19:14:23[diff] [blame]26[TabStripModel::WebContentsData](https://source.chromium.org/chromium/chromium/src/+/HEAD:chrome/browser/ui/tabs/tab_strip_model.cc).
Suman Nelson Kancherla1d0cc352018-12-06 20:26:28[diff] [blame]27That object overrides `WebContentsDestroyed()`, and when a
28`WebContents` gets destroyed, the callback is called and the object
29processes the message. Note that `TabStripModel::WebContentsData` object is not owned by the
avia41f7af2015-08-31 19:46:58[diff] [blame]30`WebContents`. It is owned indirectly by the `TabStripModel`.
31
Elly Fong-Jones8ea0fc762021-01-06 19:14:23[diff] [blame]32## SupportsUserData and WebContentsUserData
avia41f7af2015-08-31 19:46:58[diff] [blame]33
34There is a mechanism used in Chromium called
Josip Sokcevicba144412020-09-09 20:57:05[diff] [blame]35[`SupportsUserData`](https://source.chromium.org/chromium/chromium/src/+/HEAD:base/supports_user_data.h)
avia41f7af2015-08-31 19:46:58[diff] [blame]36that allows attaching of arbitrary objects to an object. The mechanism is
37simple: host objects derive from `SupportsUserData`, and owned objects derive
38from `SupportsUserData::Data`. There are three calls to attach and detach the
39data.
40
41`WebContents` derives from `SupportsUserData`, so that mechanism works for
42attaching objects to a `WebContents`, but the `SupportsUserData` mechanism is a
43bit low-level. A higher level abstraction is
Josip Sokcevicba144412020-09-09 20:57:05[diff] [blame]44[`WebContentsUserData`](https://source.chromium.org/chromium/chromium/src/+/HEAD:content/public/browser/web_contents_user_data.h),
avia41f7af2015-08-31 19:46:58[diff] [blame]45which is easy to derive from and has easy-to-use functionality in
46`CreateForWebContents()` and `FromWebContents()`.
47
48## Adding a feature to a browser tab
49
50Let's combine`WebContentsObserver`and`WebContentsUserData` together, to log
51whenever the title of a tab changes.
52
53```
54class TitleLoggerTabHelper
55 : public content::WebContentsObserver,
56 public content::WebContentsUserData<TitleLoggerTabHelper> {
57 public:
Johann16cf06fd2020-09-14 22:55:55[diff] [blame]58 TitleLoggerTabHelper(const TitleLoggerTabHelper&) = delete;
59 TitleLoggerTabHelper& operator=(const TitleLoggerTabHelper&) = delete;
avia41f7af2015-08-31 19:46:58[diff] [blame]60 ~TitleLoggerTabHelper() override;
61
62 // content::WebContentsObserver
Avi Drissman93002212017-09-27 03:20:52[diff] [blame]63 void TitleWasSet(NavigationEntry* entry) override {
avia41f7af2015-08-31 19:46:58[diff] [blame]64 LOG(INFO) << "Title: " << entry->GetTitle();
65 }
66
67 private:
68 explicit TitleLoggerTabHelper(content::WebContents* web_contents);
69 friend class content::WebContentsUserData<TitleLoggerTabHelper>;
avia41f7af2015-08-31 19:46:58[diff] [blame]70};
avia41f7af2015-08-31 19:46:58[diff] [blame]71```
72
73We want each tab to havethis`WebContentsObserver` attached to it, so that it
74will properly handle the events it's looking for, and when the tab goes away,
75then this tab helper will go away too.
76
77But how do you hook in to browser tab creation? How can we attach this tab
78helper to the `WebContents`es that are used for the browser tabs?
79
80## AttachTabHelpers
81
82There is a function called
Josip Sokcevicba144412020-09-09 20:57:05[diff] [blame]83[`AttachTabHelpers()`](https://source.chromium.org/chromium/chromium/src/+/HEAD:chrome/browser/ui/tab_helpers.cc;).
avia41f7af2015-08-31 19:46:58[diff] [blame]84Whenever a `WebContents` is created for use as a browser tab,
85`AttachTabHelpers()` is called. Every tab helper from around Chromium,
86from ContentSettings to Favicons to History to Prefs, all take this opportunity
87to hook into those `WebContents` used as tabs.
88
89If you are writing a feature that needs to deal with browser tabs, this is where
90you go. Create a tab helper, and add it (in alphabetical order, please!) to
91`AttachTabHelpers()`. Note, though, that you are _never_ allowed to call
92`AttachTabHelpers()` yourself. `AttachTabHelpers()` is only for `WebContents`
93that are in browser tabs, and all of those code paths are already written.
94
Elly Fong-Jones8ea0fc762021-01-06 19:14:23[diff] [blame]95## Reusing tab helpers with non-browser tab WebContentses
avia41f7af2015-08-31 19:46:58[diff] [blame]96
97Sometimes it's useful to re-use tab helpersfor`WebContents`es that aren't
98browser tabs. For example, the Chrome Apps code wants to be able to print, and
99wants to use the printing code that browser tabs use. So in
Josip Sokcevicba144412020-09-09 20:57:05[diff] [blame]100[`ChromeAppDelegate::InitWebContents()`](https://source.chromium.org/chromium/chromium/src/+/HEAD:chrome/browser/ui/apps/chrome_app_delegate.cc)
avia41f7af2015-08-31 19:46:58[diff] [blame]101we see that whenever the Apps code creates a new `WebContents`, it attaches a
102carefully-chosen subset of tab helpers, including two printing ones.
103
104You can do that too. If you are creating a `WebContents`, make a very deliberate
105decision about which tab helpers you need. Chances are, you don't need them all;
106you probably only need a handful.In fact, most tab helpers assume they are
107attached to browser tabs, so only add the bare minimum.
108
Elly Fong-Jones8ea0fc762021-01-06 19:14:23[diff] [blame]109## Not every WebContents has every tab helper
avia41f7af2015-08-31 19:46:58[diff] [blame]110
111The other consequence ofthis designis that you can't make the assumption that
112an arbitrary `WebContents` will have an arbitrary tab helper. The
113`WebContents`es used as browser tabs likely will have most tab helpers (though
114not necessarily all of them!) but a `WebContents` only has a tab helper if it is
115installed on it.
116
117The deeper (false and dangerous) assumption is that every `WebContents` is a
118browser tab. Do not assume that either!
119
120If your code handles `WebContents`es, be aware of their source. It is extremely
121rare to have to be able to handle arbitrary `WebContents`es. Know where they
122come from and what tab helpers are on them, and you'll be fine.

[8]ページ先頭

©2009-2025 Movatter.jp