File: extension_tab_util.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (384 lines) | stat: -rw-r--r-- 17,220 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_TAB_UTIL_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_TAB_UTIL_H_

#include <memory>
#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "chrome/browser/extensions/window_controller.h"

// TODO(jamescook): Switch most of these guards to ENABLE_EXTENSIONS.
#if !BUILDFLAG(IS_ANDROID)
// gn check doesn't understand this conditional, hence the nogncheck directives
// below.
#include "base/types/expected.h"
#include "base/values.h"
#include "chrome/common/extensions/api/tab_groups.h"
#include "chrome/common/extensions/api/tabs.h"
#include "components/tab_groups/tab_group_color.h"  // nogncheck
#include "components/tab_groups/tab_group_id.h"     // nogncheck
#include "extensions/common/features/feature.h"
#include "extensions/common/mojom/context_type.mojom-forward.h"
#include "ui/base/window_open_disposition.h"
#endif

class Browser;
class ChromeExtensionFunctionDetails;
class ExtensionFunction;
class GURL;
class Profile;
class TabStripModel;
namespace content {
class BrowserContext;
class WebContents;
}

namespace blink::mojom {
class WindowFeatures;
}

namespace tab_groups {
class TabGroupId;
class TabGroupVisualData;
}  // namespace tab_groups

namespace extensions {
class Extension;
class WindowController;

// Provides various utility functions that help manipulate tabs.
class ExtensionTabUtil {
 public:
  static constexpr char kTabNotFoundError[] = "No tab with id: *.";

#if !BUILDFLAG(IS_ANDROID)
  // This file is slowly being ported to Android. For now, most of it is
  // ifdef'd out.
  static constexpr char kNoCrashBrowserError[] =
      "I'm sorry. I'm afraid I can't do that.";
  static constexpr char kCanOnlyMoveTabsWithinNormalWindowsError[] =
      "Tabs can only be moved to and from normal windows.";
  static constexpr char kCanOnlyMoveTabsWithinSameProfileError[] =
      "Tabs can only be moved between windows in the same profile.";
  static constexpr char kNoCurrentWindowError[] = "No current window";
  static constexpr char kWindowNotFoundError[] = "No window with id: *.";
  static constexpr char kTabStripNotEditableError[] =
      "Tabs cannot be edited right now (user may be dragging a tab).";
  static constexpr char kTabStripDoesNotSupportTabGroupsError[] =
      "Grouping is not supported by tabs in this window.";
  static constexpr char kJavaScriptUrlsNotAllowedInExtensionNavigations[] =
      "JavaScript URLs are not allowed in API based extension navigations. Use "
      "chrome.scripting.executeScript instead.";
  static constexpr char kBrowserWindowNotAllowed[] =
      "Browser windows not allowed.";
  static constexpr char kCannotNavigateToDevtools[] =
      "Cannot navigate to a devtools:// page without either the devtools or "
      "debugger permission.";
  static constexpr char kLockedFullscreenModeNewTabError[] =
      "You cannot create new tabs while in locked fullscreen mode.";
  static constexpr char kCannotNavigateToChromeUntrusted[] =
      "Cannot navigate to a chrome-untrusted:// page.";
  static constexpr char kFileUrlsNotAllowedInExtensionNavigations[] =
      "Cannot navigate to a file URL without local file access.";

  static constexpr char kTabsKey[] = "tabs";
#endif  // !BUILDFLAG(IS_ANDROID)

  enum ScrubTabBehaviorType {
    kScrubTabFully,
    kScrubTabUrlToOrigin,
    kDontScrubTab,
  };

  struct ScrubTabBehavior {
    ScrubTabBehaviorType committed_info;
    ScrubTabBehaviorType pending_info;
  };

#if !BUILDFLAG(IS_ANDROID)
  struct OpenTabParams {
    OpenTabParams();
    ~OpenTabParams();

