File: startup_browser_creator.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 (351 lines) | stat: -rw-r--r-- 15,550 bytes parent folder | download | duplicates (5)
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
// 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_UI_STARTUP_STARTUP_BROWSER_CREATOR_H_
#define CHROME_BROWSER_UI_STARTUP_STARTUP_BROWSER_CREATOR_H_

#include <memory>
#include <vector>

#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/ui/startup/startup_types.h"

class Browser;
class GURL;
class PrefRegistrySimple;
class Profile;

namespace base {
class CommandLine;
}

namespace web_app {
namespace integration_tests {
class WebAppIntegrationTestDriver;
}
FORWARD_DECLARE_TEST(WebAppEngagementBrowserTest, CommandLineTab);
FORWARD_DECLARE_TEST(WebAppEngagementBrowserTest, CommandLineWindowByUrl);
FORWARD_DECLARE_TEST(WebAppEngagementBrowserTest, CommandLineWindowByAppId);
}  // namespace web_app

// Indicates how Chrome should start up the first profile.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class StartupProfileMode {
  // Regular startup with a browser window.
  kBrowserWindow = 0,
  // Profile picker window should be shown on startup.
  kProfilePicker = 1,
  // Chrome cannot start because no profiles are available.
  kError = 2,

  kMaxValue = kError,
};

// Indicates the reason why the StartupProfileMode was chosen.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class StartupProfileModeReason {
  kError = 0,

  // Cases when the profile picker is shown:
  kMultipleProfiles = 1,
  kPickerForcedByPolicy = 2,

  // Cases when the profile picker is not shown:
  kGuestModeRequested = 10,
  // Deleted kGuestSessionLacros = 11,
  kProfileDirSwitch = 12,
  kProfileEmailSwitch = 13,
  kIgnoreProfilePicker = 14,
  kCommandLineTabs = 15,
  kPickerNotSupported = 16,
  kWasRestarted = 17,
  kIncognitoModeRequested = 18,
  kAppRequested = 19,
  kUninstallApp = 20,
  kGcpwSignin = 21,
  kLaunchWithoutWindow = 22,
  // The check for Win notifications seems to be done twice. Record these
  // separately, just in case.
  kNotificationLaunchIdWin1 = 23,
  kNotificationLaunchIdWin2 = 24,
  kPickerDisabledByPolicy = 25,
  // Deleted kProfilesDisabledLacros = 26
  kSingleProfile = 27,
  kInactiveProfiles = 28,
  kUserOptedOut = 29,

  kMaxValue = kUserOptedOut,
};

// Bundles the startup profile path together with a `StartupProfileMode`.
// Depending on `StartupProfileModeFromReason(reason)`, `path` is either:
// - regular profile path for `kBrowserWindow`; if the guest mode is requested,
//   may contain either the default profile path or the guest profile path
// - empty profile path for `kProfilePicker` and `kError`
// TODO(crbug.com/40157821): return a guest profile path for the Guest
// mode.
struct StartupProfilePathInfo {
  base::FilePath path;
  StartupProfileModeReason reason = StartupProfileModeReason::kError;
};

// Bundles the startup profile together with a StartupProfileMode.
// Depending on the `mode` value, `profile` is either:
// - regular profile for `kBrowserWindow`; if the Guest mode is requested,
//   may contain either the default profile path or the guest profile path
// - nullptr for `kProfilePicker` and `kError`
// TODO(crbug.com/40157821): return a guest profile for the Guest mode.
struct StartupProfileInfo {
  raw_ptr<Profile, LeakedDanglingUntriaged> profile;
  StartupProfileMode mode;
};

// Whether the profile picker should be shown based on `reason`.
StartupProfileMode StartupProfileModeFromReason(
    StartupProfileModeReason reason);

// class containing helpers for BrowserMain to spin up a new instance and
// initialize the profile.
class StartupBrowserCreator {
 public:
  typedef std::vector<Profile*> Profiles;

  StartupBrowserCreator();
  StartupBrowserCreator(const StartupBrowserCreator&) = delete;
  StartupBrowserCreator& operator=(const StartupBrowserCreator&) = delete;
  ~StartupBrowserCreator();

  // Adds urls to be opened during first run. This overrides the standard
  // tabs shown at first run.
  // Invalid URLs (per `GURL::is_valid()`) are skipped.
  void AddFirstRunTabs(const std::vector<GURL>& urls);

