[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / views / apps / chrome_native_app_window_views_win.cc
blobdd90d061d33b84a59797a7e182cdb8a6be80fbf6
1 // Copyright 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.
5 #include "chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h"
7 #include "apps/app_window.h"
8 #include "apps/app_window_registry.h"
9 #include "apps/ui/views/app_window_frame_view.h"
10 #include "ash/shell.h"
11 #include "base/command_line.h"
12 #include "base/file_util.h"
13 #include "base/path_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "chrome/browser/apps/per_app_settings_service.h"
17 #include "chrome/browser/apps/per_app_settings_service_factory.h"
18 #include "chrome/browser/jumplist_updater_win.h"
19 #include "chrome/browser/metro_utils/metro_chrome_win.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/shell_integration.h"
22 #include "chrome/browser/ui/views/apps/app_window_desktop_native_widget_aura_win.h"
23 #include "chrome/browser/ui/views/apps/glass_app_window_frame_view_win.h"
24 #include "chrome/browser/web_applications/web_app.h"
25 #include "chrome/browser/web_applications/web_app_win.h"
26 #include "chrome/common/chrome_icon_resources_win.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "extensions/common/extension.h"
30 #include "grit/generated_resources.h"
31 #include "ui/aura/remote_window_tree_host_win.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/win/shell.h"
34 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
35 #include "ui/views/win/hwnd_util.h"
37 namespace {
39 void CreateIconAndSetRelaunchDetails(
40 const base::FilePath& web_app_path,
41 const base::FilePath& icon_file,
42 const web_app::ShortcutInfo& shortcut_info,
43 const HWND hwnd) {
44 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
46 // Set the relaunch data so "Pin this program to taskbar" has the app's
47 // information.
48 CommandLine command_line = ShellIntegration::CommandLineArgsForLauncher(
49 shortcut_info.url,
50 shortcut_info.extension_id,
51 shortcut_info.profile_path);
53 base::FilePath chrome_exe;
54 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
55 NOTREACHED();
56 return;
58 command_line.SetProgram(chrome_exe);
59 ui::win::SetRelaunchDetailsForWindow(command_line.GetCommandLineString(),
60 shortcut_info.title, hwnd);
62 if (!base::PathExists(web_app_path) &&
63 !base::CreateDirectory(web_app_path)) {
64 return;
67 ui::win::SetAppIconForWindow(icon_file.value(), hwnd);
68 web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info.favicon);
71 } // namespace
73 ChromeNativeAppWindowViewsWin::ChromeNativeAppWindowViewsWin()
74 : weak_ptr_factory_(this), glass_frame_view_(NULL) {
77 void ChromeNativeAppWindowViewsWin::ActivateParentDesktopIfNecessary() {
78 if (!ash::Shell::HasInstance())
79 return;
81 views::Widget* widget =
82 implicit_cast<views::WidgetDelegate*>(this)->GetWidget();
83 chrome::HostDesktopType host_desktop_type =
84 chrome::GetHostDesktopTypeForNativeWindow(widget->GetNativeWindow());
85 // Only switching into Ash from Native is supported. Tearing the user out of
86 // Metro mode can only be done by launching a process from Metro mode itself.
87 // This is done for launching apps, but not regular activations.
88 if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH &&
89 chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_NATIVE) {
90 chrome::ActivateMetroChrome();
94 void ChromeNativeAppWindowViewsWin::OnShortcutInfoLoaded(
95 const web_app::ShortcutInfo& shortcut_info) {
96 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
98 HWND hwnd = GetNativeAppWindowHWND();
100 // Set window's icon to the one we're about to create/update in the web app
101 // path. The icon cache will refresh on icon creation.
102 base::FilePath web_app_path = web_app::GetWebAppDataDirectory(
103 shortcut_info.profile_path, shortcut_info.extension_id,
104 shortcut_info.url);
105 base::FilePath icon_file = web_app_path
106 .Append(web_app::internals::GetSanitizedFileName(shortcut_info.title))
107 .ReplaceExtension(FILE_PATH_LITERAL(".ico"));
109 content::BrowserThread::PostBlockingPoolTask(
110 FROM_HERE,
111 base::Bind(&CreateIconAndSetRelaunchDetails,
112 web_app_path, icon_file, shortcut_info, hwnd));
115 HWND ChromeNativeAppWindowViewsWin::GetNativeAppWindowHWND() const {
116 return views::HWNDForWidget(widget()->GetTopLevelWidget());
119 void ChromeNativeAppWindowViewsWin::EnsureCaptionStyleSet() {
120 // Windows seems to have issues maximizing windows without WS_CAPTION.
121 // The default views / Aura implementation will remove this if we are using
122 // frameless or colored windows, so we put it back here.
123 HWND hwnd = GetNativeAppWindowHWND();
124 int current_style = ::GetWindowLong(hwnd, GWL_STYLE);
125 ::SetWindowLong(hwnd, GWL_STYLE, current_style | WS_CAPTION);
128 void ChromeNativeAppWindowViewsWin::OnBeforeWidgetInit(
129 views::Widget::InitParams* init_params,
130 views::Widget* widget) {
131 content::BrowserContext* browser_context = app_window()->browser_context();
132 std::string extension_id = app_window()->extension_id();
133 // If an app has any existing windows, ensure new ones are created on the
134 // same desktop.
135 apps::AppWindow* any_existing_window =
136 apps::AppWindowRegistry::Get(browser_context)
137 ->GetCurrentAppWindowForApp(extension_id);
138 chrome::HostDesktopType desktop_type;
139 if (any_existing_window) {
140 desktop_type = chrome::GetHostDesktopTypeForNativeWindow(
141 any_existing_window->GetNativeWindow());
142 } else {
143 PerAppSettingsService* settings =
144 PerAppSettingsServiceFactory::GetForBrowserContext(browser_context);
145 if (settings->HasDesktopLastLaunchedFrom(extension_id)) {
146 desktop_type = settings->GetDesktopLastLaunchedFrom(extension_id);
147 } else {
148 // We don't know what desktop this app was last launched from, so take our
149 // best guess as to what desktop the user is on.
150 desktop_type = chrome::GetActiveDesktop();
153 if (desktop_type == chrome::HOST_DESKTOP_TYPE_ASH)
154 init_params->context = ash::Shell::GetPrimaryRootWindow();
155 else
156 init_params->native_widget = new AppWindowDesktopNativeWidgetAuraWin(this);
159 void ChromeNativeAppWindowViewsWin::InitializeDefaultWindow(
160 const apps::AppWindow::CreateParams& create_params) {
161 ChromeNativeAppWindowViews::InitializeDefaultWindow(create_params);
163 const extensions::Extension* extension = app_window()->GetExtension();
164 if (!extension)
165 return;
167 std::string app_name =
168 web_app::GenerateApplicationNameFromExtensionId(extension->id());
169 base::string16 app_name_wide = base::UTF8ToWide(app_name);
170 HWND hwnd = GetNativeAppWindowHWND();
171 Profile* profile =
172 Profile::FromBrowserContext(app_window()->browser_context());
173 app_model_id_ =
174 ShellIntegration::GetAppModelIdForProfile(app_name_wide,
175 profile->GetPath());
176 ui::win::SetAppIdForWindow(app_model_id_, hwnd);
178 web_app::UpdateShortcutInfoAndIconForApp(
179 extension,
180 profile,
181 base::Bind(&ChromeNativeAppWindowViewsWin::OnShortcutInfoLoaded,
182 weak_ptr_factory_.GetWeakPtr()));
184 EnsureCaptionStyleSet();
185 UpdateShelfMenu();
188 views::NonClientFrameView*
189 ChromeNativeAppWindowViewsWin::CreateStandardDesktopAppFrame() {
190 glass_frame_view_ = NULL;
191 if (ui::win::IsAeroGlassEnabled()) {
192 glass_frame_view_ = new GlassAppWindowFrameViewWin(this, widget());
193 return glass_frame_view_;
195 return ChromeNativeAppWindowViews::CreateStandardDesktopAppFrame();
198 void ChromeNativeAppWindowViewsWin::Show() {
199 ActivateParentDesktopIfNecessary();
200 ChromeNativeAppWindowViews::Show();
203 void ChromeNativeAppWindowViewsWin::Activate() {
204 ActivateParentDesktopIfNecessary();
205 ChromeNativeAppWindowViews::Activate();
208 void ChromeNativeAppWindowViewsWin::UpdateShelfMenu() {
209 if (!JumpListUpdater::IsEnabled())
210 return;
212 // Currently the only option is related to ephemeral apps, so avoid updating
213 // the app's jump list when the feature is not enabled.
214 if (!CommandLine::ForCurrentProcess()->HasSwitch(
215 switches::kEnableEphemeralApps)) {
216 return;
219 const extensions::Extension* extension = app_window()->GetExtension();
220 if (!extension)
221 return;
223 // For the icon resources.
224 base::FilePath chrome_path;
225 if (!PathService::Get(base::FILE_EXE, &chrome_path))
226 return;
228 JumpListUpdater jumplist_updater(app_model_id_);
229 if (!jumplist_updater.BeginUpdate())
230 return;
232 // Add item to install ephemeral apps.
233 if (extension->is_ephemeral()) {
234 scoped_refptr<ShellLinkItem> link(new ShellLinkItem());
235 link->set_title(l10n_util::GetStringUTF16(IDS_APP_INSTALL_TITLE));
236 link->set_icon(chrome_path.value(),
237 icon_resources::kInstallPackagedAppIndex);
238 ShellIntegration::AppendProfileArgs(
239 app_window()->browser_context()->GetPath(), link->GetCommandLine());
240 link->GetCommandLine()->AppendSwitchASCII(switches::kInstallFromWebstore,
241 extension->id());
243 ShellLinkItemList items;
244 items.push_back(link);
245 jumplist_updater.AddTasks(items);
248 jumplist_updater.CommitUpdate();