    bool create_browser_if_needed = false;
    std::optional<int> window_id;
    std::optional<int> opener_tab_id;
    std::optional<std::string> url;
    std::optional<bool> active;
    std::optional<bool> split;
    std::optional<bool> pinned;
    std::optional<int> index;
    std::optional<int> bookmark_id;
  };

  // Opens a new tab given an extension function `function` and creation
  // parameters `params`. If a tab can be produced, it will return a
  // base::Value::Dict representing the tab, otherwise it will optionally return
  // an error message, if any is appropriate.
  static base::expected<base::Value::Dict, std::string> OpenTab(
      ExtensionFunction* function,
      const OpenTabParams& params,
      bool user_gesture);

  static int GetWindowId(Browser* browser);
  static int GetWindowIdOfTabStripModel(const TabStripModel* tab_strip_model);
#endif  // !BUILDFLAG(IS_ANDROID)

  static int GetTabId(const content::WebContents* web_contents);

#if !BUILDFLAG(IS_ANDROID)
  static int GetWindowIdOfTab(const content::WebContents* web_contents);
  static base::Value::List CreateTabList(Browser* browser,
                                         const Extension* extension,
                                         mojom::ContextType context);

  static WindowController* GetControllerFromWindowID(
      const ChromeExtensionFunctionDetails& details,
      int window_id,
      std::string* error_message);

  // Returns the Browser with the specified `window id` and the associated
  // `profile`. Optionally, this will also look at browsers associated with the
  // incognito version of `profile` if `also_match_incognito_profile` is true.
  // Populates `error_message` if no matching browser is found.
  static WindowController* GetControllerInProfileWithId(
      Profile* profile,
      int window_id,
      bool also_match_incognito_profile,
      std::string* error_message);

  // Returns the tabs:: API constant for the window type of the `browser`.
  static std::string GetBrowserWindowTypeText(Browser& browser);
#endif  // !BUILDFLAG(IS_ANDROID)

  // Creates a Tab object (see chrome/common/extensions/api/tabs.json) with
  // information about the state of a browser tab for the given `web_contents`.
  // This will scrub the tab of sensitive data (URL, favicon, title) according
  // to `scrub_tab_behavior` and `extension`'s permissions. A null extension is
  // treated as having no permissions.
  // By default, tab information should always be scrubbed (kScrubTab) for any
  // data passed to any extension.
  static api::tabs::Tab CreateTabObject(content::WebContents* web_contents,
                                        ScrubTabBehavior scrub_tab_behavior,
                                        const Extension* extension) {
    return CreateTabObject(web_contents, scrub_tab_behavior, extension, nullptr,
                           -1);
  }
  static api::tabs::Tab CreateTabObject(content::WebContents* web_contents,
                                        ScrubTabBehavior scrub_tab_behavior,
                                        const Extension* extension,
                                        TabStripModel* tab_strip,
                                        int tab_index);
#if !BUILDFLAG(IS_ANDROID)
  // Creates a base::Value::Dict representing the window for the given
  // `browser`, and scrubs any privacy-sensitive data that `extension` does not
  // have access to. `populate_tab_behavior` determines whether tabs will be
  // populated in the result. `context` is used to determine the
  // ScrubTabBehavior for the populated tabs data.
  // TODO(devlin): Convert this to a api::Windows::Window object.
  static base::Value::Dict CreateWindowValueForExtension(
      Browser& browser,
      const Extension* extension,
      WindowController::PopulateTabBehavior populate_tab_behavior,
      mojom::ContextType context);

  // Creates a tab MutedInfo object (see chrome/common/extensions/api/tabs.json)
  // with information about the mute state of a browser tab.
  static api::tabs::MutedInfo CreateMutedInfo(content::WebContents* contents);
#endif  // !BUILDFLAG(IS_ANDROID)