  // This function is equivalent to ProcessCommandLine but should only be
  // called during actual process startup.
  bool Start(const base::CommandLine& cmd_line,
             const base::FilePath& cur_dir,
             StartupProfileInfo profile_info,
             const Profiles& last_opened_profiles);

  // This function performs command-line handling and is invoked only after
  // start up (for example when we get a start request for another process).
  // |command_line| holds the command line we need to process.
  // |cur_dir| is the current working directory that the original process was
  // invoked from.
  // |profile_path_info| contains the directory that contains the profile that
  // the command line arguments will be executed under.
  static void ProcessCommandLineAlreadyRunning(
      const base::CommandLine& command_line,
      const base::FilePath& cur_dir,
      const StartupProfilePathInfo& profile_path_info);

  // Opens the set of startup pages from the current session startup prefs.
  static void OpenStartupPages(
      Browser* browser,
      chrome::startup::IsProcessStartup process_startup);

  // Returns true if we're launching a profile synchronously. In that case, the
  // opened window should not cause a session restore.
  static bool InSynchronousProfileLaunch();

  // Launches a browser window associated with |profile|. |command_line| should
  // be the command line passed to this process. |cur_dir| can be empty, which
  // implies that the directory of the executable should be used.
  // `process_startup` indicates whether this is the first browser.
  // `is_first_run` indicates that this is a new profile.
  // `restore_tabbed_browser` should only be flipped false by Ash full restore
  // code path, suppressing restoring a normal browser when there were only PWAs
  // open in previous session. See crbug.com/1463906.
  void LaunchBrowser(const base::CommandLine& command_line,
                     Profile* profile,
                     const base::FilePath& cur_dir,
                     chrome::startup::IsProcessStartup process_startup,
                     chrome::startup::IsFirstRun is_first_run,
                     bool restore_tabbed_browser);

  // Launches browser for `last_opened_profiles` if it's not empty. Otherwise,
  // launches browser for `profile_info`. `restore_tabbed_browser` should
  // only be flipped false by Ash full restore code path, suppressing restoring
  // a normal browser when there were only PWAs open in previous session. See
  // crbug.com/1463906.
  void LaunchBrowserForLastProfiles(
      const base::CommandLine& command_line,
      const base::FilePath& cur_dir,
      chrome::startup::IsProcessStartup process_startup,
      chrome::startup::IsFirstRun is_first_run,
      StartupProfileInfo profile_info,
      const Profiles& last_opened_profiles,
      bool restore_tabbed_browser);

  // Returns true during browser process startup if the previous browser was
  // restarted. This only returns true before the first StartupBrowserCreator
  // destructs. WasRestarted() will update prefs::kWasRestarted to false, but
  // caches the value of kWasRestarted until StartupBrowserCreator's
  // dtor is called. After the dtor is called, this function returns the value
  // of the preference which is expected to be false as per above.
  static bool WasRestarted();

  static SessionStartupPref GetSessionStartupPref(
      const base::CommandLine& command_line,
      const Profile* profile);

  // For faking that no profiles have been launched yet.
  static void ClearLaunchedProfilesForTesting();

  static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
  static void RegisterProfilePrefs(PrefRegistrySimple* registry);

  // Returns true if Chrome is intended to load a profile and launch without any
  // window.
  static bool ShouldLoadProfileWithoutWindow(
      const base::CommandLine& command_line);

