Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / ui / extensions / application_launch.cc
blob828809d696c5540878e54e1c096e670279ff3687
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.
5 #include "chrome/browser/ui/extensions/application_launch.h"
7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h"
9 #include "chrome/browser/extensions/extension_prefs.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/platform_app_launcher.h"
12 #include "chrome/browser/extensions/tab_helper.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/browser_tabstrip.h"
18 #include "chrome/browser/ui/browser_window.h"
19 #include "chrome/browser/ui/tab_contents/tab_contents.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/browser/web_applications/web_app.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/extensions/extension.h"
24 #include "chrome/common/extensions/extension_constants.h"
25 #include "chrome/common/url_constants.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/browser/web_contents_view.h"
29 #include "content/public/common/renderer_preferences.h"
30 #include "ui/gfx/rect.h"
32 #if defined(OS_WIN)
33 #include "base/win/metro.h"
34 #endif
36 using content::WebContents;
37 using extensions::Extension;
38 using extensions::ExtensionPrefs;
40 namespace {
42 // Get the launch URL for a given extension, with optional override/fallback.
43 // |override_url|, if non-empty, will be preferred over the extension's
44 // launch url.
45 GURL UrlForExtension(const Extension* extension,
46 const GURL& override_url) {
47 if (!extension)
48 return override_url;
50 GURL url;
51 if (!override_url.is_empty()) {
52 DCHECK(extension->web_extent().MatchesURL(override_url) ||
53 override_url.GetOrigin() == extension->url());
54 url = override_url;
55 } else {
56 url = extension->GetFullLaunchURL();
59 // For extensions lacking launch urls, determine a reasonable fallback.
60 if (!url.is_valid()) {
61 url = extension->options_url();
62 if (!url.is_valid())
63 url = GURL(chrome::kChromeUIExtensionsURL);
66 return url;
69 WebContents* OpenApplicationWindow(
70 Profile* profile,
71 const Extension* extension,
72 extension_misc::LaunchContainer container,
73 const GURL& url_input,
74 Browser** app_browser,
75 const gfx::Rect& override_bounds) {
76 DCHECK(!url_input.is_empty() || extension);
77 GURL url = UrlForExtension(extension, url_input);
79 std::string app_name;
80 app_name = extension ?
81 web_app::GenerateApplicationNameFromExtensionId(extension->id()) :
82 web_app::GenerateApplicationNameFromURL(url);
84 Browser::Type type = Browser::TYPE_POPUP;
86 gfx::Rect window_bounds;
87 if (extension) {
88 window_bounds.set_width(extension->launch_width());
89 window_bounds.set_height(extension->launch_height());
90 } else if (!override_bounds.IsEmpty()) {
91 window_bounds = override_bounds;
94 Browser::CreateParams params(type, profile);
95 params.app_name = app_name;
96 params.initial_bounds = window_bounds;
98 #if defined(USE_ASH)
99 if (extension &&
100 container == extension_misc::LAUNCH_WINDOW) {
101 // In ash, LAUNCH_FULLSCREEN launches in a maximized app window and
102 // LAUNCH_WINDOW launches in a normal app window.
103 ExtensionPrefs::LaunchType launch_type =
104 profile->GetExtensionService()->extension_prefs()->GetLaunchType(
105 extension->id(), ExtensionPrefs::LAUNCH_DEFAULT);
106 if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN)
107 params.initial_show_state = ui::SHOW_STATE_MAXIMIZED;
108 else if (launch_type == ExtensionPrefs::LAUNCH_WINDOW)
109 params.initial_show_state = ui::SHOW_STATE_NORMAL;
111 #endif
113 Browser* browser = NULL;
114 #if defined(OS_WIN)
115 // In Chrome on Windows 8 in metro mode we don't allow multiple chrome
116 // windows to be created, as we don't have a good way to switch between
117 // them. We attempt to reuse an existing Browser window.
118 if (base::win::IsMetroProcess()) {
119 browser = browser::FindBrowserWithProfile(
120 profile, chrome::HOST_DESKTOP_TYPE_NATIVE);
122 #endif
123 if (!browser)
124 browser = new Browser(params);
126 if (app_browser)
127 *app_browser = browser;
129 WebContents* web_contents = chrome::AddSelectedTabWithURL(
130 browser, url, content::PAGE_TRANSITION_AUTO_TOPLEVEL);
131 web_contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
132 web_contents->GetRenderViewHost()->SyncRendererPrefs();
134 browser->window()->Show();
136 // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
137 // focus explicitly.
138 web_contents->GetView()->SetInitialFocus();
139 return web_contents;
142 WebContents* OpenApplicationTab(Profile* profile,
143 const Extension* extension,
144 const GURL& override_url,
145 WindowOpenDisposition disposition) {
146 Browser* browser = browser::FindTabbedBrowserDeprecated(profile, false);
147 WebContents* contents = NULL;
148 if (!browser) {
149 // No browser for this profile, need to open a new one.
150 browser = new Browser(Browser::CreateParams(profile));
151 browser->window()->Show();
152 // There's no current tab in this browser window, so add a new one.
153 disposition = NEW_FOREGROUND_TAB;
154 } else {
155 // For existing browser, ensure its window is activated.
156 browser->window()->Activate();
159 // Check the prefs for overridden mode.
160 ExtensionService* extension_service = profile->GetExtensionService();
161 DCHECK(extension_service);
163 ExtensionPrefs::LaunchType launch_type =
164 extension_service->extension_prefs()->GetLaunchType(
165 extension->id(), ExtensionPrefs::LAUNCH_DEFAULT);
166 UMA_HISTOGRAM_ENUMERATION("Extensions.AppTabLaunchType", launch_type, 100);
168 int add_type = TabStripModel::ADD_ACTIVE;
169 if (launch_type == ExtensionPrefs::LAUNCH_PINNED)
170 add_type |= TabStripModel::ADD_PINNED;
172 GURL extension_url = UrlForExtension(extension, override_url);
173 // TODO(erikkay): START_PAGE doesn't seem like the right transition in all
174 // cases.
175 chrome::NavigateParams params(browser, extension_url,
176 content::PAGE_TRANSITION_AUTO_TOPLEVEL);
177 params.tabstrip_add_types = add_type;
178 params.disposition = disposition;
180 if (disposition == CURRENT_TAB) {
181 WebContents* existing_tab = chrome::GetActiveWebContents(browser);
182 TabStripModel* model = browser->tab_strip_model();
183 int tab_index = model->GetIndexOfWebContents(existing_tab);
185 existing_tab->OpenURL(content::OpenURLParams(
186 extension_url,
187 content::Referrer(existing_tab->GetURL(),
188 WebKit::WebReferrerPolicyDefault),
189 disposition, content::PAGE_TRANSITION_LINK, false));
190 // Reset existing_tab as OpenURL() may have clobbered it.
191 existing_tab = chrome::GetActiveWebContents(browser);
192 if (params.tabstrip_add_types & TabStripModel::ADD_PINNED) {
193 model->SetTabPinned(tab_index, true);
194 // Pinning may have moved the tab.
195 tab_index = model->GetIndexOfWebContents(existing_tab);
197 if (params.tabstrip_add_types & TabStripModel::ADD_ACTIVE)
198 model->ActivateTabAt(tab_index, true);
200 contents = existing_tab;
201 } else {
202 chrome::Navigate(&params);
203 contents = params.target_contents->web_contents();
206 #if defined(USE_ASH)
207 // In ash, LAUNCH_FULLSCREEN launches in a maximized app window and it should
208 // not reach here.
209 DCHECK(launch_type != ExtensionPrefs::LAUNCH_FULLSCREEN);
210 #else
211 // TODO(skerner): If we are already in full screen mode, and the user
212 // set the app to open as a regular or pinned tab, what should happen?
213 // Today we open the tab, but stay in full screen mode. Should we leave
214 // full screen mode in this case?
215 if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN &&
216 !browser->window()->IsFullscreen()) {
217 chrome::ToggleFullscreenMode(browser);
219 #endif
221 return contents;
224 } // namespace
226 namespace application_launch {
228 LaunchParams::LaunchParams(Profile* profile,
229 const extensions::Extension* extension,
230 extension_misc::LaunchContainer container,
231 WindowOpenDisposition disposition)
232 : profile(profile),
233 extension(extension),
234 container(container),
235 disposition(disposition),
236 override_url(),
237 command_line(NULL) {}
239 WebContents* OpenApplication(const LaunchParams& params) {
240 Profile* profile = params.profile;
241 const extensions::Extension* extension = params.extension;
242 extension_misc::LaunchContainer container = params.container;
243 const GURL& override_url = params.override_url;
245 WebContents* tab = NULL;
246 ExtensionPrefs* prefs = profile->GetExtensionService()->extension_prefs();
247 prefs->SetActiveBit(extension->id(), true);
249 UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100);
251 if (extension->is_platform_app()) {
252 extensions::LaunchPlatformApp(profile, extension, params.command_line,
253 params.current_directory);
254 return NULL;
257 switch (container) {
258 case extension_misc::LAUNCH_NONE: {
259 NOTREACHED();
260 break;
262 case extension_misc::LAUNCH_PANEL:
263 case extension_misc::LAUNCH_WINDOW:
264 tab = OpenApplicationWindow(profile, extension, container,
265 override_url, NULL, gfx::Rect());
266 break;
267 case extension_misc::LAUNCH_TAB: {
268 tab = OpenApplicationTab(profile, extension, override_url,
269 params.disposition);
270 break;
272 default:
273 NOTREACHED();
274 break;
276 return tab;
279 WebContents* OpenAppShortcutWindow(Profile* profile,
280 const GURL& url,
281 const gfx::Rect& override_bounds) {
282 Browser* app_browser;
283 WebContents* tab = OpenApplicationWindow(
284 profile,
285 NULL, // this is a URL app. No extension.
286 extension_misc::LAUNCH_WINDOW,
287 url,
288 &app_browser,
289 override_bounds);
291 if (!tab)
292 return NULL;
294 // Set UPDATE_SHORTCUT as the pending web app action. This action is picked
295 // up in LoadingStateChanged to schedule a GetApplicationInfo. And when
296 // the web app info is available, extensions::TabHelper notifies Browser via
297 // OnDidGetApplicationInfo, which calls
298 // web_app::UpdateShortcutForTabContents when it sees UPDATE_SHORTCUT as
299 // pending web app action.
300 extensions::TabHelper::FromWebContents(tab)->set_pending_web_app_action(
301 extensions::TabHelper::UPDATE_SHORTCUT);
303 return tab;
306 } // namespace application_launch