  // Gets the level of scrubbing of tab data that needs to happen for a given
  // extension and web contents. This is the preferred way to get
  // ScrubTabBehavior.
  static ScrubTabBehavior GetScrubTabBehavior(const Extension* extension,
                                              mojom::ContextType context,
                                              content::WebContents* contents);
  // Only use this if there is no access to a specific WebContents, such as when
  // the tab has been closed and there is no active WebContents anymore.
  static ScrubTabBehavior GetScrubTabBehavior(const Extension* extension,
                                              mojom::ContextType context,
                                              const GURL& url);

  // Removes any privacy-sensitive fields from a Tab object if appropriate,
  // given the permissions of the extension and the tab in question.  The
  // tab object is modified in place.
  static void ScrubTabForExtension(const Extension* extension,
                                   content::WebContents* contents,
                                   api::tabs::Tab* tab,
                                   ScrubTabBehavior scrub_tab_behavior);

#if !BUILDFLAG(IS_ANDROID)
  // Gets the `tab_strip_model` and `tab_index` for the given `web_contents`.
  static bool GetTabStripModel(const content::WebContents* web_contents,
                               TabStripModel** tab_strip_model,
                               int* tab_index);

  // Returns the active tab's WebContents if there is an active tab. Returns
  // null if there is no active tab.
  static content::WebContents* GetActiveTab(Browser* browser);
#endif  // !BUILDFLAG(IS_ANDROID)

  // Any out parameter (`window`, `contents`, & `tab_index`) may be null.
  //
  // The output `*window` value may be null if the tab is a prerender tab that
  // has no corresponding browser window.
  static bool GetTabById(int tab_id,
                         content::BrowserContext* browser_context,
                         bool include_incognito,
                         WindowController** window,
                         content::WebContents** contents,
                         int* tab_index);
  static bool GetTabById(int tab_id,
                         content::BrowserContext* browser_context,
                         bool include_incognito,
                         content::WebContents** contents);

#if !BUILDFLAG(IS_ANDROID)
  // Gets the extensions-specific Group ID.
  static int GetGroupId(const tab_groups::TabGroupId& id);

  // Gets the window ID that the group belongs to.
  static int GetWindowIdOfGroup(const tab_groups::TabGroupId& id);

  // Gets the metadata for the group with ID `group_id`. Sets the `error` if not
  // found. `window`, `id`, or `visual_data` may be nullptr and will not be set
  // within the function if so.
  static bool GetGroupById(int group_id,
                           content::BrowserContext* browser_context,
                           bool include_incognito,
                           WindowController** window,
                           tab_groups::TabGroupId* id,
                           const tab_groups::TabGroupVisualData** visual_data,
                           std::string* error);

  // Returns whether the group is shared or not.
  static bool GetSharedStateOfGroup(const tab_groups::TabGroupId& id);

  // Creates a TabGroup object
  // (see chrome/common/extensions/api/tab_groups.json) with information about
  // the state of a tab group for the given group `id`. Most group metadata is
  // derived from the `visual_data`, which specifies group color, title, etc.
  static api::tab_groups::TabGroup CreateTabGroupObject(
      const tab_groups::TabGroupId& id,
      const tab_groups::TabGroupVisualData& visual_data);
  static std::optional<api::tab_groups::TabGroup> CreateTabGroupObject(
      const tab_groups::TabGroupId& id);

  // Conversions between the api::tab_groups::Color enum and the TabGroupColorId
  // enum.
  static api::tab_groups::Color ColorIdToColor(
      const tab_groups::TabGroupColorId& color_id);
  static tab_groups::TabGroupColorId ColorToColorId(
      api::tab_groups::Color color);
#endif  // !BUILDFLAG(IS_ANDROID)

  // Returns all active web contents for the given `browser_context`.
  static std::vector<content::WebContents*> GetAllActiveWebContentsForContext(
      content::BrowserContext* browser_context,
      bool include_incognito);