 private:
  friend class StartupBrowserCreatorImpl;
  friend class StartupBrowserCreatorInfobarsTest;
  friend class StartupBrowserCreatorInfobarsWithoutStartupWindowTest;
  // TODO(crbug.com/40482804): Remove this when first_run_tabs gets refactored.
  friend class StartupTabProviderImpl;
  friend class web_app::integration_tests::WebAppIntegrationTestDriver;
  FRIEND_TEST_ALL_PREFIXES(BrowserTest, AppIdSwitch);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
                           ReadingWasRestartedAfterNormalStart);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
                           ReadingWasRestartedAfterRestart);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest, UpdateWithTwoProfiles);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest, LastUsedProfileActivated);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
                           ValidNotificationLaunchId);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
                           InvalidNotificationLaunchId);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserWithListAppsFeature,
                           ListAppsForAllProfiles);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserWithListAppsFeature,
                           ListAppsForGivenProfile);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTest,
                           OpenAppShortcutNoPref);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTest,
                           OpenAppShortcutTabPref);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTest,
                           OpenAppShortcutWindowPref);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTest,
                           OpenPolicyForcedAppShortcut);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
                           OpenAppShortcutNoPref);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
                           OpenAppShortcutTabPref);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
                           OpenAppShortcutWindowPref);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
                           OpenPolicyForcedAppShortcut);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest, OpenAppUrlShortcut);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
                           OpenAppUrlIncognitoShortcut);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserWithRealWebAppTest,
                           LastUsedProfilesWithRealWebApp);
  FRIEND_TEST_ALL_PREFIXES(web_app::WebAppEngagementBrowserTest,
                           CommandLineTab);
  FRIEND_TEST_ALL_PREFIXES(web_app::WebAppEngagementBrowserTest,
                           CommandLineWindowByUrl);
  FRIEND_TEST_ALL_PREFIXES(web_app::WebAppEngagementBrowserTest,
                           CommandLineWindowByAppId);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
                           LastUsedProfilesWithWebApp);
  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
                           KSameTabSwitchReplacesActiveTab);

  bool ProcessCmdLineImpl(const base::CommandLine& command_line,
                          const base::FilePath& cur_dir,
                          chrome::startup::IsProcessStartup process_startup,
                          StartupProfileInfo profile_info,
                          const Profiles& last_opened_profiles);

  // Launches the |last_used_profile| with the full command line, and the other
  // |last_opened_profiles| without the URLs to launch.
  void ProcessLastOpenedProfiles(
      const base::CommandLine& command_line,
      const base::FilePath& cur_dir,
      chrome::startup::IsProcessStartup process_startup,
      chrome::startup::IsFirstRun is_first_run,
      Profile* last_used_profile,
      const Profiles& last_opened_profiles);

  // This function performs command-line handling and is invoked only after
  // start up (for example when we get a start request for another process).
  // |command_line| holds the command line being processed.
  // |cur_dir| is the current working directory that the original process was
  // invoked from.
  // |profile| is the profile the apps will be launched in.
  static bool ProcessLoadApps(const base::CommandLine& command_line,
                              const base::FilePath& cur_dir,
                              Profile* profile);

  // Callback after a profile has been initialized. `profile` should be nullptr
  // if `mode` is `StartupProfileMode::kProfilePicker`.
  static void ProcessCommandLineWithProfile(
      const base::CommandLine& command_line,
      const base::FilePath& cur_dir,
      StartupProfileMode mode,
      Profile* profile);

  // Returns true once a profile was activated. Used by the
  // StartupBrowserCreatorTest.LastUsedProfileActivated test.
  static bool ActivatedProfile();

  // Additional tabs to open during first run.
  std::vector<GURL> first_run_tabs_;

  // True if we have already read and reset the preference kWasRestarted. (A
  // member variable instead of a static variable inside WasRestarted because
  // of testing.)
  static bool was_restarted_read_;

  static bool in_synchronous_profile_launch_;

  static bool is_launching_browser_for_last_profiles_;
};

// Returns true if |profile| has exited uncleanly and has not been launched
// after the unclean exit.
bool HasPendingUncleanExit(Profile* profile);

// Adds launched |profile| to ProfileLaunchObserver.
void AddLaunchedProfile(Profile* profile);

// Returns the path that contains the profile that should be loaded on process
// startup. This can do blocking operations to check if the profile exists in
// the case of using --profile-directory and
// --ignore-profile-directory-if-not-exists together.
// When the profile picker is shown on startup, this returns the Guest profile
// path. On Mac, the startup profile path is also used to open URLs at startup,
// bypassing the profile picker, because the profile picker does not support it.
// TODO(crbug.com/40159795): Remove this parameter once the picker
// supports opening URLs.
StartupProfilePathInfo GetStartupProfilePath(
    const base::FilePath& cur_dir,
    const base::CommandLine& command_line,
    bool ignore_profile_picker);

#if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
// Returns the profile that should be loaded on process startup. This is either
// the profile returned by GetStartupProfilePath, or the guest profile along
// with StartupProfileMode::kProfilePicker mode if the profile picker should be
// opened. Returns nullptr with kError if neither the regular profile nor the
// profile picker can be opened.
StartupProfileInfo GetStartupProfile(const base::FilePath& cur_dir,
                                     const base::CommandLine& command_line);

// Returns the profile that should be loaded on process startup when
// GetStartupProfile() returns kError. This may return kError if neither any
// profile nor the profile picker can be opened.
StartupProfileInfo GetFallbackStartupProfile();
#endif  // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)

#endif  // CHROME_BROWSER_UI_STARTUP_STARTUP_BROWSER_CREATOR_H_