blob: 1445c175c92b28a52906e47a85e221412d2796bb [file] [log] [blame]
Tom Lukaszewicz6c7b31e2022-06-02 21:31:111// Copyright 2022 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/browser_process_platform_part_chromeos.h"
6
7#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
8#include "chrome/browser/prefs/session_startup_pref.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/profiles/profile_io_data.h"
11#include "chrome/browser/sessions/session_restore.h"
12#include "chrome/browser/sessions/session_service_utils.h"
13#include "chrome/browser/ui/browser.h"
14#include "chrome/browser/ui/browser_finder.h"
15#include "chrome/browser/ui/browser_list.h"
16#include "chrome/browser/ui/browser_navigator.h"
17#include "chrome/browser/ui/browser_navigator_params.h"
18#include "chrome/browser/ui/browser_window.h"
19#include "chrome/browser/ui/startup/startup_browser_creator.h"
20#include "chrome/browser/ui/tabs/tab_strip_model.h"
21#include "components/custom_handlers/protocol_handler_registry.h"
22#include "ui/base/page_transition_types.h"
23#include "ui/base/window_open_disposition.h"
24
25BrowserProcessPlatformPartChromeOS::BrowserProcessPlatformPartChromeOS()
26 : browser_restore_observer_(this) {}
27
28BrowserProcessPlatformPartChromeOS::~BrowserProcessPlatformPartChromeOS() =
29 default;
30
31bool BrowserProcessPlatformPartChromeOS::CanRestoreUrlsForProfile(
32 const Profile* profile) const {
33 return profile->IsRegularProfile();
34}
35
36BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::
37 BrowserRestoreObserver(
38 const BrowserProcessPlatformPartChromeOS* browser_process_platform_part)
39 : browser_process_platform_part_(browser_process_platform_part) {
40 BrowserList::AddObserver(this);
41}
42
43BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::
44 ~BrowserRestoreObserver() {
45 BrowserList::RemoveObserver(this);
46}
47
48void BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::OnBrowserAdded(
49 Browser* browser) {
50 // If |browser| is the only browser, restores urls based on the on startup
51 // setting.
52 if (chrome::GetBrowserCount(browser->profile()) == 1 &&
53 ShouldRestoreUrls(browser)) {
54 if (ShouldOpenUrlsInNewBrowser(browser)) {
55 // Delay creating a new browser until |browser| is activated.
56 on_session_restored_callback_subscription_ =
57 SessionRestore::RegisterOnSessionRestoredCallback(base::BindRepeating(
58 &BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::
59 OnSessionRestoreDone,
60 base::Unretained(this)));
61 } else {
62 RestoreUrls(browser);
63 }
64 }
65
66 // If the startup urls from LAST_AND_URLS pref are already opened in a new
67 // browser, skip opening the same browser.
68 if (browser->creation_source() ==
69 Browser::CreationSource::kLastAndUrlsStartupPref) {
70 DCHECK(on_session_restored_callback_subscription_);
71 on_session_restored_callback_subscription_ = {};
72 }
73}
74
75void BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::
76 OnSessionRestoreDone(Profile* profile, int num_tabs_restored) {
77 // Ensure this callback to be called exactly once.
78 on_session_restored_callback_subscription_ = {};
79
80 // All browser windows are created. Open startup urls in a new browser.
81 auto create_params = Browser::CreateParams(profile, /*user_gesture*/ false);
82 Browser* browser = Browser::Create(create_params);
83 RestoreUrls(browser);
84 browser->window()->Show();
85 browser->window()->Activate();
86}
87
88bool BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::
89 ShouldRestoreUrls(Browser* browser) const {
90 Profile* profile = browser->profile();
91
92 // Only open urls for regular sign in users.
93 DCHECK(profile);
94 if (!browser_process_platform_part_->CanRestoreUrlsForProfile(profile))
95 return false;
96
97 // If during the restore process, or restore from a crash, don't launch urls.
98 // However, in case of LAST_AND_URLS startup setting, urls should be opened
99 // even when the restore session is in progress.
100 SessionStartupPref pref =
101 SessionStartupPref::GetStartupPref(browser->profile()->GetPrefs());
102 if ((SessionRestore::IsRestoring(profile) &&
103 pref.type != SessionStartupPref::LAST_AND_URLS) ||
104 HasPendingUncleanExit(profile)) {
105 return false;
106 }
107
108 // App windows should not be restored.
109 auto window_type = WindowTypeForBrowserType(browser->type());
110 if (window_type == sessions::SessionWindow::TYPE_APP ||
111 window_type == sessions::SessionWindow::TYPE_APP_POPUP) {
112 return false;
113 }
114
115 // If the browser is created by StartupBrowserCreator,
116 // StartupBrowserCreatorImpl::OpenTabsInBrowser can open tabs, so don't
117 // restore urls here.
118 if (browser->creation_source() == Browser::CreationSource::kStartupCreator)
119 return false;
120
121 // If the startup setting is not open urls, don't launch urls.
122 if (!pref.ShouldOpenUrls() || pref.urls.empty())
123 return false;
124
125 return true;
126}
127
128// If the startup setting is both the restore last session and the open urls,
129// those should be opened in a new browser.
130bool BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::
131 ShouldOpenUrlsInNewBrowser(Browser* browser) const {
132 SessionStartupPref pref =
133 SessionStartupPref::GetStartupPref(browser->profile()->GetPrefs());
134 return pref.type == SessionStartupPref::LAST_AND_URLS;
135}
136
137void BrowserProcessPlatformPartChromeOS::BrowserRestoreObserver::RestoreUrls(
138 Browser* browser) {
139 DCHECK(browser);
140
141 SessionStartupPref pref =
142 SessionStartupPref::GetStartupPref(browser->profile()->GetPrefs());
143 std::vector<GURL> urls;
144 for (const auto& url : pref.urls)
145 urls.push_back(url);
146
147 custom_handlers::ProtocolHandlerRegistry* registry =
148 ProtocolHandlerRegistryFactory::GetForBrowserContext(browser->profile());
149 for (const GURL& url : urls) {
150 // We skip URLs that we'd have to launch an external protocol handler for.
151 // This avoids us getting into an infinite loop asking ourselves to open
152 // a URL, should the handler be (incorrectly) configured to be us. Anyone
153 // asking us to open such a URL should really ask the handler directly.
154 bool handled_by_chrome =
155 ProfileIOData::IsHandledURL(url) ||
156 (registry && registry->IsHandledProtocol(url.scheme()));
157 if (!handled_by_chrome)
158 continue;
159
160 int add_types = TabStripModel::ADD_NONE | TabStripModel::ADD_FORCE_INDEX;
161 NavigateParams params(browser, url, ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
162 params.disposition = WindowOpenDisposition::NEW_BACKGROUND_TAB;
163 params.tabstrip_add_types = add_types;
164 Navigate(&params);
165 }
166}