  // Determines if the `web_contents` is in `browser_context` or it's OTR
  // BrowserContext if `include_incognito` is true.
  static bool IsWebContentsInContext(content::WebContents* web_contents,
                                     content::BrowserContext* browser_context,
                                     bool include_incognito);

#if !BUILDFLAG(IS_ANDROID)
  // Takes `url_string` and returns a GURL which is either valid and absolute
  // or invalid. If `url_string` is not directly interpretable as a valid (it is
  // likely a relative URL) an attempt is made to resolve it. When `extension`
  // is non-null, the URL is resolved relative to its extension base
  // (chrome-extension://<id>/). Using the source frame url would be more
  // correct, but because the api shipped with urls resolved relative to their
  // extension base, we decided it wasn't worth breaking existing extensions to
  // fix.
  static GURL ResolvePossiblyRelativeURL(const std::string& url_string,
                                         const Extension* extension);

  // Returns true if navigating to `url` could kill a page or the browser
  // itself, whether by simulating a crash, browser quit, thread hang, or
  // equivalent. Extensions should be prevented from navigating to such URLs.
  //
  // The caller should ensure that `url` has already been "fixed up" by calling
  // url_formatter::FixupURL.
  static bool IsKillURL(const GURL& url);

  // Resolves the URL and ensures the extension is allowed to navigate to it.
  // Returns the url if successful, otherwise returns an error string.
  static base::expected<GURL, std::string> PrepareURLForNavigation(
      const std::string& url_string,
      const Extension* extension,
      content::BrowserContext* browser_context);

  // Opens a tab for the specified `web_contents`.
  static void CreateTab(std::unique_ptr<content::WebContents> web_contents,
                        const std::string& extension_id,
                        WindowOpenDisposition disposition,
                        const blink::mojom::WindowFeatures& window_features,
                        bool user_gesture);
#endif  // !BUILDFLAG(IS_ANDROID)

  // Executes the specified callback for all tabs in all browser windows.
  static void ForEachTab(
      base::RepeatingCallback<void(content::WebContents*)> callback);

  // Open the extension's options page. Returns true if an options page was
  // successfully opened (though it may not necessarily *load*, e.g. if the
  // URL does not exist). This call to open the options page is initiated from
  // the details page of chrome://extensions.
  static bool OpenOptionsPageFromWebContents(
      const Extension* extension,
      content::WebContents* web_contents);

#if !BUILDFLAG(IS_ANDROID)
  static WindowController* GetWindowControllerOfTab(
      const content::WebContents* web_contents);

  // Open the extension's options page. Returns true if an options page was
  // successfully opened (though it may not necessarily *load*, e.g. if the
  // URL does not exist). This call to open the options page is iniatiated by
  // the extension via chrome.runtime.openOptionsPage.
  static bool OpenOptionsPageFromAPI(const Extension* extension,
                                     content::BrowserContext* browser_context);

  // Open the extension's options page. Returns true if an options page was
  // successfully opened (though it may not necessarily *load*, e.g. if the
  // URL does not exist).
  static bool OpenOptionsPage(const Extension* extension, Browser* browser);

  // Returns true if the given Browser can report tabs to extensions.
  // Example of Browsers which don't support tabs include apps and devtools.
  static bool BrowserSupportsTabs(Browser* browser);

  // Determines the loading status of the given `contents`. This needs to access
  // some non-const member functions of `contents`, but actually leaves it
  // unmodified.
  static api::tabs::TabStatus GetLoadingStatus(content::WebContents* contents);
#endif  // !BUILDFLAG(IS_ANDROID)

  // Clears the back-forward cache for all active tabs across all browser
  // contexts.
  static void ClearBackForwardCache();

#if !BUILDFLAG(IS_ANDROID)
  // Check TabStripModel editability in every browser because a drag session
  // could be running in another browser that reverts to the current browser. Or
  // a drag could be mid-handoff if from one browser to another.
  static bool IsTabStripEditable();

  // Retrieve a TabStripModel only if every browser is editable.
  static TabStripModel* GetEditableTabStripModel(Browser* browser);

  static bool TabIsInSavedTabGroup(content::WebContents* contents,
                                   TabStripModel* tab_strip_model);
#endif  // !BUILDFLAG(IS_ANDROID)
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TAB_UTIL_H_