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(&params);
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(&params);
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