OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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/extensions/application_launch.h" |
| 6 |
| 7 #include "base/metrics/field_trial.h" |
| 8 #include "base/metrics/histogram.h" |
| 9 #include "chrome/browser/extensions/api/app/app_api.h" |
| 10 #include "chrome/browser/extensions/default_apps_trial.h" |
| 11 #include "chrome/browser/extensions/extension_prefs.h" |
| 12 #include "chrome/browser/extensions/extension_service.h" |
| 13 #include "chrome/browser/extensions/extension_tab_helper.h" |
| 14 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 16 #include "chrome/browser/ui/browser.h" |
| 17 #include "chrome/browser/ui/browser_finder.h" |
| 18 #include "chrome/browser/ui/panels/panel_manager.h" |
| 19 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 20 #include "chrome/browser/web_applications/web_app.h" |
| 21 #include "chrome/common/extensions/extension.h" |
| 22 #include "chrome/common/extensions/extension_constants.h" |
| 23 #include "chrome/common/url_constants.h" |
| 24 #include "content/public/browser/render_view_host.h" |
| 25 #include "content/public/browser/web_contents.h" |
| 26 #include "content/public/browser/web_contents_view.h" |
| 27 #include "content/public/common/renderer_preferences.h" |
| 28 |
| 29 using content::WebContents; |
| 30 |
| 31 namespace { |
| 32 |
| 33 // Get the launch URL for a given extension, with optional override/fallback. |
| 34 // |override_url|, if non-empty, will be preferred over the extension's |
| 35 // launch url. |
| 36 GURL UrlForExtension(const Extension* extension, const GURL& override_url) { |
| 37 if (!extension) |
| 38 return override_url; |
| 39 |
| 40 GURL url; |
| 41 if (!override_url.is_empty()) { |
| 42 DCHECK(extension->web_extent().MatchesURL(override_url)); |
| 43 url = override_url; |
| 44 } else { |
| 45 url = extension->GetFullLaunchURL(); |
| 46 } |
| 47 |
| 48 // For extensions lacking launch urls, determine a reasonable fallback. |
| 49 if (!url.is_valid()) { |
| 50 url = extension->options_url(); |
| 51 if (!url.is_valid()) |
| 52 url = GURL(chrome::kChromeUIExtensionsURL); |
| 53 } |
| 54 |
| 55 return url; |
| 56 } |
| 57 |
| 58 bool AllowPanels(const std::string& app_name) { |
| 59 return PanelManager::ShouldUsePanels( |
| 60 web_app::GetExtensionIdFromApplicationName(app_name)); |
| 61 } |
| 62 |
| 63 } // namespace |
| 64 |
| 65 namespace ApplicationLaunch { |
| 66 |
| 67 WebContents* OpenApplication(Profile* profile, |
| 68 const Extension* extension, |
| 69 extension_misc::LaunchContainer container, |
| 70 const GURL& override_url, |
| 71 WindowOpenDisposition disposition) { |
| 72 WebContents* tab = NULL; |
| 73 ExtensionPrefs* prefs = profile->GetExtensionService()->extension_prefs(); |
| 74 prefs->SetActiveBit(extension->id(), true); |
| 75 |
| 76 UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100); |
| 77 |
| 78 if (extension->is_platform_app()) { |
| 79 extensions::AppEventRouter::DispatchOnLaunchedEvent(profile, extension); |
| 80 return NULL; |
| 81 } |
| 82 |
| 83 switch (container) { |
| 84 case extension_misc::LAUNCH_NONE: { |
| 85 NOTREACHED(); |
| 86 break; |
| 87 } |
| 88 case extension_misc::LAUNCH_PANEL: |
| 89 #if defined(USE_ASH) |
| 90 if (extension && |
| 91 CommandLine::ForCurrentProcess()->HasSwitch( |
| 92 ash::switches::kAuraPanelManager)) { |
| 93 tab = OpenApplicationPanel(profile, extension, override_url); |
| 94 break; |
| 95 } |
| 96 // else fall through to LAUNCH_WINDOW |
| 97 #endif |
| 98 case extension_misc::LAUNCH_WINDOW: |
| 99 tab = OpenApplicationWindow(profile, extension, container, |
| 100 override_url, NULL); |
| 101 break; |
| 102 case extension_misc::LAUNCH_TAB: { |
| 103 tab = OpenApplicationTab(profile, extension, override_url, |
| 104 disposition); |
| 105 break; |
| 106 } |
| 107 default: |
| 108 NOTREACHED(); |
| 109 break; |
| 110 } |
| 111 return tab; |
| 112 } |
| 113 |
| 114 #if defined(USE_ASH) |
| 115 WebContents* OpenApplicationPanel( |
| 116 Profile* profile, |
| 117 const Extension* extension, |
| 118 const GURL& url_input) { |
| 119 GURL url = UrlForExtension(extension, url_input); |
| 120 std::string app_name = |
| 121 web_app::GenerateApplicationNameFromExtensionId(extension->id()); |
| 122 gfx::Rect panel_bounds; |
| 123 panel_bounds.set_width(extension->launch_width()); |
| 124 panel_bounds.set_height(extension->launch_height()); |
| 125 PanelViewAura* panel_view = new PanelViewAura(app_name); |
| 126 panel_view->Init(profile, url, panel_bounds); |
| 127 return panel_view->WebContents(); |
| 128 } |
| 129 #endif |
| 130 |
| 131 WebContents* OpenApplicationWindow( |
| 132 Profile* profile, |
| 133 const Extension* extension, |
| 134 extension_misc::LaunchContainer container, |
| 135 const GURL& url_input, |
| 136 Browser** app_browser) { |
| 137 DCHECK(!url_input.is_empty() || extension); |
| 138 GURL url = UrlForExtension(extension, url_input); |
| 139 |
| 140 std::string app_name; |
| 141 app_name = extension ? |
| 142 web_app::GenerateApplicationNameFromExtensionId(extension->id()) : |
| 143 web_app::GenerateApplicationNameFromURL(url); |
| 144 |
| 145 Browser::Type type = Browser::TYPE_POPUP; |
| 146 if (extension && |
| 147 container == extension_misc::LAUNCH_PANEL && |
| 148 AllowPanels(app_name)) { |
| 149 type = Browser::TYPE_PANEL; |
| 150 } |
| 151 |
| 152 gfx::Rect window_bounds; |
| 153 if (extension) { |
| 154 window_bounds.set_width(extension->launch_width()); |
| 155 window_bounds.set_height(extension->launch_height()); |
| 156 } |
| 157 |
| 158 Browser::CreateParams params(type, profile); |
| 159 params.app_name = app_name; |
| 160 params.initial_bounds = window_bounds; |
| 161 |
| 162 #if defined(USE_ASH) |
| 163 if (extension && |
| 164 container == extension_misc::LAUNCH_WINDOW) { |
| 165 // In ash, LAUNCH_FULLSCREEN launches in a maximized app window and |
| 166 // LAUNCH_WINDOW launches in a normal app window. |
| 167 ExtensionPrefs::LaunchType launch_type = |
| 168 profile->GetExtensionService()->extension_prefs()->GetLaunchType( |
| 169 extension->id(), ExtensionPrefs::LAUNCH_DEFAULT); |
| 170 if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN) |
| 171 params.initial_show_state = ui::SHOW_STATE_MAXIMIZED; |
| 172 else if (launch_type == ExtensionPrefs::LAUNCH_WINDOW) |
| 173 params.initial_show_state = ui::SHOW_STATE_NORMAL; |
| 174 } |
| 175 #endif |
| 176 |
| 177 Browser* browser = Browser::CreateWithParams(params); |
| 178 |
| 179 if (app_browser) |
| 180 *app_browser = browser; |
| 181 |
| 182 TabContentsWrapper* wrapper = |
| 183 browser->AddSelectedTabWithURL(url, content::PAGE_TRANSITION_START_PAGE); |
| 184 WebContents* contents = wrapper->web_contents(); |
| 185 contents->GetMutableRendererPrefs()->can_accept_load_drops = false; |
| 186 contents->GetRenderViewHost()->SyncRendererPrefs(); |
| 187 // TODO(stevenjb): Find the right centralized place to do this. Currently it |
| 188 // is only done for app tabs in normal browsers through SetExtensionAppById. |
| 189 if (extension && type == Browser::TYPE_PANEL) |
| 190 wrapper->extension_tab_helper()->SetExtensionAppIconById(extension->id()); |
| 191 |
| 192 browser->window()->Show(); |
| 193 |
| 194 // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial |
| 195 // focus explicitly. |
| 196 contents->GetView()->SetInitialFocus(); |
| 197 return contents; |
| 198 } |
| 199 |
| 200 WebContents* OpenAppShortcutWindow(Profile* profile, |
| 201 const GURL& url, |
| 202 bool update_shortcut) { |
| 203 Browser* app_browser; |
| 204 WebContents* tab = OpenApplicationWindow( |
| 205 profile, |
| 206 NULL, // this is a URL app. No extension. |
| 207 extension_misc::LAUNCH_WINDOW, |
| 208 url, |
| 209 &app_browser); |
| 210 |
| 211 if (!tab) |
| 212 return NULL; |
| 213 |
| 214 if (update_shortcut) { |
| 215 // Set UPDATE_SHORTCUT as the pending web app action. This action is picked |
| 216 // up in LoadingStateChanged to schedule a GetApplicationInfo. And when |
| 217 // the web app info is available, ExtensionTabHelper notifies Browser via |
| 218 // OnDidGetApplicationInfo, which calls |
| 219 // web_app::UpdateShortcutForTabContents when it sees UPDATE_SHORTCUT as |
| 220 // pending web app action. |
| 221 app_browser->set_pending_web_app_action(Browser::UPDATE_SHORTCUT); |
| 222 } |
| 223 return tab; |
| 224 } |
| 225 |
| 226 WebContents* OpenApplicationTab(Profile* profile, |
| 227 const Extension* extension, |
| 228 const GURL& override_url, |
| 229 WindowOpenDisposition disposition) { |
| 230 Browser* browser = browser::FindTabbedBrowser(profile, false); |
| 231 WebContents* contents = NULL; |
| 232 if (!browser) { |
| 233 // No browser for this profile, need to open a new one. |
| 234 browser = Browser::Create(profile); |
| 235 browser->window()->Show(); |
| 236 // There's no current tab in this browser window, so add a new one. |
| 237 disposition = NEW_FOREGROUND_TAB; |
| 238 } else { |
| 239 // For existing browser, ensure its window is activated. |
| 240 browser->window()->Activate(); |
| 241 } |
| 242 |
| 243 // Check the prefs for overridden mode. |
| 244 ExtensionService* extension_service = profile->GetExtensionService(); |
| 245 DCHECK(extension_service); |
| 246 |
| 247 ExtensionPrefs::LaunchType launch_type = |
| 248 extension_service->extension_prefs()->GetLaunchType( |
| 249 extension->id(), ExtensionPrefs::LAUNCH_DEFAULT); |
| 250 UMA_HISTOGRAM_ENUMERATION("Extensions.AppTabLaunchType", launch_type, 100); |
| 251 |
| 252 static bool default_apps_trial_exists = |
| 253 base::FieldTrialList::TrialExists(kDefaultAppsTrialName); |
| 254 if (default_apps_trial_exists) { |
| 255 UMA_HISTOGRAM_ENUMERATION( |
| 256 base::FieldTrial::MakeName("Extensions.AppTabLaunchType", |
| 257 kDefaultAppsTrialName), |
| 258 launch_type, 100); |
| 259 } |
| 260 |
| 261 int add_type = TabStripModel::ADD_ACTIVE; |
| 262 if (launch_type == ExtensionPrefs::LAUNCH_PINNED) |
| 263 add_type |= TabStripModel::ADD_PINNED; |
| 264 |
| 265 GURL extension_url = UrlForExtension(extension, override_url); |
| 266 // TODO(erikkay): START_PAGE doesn't seem like the right transition in all |
| 267 // cases. |
| 268 browser::NavigateParams params(browser, extension_url, |
| 269 content::PAGE_TRANSITION_START_PAGE); |
| 270 params.tabstrip_add_types = add_type; |
| 271 params.disposition = disposition; |
| 272 |
| 273 if (disposition == CURRENT_TAB) { |
| 274 WebContents* existing_tab = browser->GetSelectedWebContents(); |
| 275 TabStripModel* model = browser->tab_strip_model(); |
| 276 int tab_index = model->GetWrapperIndex(existing_tab); |
| 277 |
| 278 existing_tab->OpenURL(content::OpenURLParams( |
| 279 extension_url, |
| 280 content::Referrer(existing_tab->GetURL(), |
| 281 WebKit::WebReferrerPolicyDefault), |
| 282 disposition, content::PAGE_TRANSITION_LINK, false)); |
| 283 // Reset existing_tab as OpenURL() may have clobbered it. |
| 284 existing_tab = browser->GetSelectedWebContents(); |
| 285 if (params.tabstrip_add_types & TabStripModel::ADD_PINNED) { |
| 286 model->SetTabPinned(tab_index, true); |
| 287 // Pinning may have moved the tab. |
| 288 tab_index = model->GetWrapperIndex(existing_tab); |
| 289 } |
| 290 if (params.tabstrip_add_types & TabStripModel::ADD_ACTIVE) |
| 291 model->ActivateTabAt(tab_index, true); |
| 292 |
| 293 contents = existing_tab; |
| 294 } else { |
| 295 browser::Navigate(¶ms); |
| 296 contents = params.target_contents->web_contents(); |
| 297 } |
| 298 |
| 299 #if defined(USE_ASH) |
| 300 // In ash, LAUNCH_FULLSCREEN launches in a maximized app window and it should |
| 301 // not reach here. |
| 302 DCHECK(launch_type != ExtensionPrefs::LAUNCH_FULLSCREEN); |
| 303 #else |
| 304 // TODO(skerner): If we are already in full screen mode, and the user |
| 305 // set the app to open as a regular or pinned tab, what should happen? |
| 306 // Today we open the tab, but stay in full screen mode. Should we leave |
| 307 // full screen mode in this case? |
| 308 if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN && |
| 309 !browser->window()->IsFullscreen()) { |
| 310 browser->ToggleFullscreenMode(); |
| 311 } |
| 312 #endif |
| 313 |
| 314 return contents; |
| 315 } |
| 316 |
| 317 } // namespace ApplicationLaunch |
OLD | NEW |