chrome_native_app_window_views_win.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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. 4 5#include "chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h" 6 7#include "apps/app_window.h" 8#include "apps/app_window_registry.h" 9#include "ash/shell.h" 10#include "base/command_line.h" 11#include "base/path_service.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/threading/sequenced_worker_pool.h" 14#include "chrome/browser/apps/per_app_settings_service.h" 15#include "chrome/browser/apps/per_app_settings_service_factory.h" 16#include "chrome/browser/jumplist_updater_win.h" 17#include "chrome/browser/metro_utils/metro_chrome_win.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/web_applications/web_app.h" 20#include "chrome/common/chrome_icon_resources_win.h" 21#include "chrome/common/chrome_switches.h" 22#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 23#include "content/public/browser/browser_thread.h" 24#include "extensions/common/extension.h" 25#include "grit/generated_resources.h" 26#include "ui/aura/remote_window_tree_host_win.h" 27#include "ui/base/l10n/l10n_util.h" 28#include "ui/base/win/shell.h" 29#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" 30#include "ui/views/win/hwnd_util.h" 31 32ChromeNativeAppWindowViewsWin::ChromeNativeAppWindowViewsWin() 33 : weak_ptr_factory_(this) {} 34 35void ChromeNativeAppWindowViewsWin::ActivateParentDesktopIfNecessary() { 36 if (!ash::Shell::HasInstance()) 37 return; 38 39 views::Widget* widget = 40 implicit_cast<views::WidgetDelegate*>(this)->GetWidget(); 41 chrome::HostDesktopType host_desktop_type = 42 chrome::GetHostDesktopTypeForNativeWindow(widget->GetNativeWindow()); 43 // Only switching into Ash from Native is supported. Tearing the user out of 44 // Metro mode can only be done by launching a process from Metro mode itself. 45 // This is done for launching apps, but not regular activations. 46 if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH && 47 chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_NATIVE) { 48 chrome::ActivateMetroChrome(); 49 } 50} 51 52HWND ChromeNativeAppWindowViewsWin::GetNativeAppWindowHWND() const { 53 return views::HWNDForWidget(widget()->GetTopLevelWidget()); 54} 55 56void ChromeNativeAppWindowViewsWin::OnBeforeWidgetInit( 57 views::Widget::InitParams* init_params, 58 views::Widget* widget) { 59 content::BrowserContext* browser_context = app_window()->browser_context(); 60 const extensions::Extension* extension = app_window()->extension(); 61 // If an app has any existing windows, ensure new ones are created on the 62 // same desktop. 63 apps::AppWindow* any_existing_window = 64 apps::AppWindowRegistry::Get(browser_context) 65 ->GetCurrentAppWindowForApp(extension->id()); 66 chrome::HostDesktopType desktop_type; 67 if (any_existing_window) { 68 desktop_type = chrome::GetHostDesktopTypeForNativeWindow( 69 any_existing_window->GetNativeWindow()); 70 } else { 71 PerAppSettingsService* settings = 72 PerAppSettingsServiceFactory::GetForBrowserContext(browser_context); 73 if (settings->HasDesktopLastLaunchedFrom(extension->id())) { 74 desktop_type = settings->GetDesktopLastLaunchedFrom(extension->id()); 75 } else { 76 // We don't know what desktop this app was last launched from, so take our 77 // best guess as to what desktop the user is on. 78 desktop_type = chrome::GetActiveDesktop(); 79 } 80 } 81 if (desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) 82 init_params->context = ash::Shell::GetPrimaryRootWindow(); 83 else 84 init_params->native_widget = new views::DesktopNativeWidgetAura(widget); 85} 86 87void ChromeNativeAppWindowViewsWin::InitializeDefaultWindow( 88 const apps::AppWindow::CreateParams& create_params) { 89 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 90 91 ChromeNativeAppWindowViews::InitializeDefaultWindow(create_params); 92 93 SetAppDetailsForWindow(); 94 95 UpdateShelfMenu(); 96} 97 98void ChromeNativeAppWindowViewsWin::Show() { 99 ActivateParentDesktopIfNecessary(); 100 ChromeNativeAppWindowViews::Show(); 101} 102 103void ChromeNativeAppWindowViewsWin::Activate() { 104 ActivateParentDesktopIfNecessary(); 105 ChromeNativeAppWindowViews::Activate(); 106} 107 108void ChromeNativeAppWindowViewsWin::UpdateShelfMenu() { 109 if (!JumpListUpdater::IsEnabled()) 110 return; 111 112 // Currently the only option is related to ephemeral apps, so avoid updating 113 // the app's jump list when the feature is not enabled. 114 if (!CommandLine::ForCurrentProcess()->HasSwitch( 115 switches::kEnableEphemeralApps)) { 116 return; 117 } 118 119 // For the icon resources. 120 base::FilePath chrome_path; 121 if (!PathService::Get(base::FILE_EXE, &chrome_path)) 122 return; 123 124 JumpListUpdater jumplist_updater(app_model_id_); 125 if (!jumplist_updater.BeginUpdate()) 126 return; 127 128 // Add item to install ephemeral apps. 129 const extensions::Extension* extension = app_window()->extension(); 130 DCHECK(extension); 131 if (extension->is_ephemeral()) { 132 scoped_refptr<ShellLinkItem> link(new ShellLinkItem()); 133 link->set_title(l10n_util::GetStringUTF16(IDS_APP_INSTALL_TITLE)); 134 link->set_icon(chrome_path.value(), 135 icon_resources::kInstallPackagedAppIndex); 136 ShellIntegration::AppendProfileArgs( 137 app_window()->browser_context()->GetPath(), link->GetCommandLine()); 138 link->GetCommandLine()->AppendSwitchASCII(switches::kInstallFromWebstore, 139 extension->id()); 140 141 ShellLinkItemList items; 142 items.push_back(link); 143 jumplist_updater.AddTasks(items); 144 } 145 146 jumplist_updater.CommitUpdate(); 147} 148 149void ChromeNativeAppWindowViewsWin::SetAppDetailsForWindow() { 150 // Set the Application Model ID so that windows are grouped correctly. 151 const extensions::Extension* app = app_window()->extension(); 152 std::string app_name = 153 web_app::GenerateApplicationNameFromExtensionId(app->id()); 154 base::string16 app_name_wide = base::UTF8ToWide(app_name); 155 HWND hwnd = GetNativeAppWindowHWND(); 156 Profile* profile = 157 Profile::FromBrowserContext(app_window()->browser_context()); 158 app_model_id_ = 159 ShellIntegration::GetAppModelIdForProfile(app_name_wide, 160 profile->GetPath()); 161 162 // Set the relaunch data so "Pin this program to taskbar" has the app's 163 // information. 164 base::FilePath chrome_exe; 165 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 166 NOTREACHED(); 167 return; 168 } 169 170 GURL url = extensions::AppLaunchInfo::GetLaunchWebURL(app); 171 CommandLine command_line = ShellIntegration::CommandLineArgsForLauncher( 172 url, app->id(), profile->GetPath()); 173 command_line.SetProgram(chrome_exe); 174 175 // Set window's icon to the one in the web app path. This was created when the 176 // app was installed. The icon cache would have been refreshed at that time. 177 base::string16 title = base::UTF8ToUTF16(app->name()); 178 base::FilePath web_app_path = web_app::GetWebAppDataDirectory( 179 profile->GetPath(), app->id(), url); 180 base::FilePath icon_file = web_app_path 181 .Append(web_app::internals::GetSanitizedFileName(title)) 182 .ReplaceExtension(FILE_PATH_LITERAL(".ico")); 183 184 ui::win::SetAppDetailsForWindow( 185 app_model_id_, 186 icon_file.value(), 187 command_line.GetCommandLineString(), 188 title, 189 hwnd); 190} 191