Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / apps / chrome_app_delegate.cc
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/apps/chrome_app_delegate.h"
6
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"
33
34 #if defined(USE_ASH)
35 #include "ash/shelf/shelf_constants.h"
36 #endif
37
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"
42 #else
43 #include "chrome/browser/printing/print_view_manager_basic.h"
44 #endif  // defined(ENABLE_FULL_PRINTING)
45 #endif  // defined(ENABLE_PRINTING)
46
47 namespace {
48
49 bool disable_external_open_for_testing_ = false;
50
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
56   // window.
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;
61   } else {
62     new_tab_params.disposition = NEW_FOREGROUND_TAB;
63     new_tab_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
64   }
65
66   new_tab_params.initiating_profile = Profile::FromBrowserContext(context);
67   chrome::Navigate(&new_tab_params);
68
69   return new_tab_params.target_contents;
70 }
71
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 {
77  public:
78   OpenURLFromTabBasedOnBrowserDefault(scoped_ptr<content::WebContents> source,
79                                       const content::OpenURLParams& params)
80       : source_(source.Pass()), params_(params) {}
81
82   // Opens a URL when called with the result of if this is the default system
83   // browser or not.
84   virtual void SetDefaultWebClientUIState(
85       ShellIntegration::DefaultWebClientUIState state) OVERRIDE {
86     Profile* profile =
87         Profile::FromBrowserContext(source_->GetBrowserContext());
88     DCHECK(profile);
89     if (!profile)
90       return;
91     switch (state) {
92       case ShellIntegration::STATE_PROCESSING:
93         break;
94       case ShellIntegration::STATE_IS_DEFAULT:
95         OpenURLFromTabInternal(profile, params_);
96         break;
97       case ShellIntegration::STATE_NOT_DEFAULT:
98       case ShellIntegration::STATE_UNKNOWN:
99         platform_util::OpenExternal(profile, params_.url);
100         break;
101     }
102   }
103
104   virtual bool IsOwnedByWorker() OVERRIDE { return true; }
105
106  private:
107   scoped_ptr<content::WebContents> source_;
108   const content::OpenURLParams params_;
109 };
110
111 }  // namespace
112
113 class ChromeAppDelegate::NewWindowContentsDelegate
114     : public content::WebContentsDelegate {
115  public:
116   NewWindowContentsDelegate() {}
117   virtual ~NewWindowContentsDelegate() {}
118
119   virtual content::WebContents* OpenURLFromTab(
120       content::WebContents* source,
121       const content::OpenURLParams& params) OVERRIDE;
122
123  private:
124   DISALLOW_COPY_AND_ASSIGN(NewWindowContentsDelegate);
125 };
126
127 content::WebContents*
128 ChromeAppDelegate::NewWindowContentsDelegate::OpenURLFromTab(
129     content::WebContents* source,
130     const content::OpenURLParams& params) {
131   if (source) {
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(),
142                                                         params));
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();
148   }
149   return NULL;
150 }
151
152 ChromeAppDelegate::ChromeAppDelegate(scoped_ptr<ScopedKeepAlive> keep_alive)
153     : keep_alive_(keep_alive.Pass()),
154       new_window_contents_delegate_(new NewWindowContentsDelegate()) {
155   registrar_.Add(this,
156                  chrome::NOTIFICATION_APP_TERMINATING,
157                  content::NotificationService::AllSources());
158 }
159
160 ChromeAppDelegate::~ChromeAppDelegate() {
161   // Unregister now to prevent getting notified if |keep_alive_| is the last.
162   terminating_callback_.Reset();
163 }
164
165 void ChromeAppDelegate::DisableExternalOpenForTesting() {
166   disable_external_open_for_testing_ = true;
167 }
168
169 void ChromeAppDelegate::InitWebContents(content::WebContents* web_contents) {
170   FaviconTabHelper::CreateForWebContents(web_contents);
171
172 #if defined(ENABLE_PRINTING)
173 #if defined(ENABLE_FULL_PRINTING)
174   printing::PrintViewManager::CreateForWebContents(web_contents);
175   printing::PrintPreviewMessageHandler::CreateForWebContents(web_contents);
176 #else
177   printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
178 #endif  // defined(ENABLE_FULL_PRINTING)
179 #endif  // defined(ENABLE_PRINTING)
180   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
181       web_contents);
182
183   // Kiosk app supports zooming.
184   if (chrome::IsRunningInForcedAppMode())
185     ZoomController::CreateForWebContents(web_contents);
186 }
187
188 void ChromeAppDelegate::ResizeWebContents(content::WebContents* web_contents,
189                                           const gfx::Size& size) {
190   ::ResizeWebContents(web_contents, size);
191 }
192
193 content::WebContents* ChromeAppDelegate::OpenURLFromTab(
194     content::BrowserContext* context,
195     content::WebContents* source,
196     const content::OpenURLParams& params) {
197   return OpenURLFromTabInternal(context, params);
198 }
199
200 void ChromeAppDelegate::AddNewContents(content::BrowserContext* context,
201                                        content::WebContents* new_contents,
202                                        WindowOpenDisposition disposition,
203                                        const gfx::Rect& initial_pos,
204                                        bool user_gesture,
205                                        bool* was_blocked) {
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());
212     return;
213   }
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
217   // new window.
218   disposition =
219       disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
220   chrome::AddWebContents(displayer.browser(),
221                          NULL,
222                          new_contents,
223                          disposition,
224                          initial_pos,
225                          user_gesture,
226                          was_blocked);
227 }
228
229 content::ColorChooser* ChromeAppDelegate::ShowColorChooser(
230     content::WebContents* web_contents,
231     SkColor initial_color) {
232   return chrome::ShowColorChooser(web_contents, initial_color);
233 }
234
235 void ChromeAppDelegate::RunFileChooser(
236     content::WebContents* tab,
237     const content::FileChooserParams& params) {
238   FileSelectHelper::RunFileChooser(tab, params);
239 }
240
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);
248 }
249
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);
258 }
259
260 int ChromeAppDelegate::PreferredIconSize() {
261 #if defined(USE_ASH)
262   return ash::kShelfSize;
263 #else
264   return extension_misc::EXTENSION_ICON_SMALL;
265 #endif
266 }
267
268 void ChromeAppDelegate::SetWebContentsBlocked(
269     content::WebContents* web_contents,
270     bool blocked) {
271   // RenderViewHost may be NULL during shutdown.
272   content::RenderViewHost* host = web_contents->GetRenderViewHost();
273   if (host) {
274     host->Send(new ChromeViewMsg_SetVisuallyDeemphasized(host->GetRoutingID(),
275                                                          blocked));
276   }
277 }
278
279 bool ChromeAppDelegate::IsWebContentsVisible(
280     content::WebContents* web_contents) {
281   return platform_util::IsVisible(web_contents->GetNativeView());
282 }
283
284 void ChromeAppDelegate::SetTerminatingCallback(const base::Closure& callback) {
285   terminating_callback_ = callback;
286 }
287
288 void ChromeAppDelegate::Observe(int type,
289                                 const content::NotificationSource& source,
290                                 const content::NotificationDetails& details) {
291   switch (type) {
292     case chrome::NOTIFICATION_APP_TERMINATING:
293       if (!terminating_callback_.is_null())
294         terminating_callback_.Run();
295       break;
296     default:
297       NOTREACHED() << "Received unexpected notification";
298   }
299 }