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/apps/chrome_app_delegate.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/app_mode/app_mode_utils.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
12 #include "chrome/browser/favicon/favicon_tab_helper.h"
13 #include "chrome/browser/file_select_helper.h"
14 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
15 #include "chrome/browser/platform_util.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/shell_integration.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_dialogs.h"
20 #include "chrome/browser/ui/browser_tabstrip.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
23 #include "chrome/browser/ui/web_contents_sizer.h"
24 #include "chrome/browser/ui/zoom/zoom_controller.h"
25 #include "chrome/common/extensions/chrome_extension_messages.h"
26 #include "content/public/browser/browser_context.h"
27 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/render_view_host.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/browser/web_contents_delegate.h"
31 #include "extensions/common/constants.h"
32 #include "extensions/grit/extensions_browser_resources.h"
33 #include "ui/base/resource/resource_bundle.h"
36 #include "ash/shelf/shelf_constants.h"
39 #if defined(ENABLE_PRINTING)
40 #if defined(ENABLE_FULL_PRINTING)
41 #include "chrome/browser/printing/print_preview_message_handler.h"
42 #include "chrome/browser/printing/print_view_manager.h"
44 #include "chrome/browser/printing/print_view_manager_basic.h"
45 #endif // defined(ENABLE_FULL_PRINTING)
46 #endif // defined(ENABLE_PRINTING)
50 bool disable_external_open_for_testing_
= false;
52 // Opens a URL with Chromium (not external browser) with the right profile.
53 content::WebContents
* OpenURLFromTabInternal(
54 content::BrowserContext
* context
,
55 const content::OpenURLParams
& params
) {
56 // Force all links to open in a new tab, even if they were trying to open a
58 chrome::NavigateParams
new_tab_params(
59 static_cast<Browser
*>(NULL
), params
.url
, params
.transition
);
60 if (params
.disposition
== NEW_BACKGROUND_TAB
) {
61 new_tab_params
.disposition
= NEW_BACKGROUND_TAB
;
63 new_tab_params
.disposition
= NEW_FOREGROUND_TAB
;
64 new_tab_params
.window_action
= chrome::NavigateParams::SHOW_WINDOW
;
67 new_tab_params
.initiating_profile
= Profile::FromBrowserContext(context
);
68 chrome::Navigate(&new_tab_params
);
70 return new_tab_params
.target_contents
;
73 // Helper class that opens a URL based on if this browser instance is the
74 // default system browser. If it is the default, open the URL directly instead
75 // of asking the system to open it.
76 class OpenURLFromTabBasedOnBrowserDefault
77 : public ShellIntegration::DefaultWebClientObserver
{
79 OpenURLFromTabBasedOnBrowserDefault(scoped_ptr
<content::WebContents
> source
,
80 const content::OpenURLParams
& params
)
81 : source_(source
.Pass()), params_(params
) {}
83 // Opens a URL when called with the result of if this is the default system
85 virtual void SetDefaultWebClientUIState(
86 ShellIntegration::DefaultWebClientUIState state
) OVERRIDE
{
88 Profile::FromBrowserContext(source_
->GetBrowserContext());
93 case ShellIntegration::STATE_PROCESSING
:
95 case ShellIntegration::STATE_IS_DEFAULT
:
96 OpenURLFromTabInternal(profile
, params_
);
98 case ShellIntegration::STATE_NOT_DEFAULT
:
99 case ShellIntegration::STATE_UNKNOWN
:
100 platform_util::OpenExternal(profile
, params_
.url
);
105 virtual bool IsOwnedByWorker() OVERRIDE
{ return true; }
108 scoped_ptr
<content::WebContents
> source_
;
109 const content::OpenURLParams params_
;
114 class ChromeAppDelegate::NewWindowContentsDelegate
115 : public content::WebContentsDelegate
{
117 NewWindowContentsDelegate() {}
118 virtual ~NewWindowContentsDelegate() {}
120 virtual content::WebContents
* OpenURLFromTab(
121 content::WebContents
* source
,
122 const content::OpenURLParams
& params
) OVERRIDE
;
125 DISALLOW_COPY_AND_ASSIGN(NewWindowContentsDelegate
);
128 content::WebContents
*
129 ChromeAppDelegate::NewWindowContentsDelegate::OpenURLFromTab(
130 content::WebContents
* source
,
131 const content::OpenURLParams
& params
) {
133 // This NewWindowContentsDelegate was given ownership of the incoming
134 // WebContents by being assigned as its delegate within
135 // ChromeAppDelegate::AddNewContents, but this is the first time
136 // NewWindowContentsDelegate actually sees the WebContents.
137 // Here it is captured for deletion.
138 scoped_ptr
<content::WebContents
> owned_source(source
);
139 scoped_refptr
<ShellIntegration::DefaultWebClientWorker
>
140 check_if_default_browser_worker
=
141 new ShellIntegration::DefaultBrowserWorker(
142 new OpenURLFromTabBasedOnBrowserDefault(owned_source
.Pass(),
144 // Object lifetime notes: The OpenURLFromTabBasedOnBrowserDefault is owned
145 // by check_if_default_browser_worker. StartCheckIsDefault() takes lifetime
146 // ownership of check_if_default_browser_worker and will clean up after
147 // the asynchronous tasks.
148 check_if_default_browser_worker
->StartCheckIsDefault();
153 ChromeAppDelegate::ChromeAppDelegate()
154 : new_window_contents_delegate_(new NewWindowContentsDelegate()) {
156 chrome::NOTIFICATION_APP_TERMINATING
,
157 content::NotificationService::AllSources());
160 ChromeAppDelegate::~ChromeAppDelegate() {
163 void ChromeAppDelegate::DisableExternalOpenForTesting() {
164 disable_external_open_for_testing_
= true;
167 void ChromeAppDelegate::InitWebContents(content::WebContents
* web_contents
) {
168 FaviconTabHelper::CreateForWebContents(web_contents
);
170 #if defined(ENABLE_PRINTING)
171 #if defined(ENABLE_FULL_PRINTING)
172 printing::PrintViewManager::CreateForWebContents(web_contents
);
173 printing::PrintPreviewMessageHandler::CreateForWebContents(web_contents
);
175 printing::PrintViewManagerBasic::CreateForWebContents(web_contents
);
176 #endif // defined(ENABLE_FULL_PRINTING)
177 #endif // defined(ENABLE_PRINTING)
178 extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
181 // Kiosk app supports zooming.
182 if (chrome::IsRunningInForcedAppMode())
183 ZoomController::CreateForWebContents(web_contents
);
186 void ChromeAppDelegate::ResizeWebContents(content::WebContents
* web_contents
,
187 const gfx::Size
& size
) {
188 ::ResizeWebContents(web_contents
, size
);
191 content::WebContents
* ChromeAppDelegate::OpenURLFromTab(
192 content::BrowserContext
* context
,
193 content::WebContents
* source
,
194 const content::OpenURLParams
& params
) {
195 return OpenURLFromTabInternal(context
, params
);
198 void ChromeAppDelegate::AddNewContents(content::BrowserContext
* context
,
199 content::WebContents
* new_contents
,
200 WindowOpenDisposition disposition
,
201 const gfx::Rect
& initial_pos
,
204 if (!disable_external_open_for_testing_
) {
205 // We don't really want to open a window for |new_contents|, but we need to
206 // capture its intended navigation. Here we give ownership to the
207 // NewWindowContentsDelegate, which will dispose of the contents once
208 // a navigation is captured.
209 new_contents
->SetDelegate(new_window_contents_delegate_
.get());
212 chrome::ScopedTabbedBrowserDisplayer
displayer(
213 Profile::FromBrowserContext(context
), chrome::GetActiveDesktop());
214 // Force all links to open in a new tab, even if they were trying to open a
217 disposition
== NEW_BACKGROUND_TAB
? disposition
: NEW_FOREGROUND_TAB
;
218 chrome::AddWebContents(displayer
.browser(),
227 content::ColorChooser
* ChromeAppDelegate::ShowColorChooser(
228 content::WebContents
* web_contents
,
229 SkColor initial_color
) {
230 return chrome::ShowColorChooser(web_contents
, initial_color
);
233 void ChromeAppDelegate::RunFileChooser(
234 content::WebContents
* tab
,
235 const content::FileChooserParams
& params
) {
236 FileSelectHelper::RunFileChooser(tab
, params
);
239 void ChromeAppDelegate::RequestMediaAccessPermission(
240 content::WebContents
* web_contents
,
241 const content::MediaStreamRequest
& request
,
242 const content::MediaResponseCallback
& callback
,
243 const extensions::Extension
* extension
) {
244 MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
245 web_contents
, request
, callback
, extension
);
248 bool ChromeAppDelegate::CheckMediaAccessPermission(
249 content::WebContents
* web_contents
,
250 const GURL
& security_origin
,
251 content::MediaStreamType type
,
252 const extensions::Extension
* extension
) {
253 return MediaCaptureDevicesDispatcher::GetInstance()
254 ->CheckMediaAccessPermission(
255 web_contents
, security_origin
, type
, extension
);
258 int ChromeAppDelegate::PreferredIconSize() {
260 return ash::kShelfSize
;
262 return extension_misc::EXTENSION_ICON_SMALL
;
266 gfx::ImageSkia
ChromeAppDelegate::GetAppDefaultIcon() {
267 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
268 IDR_APP_DEFAULT_ICON
);
271 void ChromeAppDelegate::SetWebContentsBlocked(
272 content::WebContents
* web_contents
,
274 // RenderViewHost may be NULL during shutdown.
275 content::RenderViewHost
* host
= web_contents
->GetRenderViewHost();
277 host
->Send(new ChromeViewMsg_SetVisuallyDeemphasized(host
->GetRoutingID(),
282 bool ChromeAppDelegate::IsWebContentsVisible(
283 content::WebContents
* web_contents
) {
284 return platform_util::IsVisible(web_contents
->GetNativeView());
287 void ChromeAppDelegate::SetTerminatingCallback(const base::Closure
& callback
) {
288 terminating_callback_
= callback
;
291 void ChromeAppDelegate::Observe(int type
,
292 const content::NotificationSource
& source
,
293 const content::NotificationDetails
& details
) {
295 case chrome::NOTIFICATION_APP_TERMINATING
:
296 if (!terminating_callback_
.is_null())
297 terminating_callback_
.Run();
300 NOTREACHED() << "Received unexpected notification";