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/apps/scoped_keep_alive.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
13 #include "chrome/browser/favicon/favicon_tab_helper.h"
14 #include "chrome/browser/file_select_helper.h"
15 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
16 #include "chrome/browser/platform_util.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/shell_integration.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/browser_dialogs.h"
21 #include "chrome/browser/ui/browser_tabstrip.h"
22 #include "chrome/browser/ui/browser_window.h"
23 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
24 #include "chrome/browser/ui/web_contents_sizer.h"
25 #include "chrome/browser/ui/zoom/zoom_controller.h"
26 #include "chrome/common/extensions/chrome_extension_messages.h"
27 #include "content/public/browser/browser_context.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/browser/web_contents_delegate.h"
32 #include "extensions/common/constants.h"
35 #include "ash/shelf/shelf_constants.h"
38 #if defined(ENABLE_PRINTING)
39 #if defined(ENABLE_FULL_PRINTING)
40 #include "chrome/browser/printing/print_preview_message_handler.h"
41 #include "chrome/browser/printing/print_view_manager.h"
43 #include "chrome/browser/printing/print_view_manager_basic.h"
44 #endif // defined(ENABLE_FULL_PRINTING)
45 #endif // defined(ENABLE_PRINTING)
49 bool disable_external_open_for_testing_ = false;
51 // Opens a URL with Chromium (not external browser) with the right profile.
52 content::WebContents* OpenURLFromTabInternal(
53 content::BrowserContext* context,
54 const content::OpenURLParams& params) {
55 // Force all links to open in a new tab, even if they were trying to open a
57 chrome::NavigateParams new_tab_params(
58 static_cast<Browser*>(NULL), params.url, params.transition);
59 if (params.disposition == NEW_BACKGROUND_TAB) {
60 new_tab_params.disposition = NEW_BACKGROUND_TAB;
62 new_tab_params.disposition = NEW_FOREGROUND_TAB;
63 new_tab_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
66 new_tab_params.initiating_profile = Profile::FromBrowserContext(context);
67 chrome::Navigate(&new_tab_params);
69 return new_tab_params.target_contents;
72 // Helper class that opens a URL based on if this browser instance is the
73 // default system browser. If it is the default, open the URL directly instead
74 // of asking the system to open it.
75 class OpenURLFromTabBasedOnBrowserDefault
76 : public ShellIntegration::DefaultWebClientObserver {
78 OpenURLFromTabBasedOnBrowserDefault(scoped_ptr<content::WebContents> source,
79 const content::OpenURLParams& params)
80 : source_(source.Pass()), params_(params) {}
82 // Opens a URL when called with the result of if this is the default system
84 virtual void SetDefaultWebClientUIState(
85 ShellIntegration::DefaultWebClientUIState state) OVERRIDE {
87 Profile::FromBrowserContext(source_->GetBrowserContext());
92 case ShellIntegration::STATE_PROCESSING:
94 case ShellIntegration::STATE_IS_DEFAULT:
95 OpenURLFromTabInternal(profile, params_);
97 case ShellIntegration::STATE_NOT_DEFAULT:
98 case ShellIntegration::STATE_UNKNOWN:
99 platform_util::OpenExternal(profile, params_.url);
104 virtual bool IsOwnedByWorker() OVERRIDE { return true; }
107 scoped_ptr<content::WebContents> source_;
108 const content::OpenURLParams params_;
113 class ChromeAppDelegate::NewWindowContentsDelegate
114 : public content::WebContentsDelegate {
116 NewWindowContentsDelegate() {}
117 virtual ~NewWindowContentsDelegate() {}
119 virtual content::WebContents* OpenURLFromTab(
120 content::WebContents* source,
121 const content::OpenURLParams& params) OVERRIDE;
124 DISALLOW_COPY_AND_ASSIGN(NewWindowContentsDelegate);
127 content::WebContents*
128 ChromeAppDelegate::NewWindowContentsDelegate::OpenURLFromTab(
129 content::WebContents* source,
130 const content::OpenURLParams& params) {
132 // This NewWindowContentsDelegate was given ownership of the incoming
133 // WebContents by being assigned as its delegate within
134 // ChromeAppDelegate::AddNewContents, but this is the first time
135 // NewWindowContentsDelegate actually sees the WebContents.
136 // Here it is captured for deletion.
137 scoped_ptr<content::WebContents> owned_source(source);
138 scoped_refptr<ShellIntegration::DefaultWebClientWorker>
139 check_if_default_browser_worker =
140 new ShellIntegration::DefaultBrowserWorker(
141 new OpenURLFromTabBasedOnBrowserDefault(owned_source.Pass(),
143 // Object lifetime notes: The OpenURLFromTabBasedOnBrowserDefault is owned
144 // by check_if_default_browser_worker. StartCheckIsDefault() takes lifetime
145 // ownership of check_if_default_browser_worker and will clean up after
146 // the asynchronous tasks.
147 check_if_default_browser_worker->StartCheckIsDefault();
152 ChromeAppDelegate::ChromeAppDelegate(scoped_ptr<ScopedKeepAlive> keep_alive)
153 : keep_alive_(keep_alive.Pass()),
154 new_window_contents_delegate_(new NewWindowContentsDelegate()) {
156 chrome::NOTIFICATION_APP_TERMINATING,
157 content::NotificationService::AllSources());
160 ChromeAppDelegate::~ChromeAppDelegate() {
161 // Unregister now to prevent getting notified if |keep_alive_| is the last.
162 terminating_callback_.Reset();
165 void ChromeAppDelegate::DisableExternalOpenForTesting() {
166 disable_external_open_for_testing_ = true;
169 void ChromeAppDelegate::InitWebContents(content::WebContents* web_contents) {
170 FaviconTabHelper::CreateForWebContents(web_contents);
172 #if defined(ENABLE_PRINTING)
173 #if defined(ENABLE_FULL_PRINTING)
174 printing::PrintViewManager::CreateForWebContents(web_contents);
175 printing::PrintPreviewMessageHandler::CreateForWebContents(web_contents);
177 printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
178 #endif // defined(ENABLE_FULL_PRINTING)
179 #endif // defined(ENABLE_PRINTING)
180 extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
183 // Kiosk app supports zooming.
184 if (chrome::IsRunningInForcedAppMode())
185 ZoomController::CreateForWebContents(web_contents);
188 void ChromeAppDelegate::ResizeWebContents(content::WebContents* web_contents,
189 const gfx::Size& size) {
190 ::ResizeWebContents(web_contents, size);
193 content::WebContents* ChromeAppDelegate::OpenURLFromTab(
194 content::BrowserContext* context,
195 content::WebContents* source,
196 const content::OpenURLParams& params) {
197 return OpenURLFromTabInternal(context, params);
200 void ChromeAppDelegate::AddNewContents(content::BrowserContext* context,
201 content::WebContents* new_contents,
202 WindowOpenDisposition disposition,
203 const gfx::Rect& initial_pos,
206 if (!disable_external_open_for_testing_) {
207 // We don't really want to open a window for |new_contents|, but we need to
208 // capture its intended navigation. Here we give ownership to the
209 // NewWindowContentsDelegate, which will dispose of the contents once
210 // a navigation is captured.
211 new_contents->SetDelegate(new_window_contents_delegate_.get());
214 chrome::ScopedTabbedBrowserDisplayer displayer(
215 Profile::FromBrowserContext(context), chrome::GetActiveDesktop());
216 // Force all links to open in a new tab, even if they were trying to open a
219 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
220 chrome::AddWebContents(displayer.browser(),
229 content::ColorChooser* ChromeAppDelegate::ShowColorChooser(
230 content::WebContents* web_contents,
231 SkColor initial_color) {
232 return chrome::ShowColorChooser(web_contents, initial_color);
235 void ChromeAppDelegate::RunFileChooser(
236 content::WebContents* tab,
237 const content::FileChooserParams& params) {
238 FileSelectHelper::RunFileChooser(tab, params);
241 void ChromeAppDelegate::RequestMediaAccessPermission(
242 content::WebContents* web_contents,
243 const content::MediaStreamRequest& request,
244 const content::MediaResponseCallback& callback,
245 const extensions::Extension* extension) {
246 MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
247 web_contents, request, callback, extension);
250 bool ChromeAppDelegate::CheckMediaAccessPermission(
251 content::WebContents* web_contents,
252 const GURL& security_origin,
253 content::MediaStreamType type,
254 const extensions::Extension* extension) {
255 return MediaCaptureDevicesDispatcher::GetInstance()
256 ->CheckMediaAccessPermission(
257 web_contents, security_origin, type, extension);
260 int ChromeAppDelegate::PreferredIconSize() {
262 return ash::kShelfSize;
264 return extension_misc::EXTENSION_ICON_SMALL;
268 void ChromeAppDelegate::SetWebContentsBlocked(
269 content::WebContents* web_contents,
271 // RenderViewHost may be NULL during shutdown.
272 content::RenderViewHost* host = web_contents->GetRenderViewHost();
274 host->Send(new ChromeViewMsg_SetVisuallyDeemphasized(host->GetRoutingID(),
279 bool ChromeAppDelegate::IsWebContentsVisible(
280 content::WebContents* web_contents) {
281 return platform_util::IsVisible(web_contents->GetNativeView());
284 void ChromeAppDelegate::SetTerminatingCallback(const base::Closure& callback) {
285 terminating_callback_ = callback;
288 void ChromeAppDelegate::Observe(int type,
289 const content::NotificationSource& source,
290 const content::NotificationDetails& details) {
292 case chrome::NOTIFICATION_APP_TERMINATING:
293 if (!terminating_callback_.is_null())
294 terminating_callback_.Run();
297 NOTREACHED() << "Received unexpected notification";