1 // Copyright (c) 2014 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/ui/settings_window_manager_chromeos.h"
6
7 #include "ash/public/cpp/app_types.h"
8 #include "ash/public/cpp/multi_user_window_manager.h"
9 #include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h"
10 #include "chrome/browser/app_mode/app_mode_utils.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
13 #include "chrome/browser/ui/ash/window_properties.h"
14 #include "chrome/browser/ui/browser_finder.h"
15 #include "chrome/browser/ui/browser_navigator.h"
16 #include "chrome/browser/ui/browser_navigator_params.h"
17 #include "chrome/browser/ui/browser_window.h"
18 #include "chrome/browser/ui/chrome_pages.h"
19 #include "chrome/browser/ui/settings_window_manager_observer_chromeos.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
22 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
23 #include "chrome/browser/web_applications/components/web_app_utils.h"
24 #include "chrome/browser/web_applications/system_web_app_manager.h"
25 #include "chrome/common/webui_url_constants.h"
26 #include "chromeos/constants/chromeos_features.h"
27 #include "content/public/browser/web_contents.h"
28 #include "ui/aura/client/aura_constants.h"
29 #include "url/gurl.h"
30
31 namespace chrome {
32
33 namespace {
34
35 bool g_force_deprecated_settings_window_for_testing = false;
36
37 // This method handles the case of resurfacing the user's OS Settings
38 // standalone window that may be at the time located on another user's desktop.
ShowSettingsOnCurrentDesktop(Browser * browser)39 void ShowSettingsOnCurrentDesktop(Browser* browser) {
40 auto* window_manager = MultiUserWindowManagerHelper::GetWindowManager();
41 if (window_manager && browser) {
42 window_manager->ShowWindowForUser(browser->window()->GetNativeWindow(),
43 window_manager->CurrentAccountId());
44 browser->window()->Show();
45 }
46 }
47
48 } // namespace
49
50 // static
GetInstance()51 SettingsWindowManager* SettingsWindowManager::GetInstance() {
52 return base::Singleton<SettingsWindowManager>::get();
53 }
54
55 // static
ForceDeprecatedSettingsWindowForTesting()56 void SettingsWindowManager::ForceDeprecatedSettingsWindowForTesting() {
57 g_force_deprecated_settings_window_for_testing = true;
58 }
59
60 // static
UseDeprecatedSettingsWindow(const Profile * profile)61 bool SettingsWindowManager::UseDeprecatedSettingsWindow(
62 const Profile* profile) {
63 return !web_app::AreWebAppsEnabled(profile) ||
64 chrome::IsRunningInForcedAppMode() ||
65 g_force_deprecated_settings_window_for_testing;
66 }
67
AddObserver(SettingsWindowManagerObserver * observer)68 void SettingsWindowManager::AddObserver(
69 SettingsWindowManagerObserver* observer) {
70 observers_.AddObserver(observer);
71 }
72
RemoveObserver(SettingsWindowManagerObserver * observer)73 void SettingsWindowManager::RemoveObserver(
74 SettingsWindowManagerObserver* observer) {
75 observers_.RemoveObserver(observer);
76 }
77
ShowChromePageForProfile(Profile * profile,const GURL & gurl)78 void SettingsWindowManager::ShowChromePageForProfile(Profile* profile,
79 const GURL& gurl) {
80 // Use the original (non off-the-record) profile for settings unless
81 // this is a guest session.
82 if (!profile->IsGuestSession() && profile->IsOffTheRecord())
83 profile = profile->GetOriginalProfile();
84
85 // TODO(crbug.com/1067073): Remove legacy Settings Window.
86 if (!UseDeprecatedSettingsWindow(profile)) {
87 bool did_create;
88 Browser* browser = web_app::LaunchSystemWebApp(
89 profile, web_app::SystemAppType::SETTINGS, gurl,
90 /*params=*/base::nullopt, &did_create);
91 ShowSettingsOnCurrentDesktop(browser);
92 // Only notify if we created a new browser.
93 if (!did_create || !browser)
94 return;
95
96 for (SettingsWindowManagerObserver& observer : observers_)
97 observer.OnNewSettingsWindow(browser);
98
99 return;
100 }
101
102 // Look for an existing browser window.
103 Browser* browser = FindBrowserForProfile(profile);
104 if (browser) {
105 DCHECK(browser->profile() == profile);
106 content::WebContents* web_contents =
107 browser->tab_strip_model()->GetWebContentsAt(0);
108 if (web_contents && web_contents->GetURL() == gurl) {
109 browser->window()->Show();
110 return;
111 }
112
113 NavigateParams params(browser, gurl, ui::PAGE_TRANSITION_AUTO_BOOKMARK);
114 params.window_action = NavigateParams::SHOW_WINDOW;
115 params.user_gesture = true;
116 Navigate(¶ms);
117 return;
118 }
119
120 // No existing browser window, create one.
121 NavigateParams params(profile, gurl, ui::PAGE_TRANSITION_AUTO_BOOKMARK);
122 params.disposition = WindowOpenDisposition::NEW_POPUP;
123 params.trusted_source = true;
124 params.window_action = NavigateParams::SHOW_WINDOW;
125 params.user_gesture = true;
126 params.path_behavior = NavigateParams::IGNORE_AND_NAVIGATE;
127 Navigate(¶ms);
128 browser = params.browser;
129
130 // operator[] not used because SessionID has no default constructor.
131 settings_session_map_.emplace(profile, SessionID::InvalidValue())
132 .first->second = browser->session_id();
133 DCHECK(browser->is_trusted_source());
134
135 auto* window = browser->window()->GetNativeWindow();
136 window->SetProperty(aura::client::kAppType,
137 static_cast<int>(ash::AppType::CHROME_APP));
138 window->SetProperty(kOverrideWindowIconResourceIdKey, IDR_SETTINGS_LOGO_192);
139
140 for (SettingsWindowManagerObserver& observer : observers_)
141 observer.OnNewSettingsWindow(browser);
142 }
143
ShowOSSettings(Profile * profile)144 void SettingsWindowManager::ShowOSSettings(Profile* profile) {
145 ShowOSSettings(profile, std::string());
146 }
147
ShowOSSettings(Profile * profile,const std::string & sub_page)148 void SettingsWindowManager::ShowOSSettings(Profile* profile,
149 const std::string& sub_page) {
150 ShowChromePageForProfile(profile, chrome::GetOSSettingsUrl(sub_page));
151 }
152
FindBrowserForProfile(Profile * profile)153 Browser* SettingsWindowManager::FindBrowserForProfile(Profile* profile) {
154 if (!UseDeprecatedSettingsWindow(profile)) {
155 return web_app::FindSystemWebAppBrowser(profile,
156 web_app::SystemAppType::SETTINGS);
157 }
158
159 auto iter = settings_session_map_.find(profile);
160 if (iter != settings_session_map_.end())
161 return chrome::FindBrowserWithID(iter->second);
162
163 return nullptr;
164 }
165
IsSettingsBrowser(Browser * browser) const166 bool SettingsWindowManager::IsSettingsBrowser(Browser* browser) const {
167 DCHECK(browser);
168
169 Profile* profile = browser->profile();
170 if (!UseDeprecatedSettingsWindow(profile)) {
171 if (!browser->app_controller() || !browser->app_controller()->HasAppId())
172 return false;
173
174 // TODO(calamity): Determine whether, during startup, we need to wait for
175 // app install and then provide a valid answer here.
176 base::Optional<std::string> settings_app_id =
177 web_app::GetAppIdForSystemWebApp(profile,
178 web_app::SystemAppType::SETTINGS);
179 return settings_app_id &&
180 browser->app_controller()->GetAppId() == settings_app_id.value();
181 } else {
182 auto iter = settings_session_map_.find(profile);
183 return iter != settings_session_map_.end() &&
184 iter->second == browser->session_id();
185 }
186 }
187
SettingsWindowManager()188 SettingsWindowManager::SettingsWindowManager() {}
189
~SettingsWindowManager()190 SettingsWindowManager::~SettingsWindowManager() {}
191
192 } // namespace chrome
193