chrome_app_delegate.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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/favicon/favicon_tab_helper.h"
10#include "chrome/browser/file_select_helper.h"
11#include "chrome/browser/media/media_capture_devices_dispatcher.h"
12#include "chrome/browser/platform_util.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/browser/shell_integration.h"
15#include "chrome/browser/ui/browser.h"
16#include "chrome/browser/ui/browser_dialogs.h"
17#include "chrome/browser/ui/browser_tabstrip.h"
18#include "chrome/browser/ui/browser_window.h"
19#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
20#include "chrome/common/extensions/chrome_extension_messages.h"
21#include "content/public/browser/browser_context.h"
22#include "content/public/browser/render_view_host.h"
23#include "content/public/browser/web_contents.h"
24#include "content/public/browser/web_contents_delegate.h"
25#include "extensions/common/constants.h"
26
27#if defined(USE_ASH)
28#include "ash/shelf/shelf_constants.h"
29#endif
30
31#if defined(ENABLE_PRINTING)
32#if defined(ENABLE_FULL_PRINTING)
33#include "chrome/browser/printing/print_preview_message_handler.h"
34#include "chrome/browser/printing/print_view_manager.h"
35#else
36#include "chrome/browser/printing/print_view_manager_basic.h"
37#endif  // defined(ENABLE_FULL_PRINTING)
38#endif  // defined(ENABLE_PRINTING)
39
40namespace {
41
42bool disable_external_open_for_testing_ = false;
43
44// Opens a URL with Chromium (not external browser) with the right profile.
45content::WebContents* OpenURLFromTabInternal(
46    content::BrowserContext* context,
47    const content::OpenURLParams& params) {
48  // Force all links to open in a new tab, even if they were trying to open a
49  // window.
50  chrome::NavigateParams new_tab_params(
51      static_cast<Browser*>(NULL), params.url, params.transition);
52  if (params.disposition == NEW_BACKGROUND_TAB) {
53    new_tab_params.disposition = NEW_BACKGROUND_TAB;
54  } else {
55    new_tab_params.disposition = NEW_FOREGROUND_TAB;
56    new_tab_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
57  }
58
59  new_tab_params.initiating_profile = Profile::FromBrowserContext(context);
60  chrome::Navigate(&new_tab_params);
61
62  return new_tab_params.target_contents;
63}
64
65// Helper class that opens a URL based on if this browser instance is the
66// default system browser. If it is the default, open the URL directly instead
67// of asking the system to open it.
68class OpenURLFromTabBasedOnBrowserDefault
69    : public ShellIntegration::DefaultWebClientObserver {
70 public:
71  OpenURLFromTabBasedOnBrowserDefault(scoped_ptr<content::WebContents> source,
72                                      const content::OpenURLParams& params)
73      : source_(source.Pass()), params_(params) {}
74
75  // Opens a URL when called with the result of if this is the default system
76  // browser or not.
77  virtual void SetDefaultWebClientUIState(
78      ShellIntegration::DefaultWebClientUIState state) OVERRIDE {
79    Profile* profile =
80        Profile::FromBrowserContext(source_->GetBrowserContext());
81    DCHECK(profile);
82    if (!profile)
83      return;
84    switch (state) {
85      case ShellIntegration::STATE_PROCESSING:
86        break;
87      case ShellIntegration::STATE_IS_DEFAULT:
88        OpenURLFromTabInternal(profile, params_);
89        break;
90      case ShellIntegration::STATE_NOT_DEFAULT:
91      case ShellIntegration::STATE_UNKNOWN:
92        platform_util::OpenExternal(profile, params_.url);
93        break;
94    }
95  }
96
97  virtual bool IsOwnedByWorker() OVERRIDE { return true; }
98
99 private:
100  scoped_ptr<content::WebContents> source_;
101  const content::OpenURLParams params_;
102};
103
104}  // namespace
105
106class ChromeAppDelegate::NewWindowContentsDelegate
107    : public content::WebContentsDelegate {
108 public:
109  NewWindowContentsDelegate() {}
110  virtual ~NewWindowContentsDelegate() {}
111
112  virtual content::WebContents* OpenURLFromTab(
113      content::WebContents* source,
114      const content::OpenURLParams& params) OVERRIDE;
115
116 private:
117  DISALLOW_COPY_AND_ASSIGN(NewWindowContentsDelegate);
118};
119
120content::WebContents*
121ChromeAppDelegate::NewWindowContentsDelegate::OpenURLFromTab(
122    content::WebContents* source,
123    const content::OpenURLParams& params) {
124  if (source) {
125    // This NewWindowContentsDelegate was given ownership of the incoming
126    // WebContents by being assigned as its delegate within
127    // ChromeAppDelegate::AddNewContents, but this is the first time
128    // NewWindowContentsDelegate actually sees the WebContents.
129    // Here it is captured for deletion.
130    scoped_ptr<content::WebContents> owned_source(source);
131    scoped_refptr<ShellIntegration::DefaultWebClientWorker>
132        check_if_default_browser_worker =
133            new ShellIntegration::DefaultBrowserWorker(
134                new OpenURLFromTabBasedOnBrowserDefault(owned_source.Pass(),
135                                                        params));
136    // Object lifetime notes: The OpenURLFromTabBasedOnBrowserDefault is owned
137    // by check_if_default_browser_worker. StartCheckIsDefault() takes lifetime
138    // ownership of check_if_default_browser_worker and will clean up after
139    // the asynchronous tasks.
140    check_if_default_browser_worker->StartCheckIsDefault();
141  }
142  return NULL;
143}
144
145ChromeAppDelegate::ChromeAppDelegate()
146    : new_window_contents_delegate_(new NewWindowContentsDelegate()) {
147}
148
149ChromeAppDelegate::~ChromeAppDelegate() {
150}
151
152void ChromeAppDelegate::DisableExternalOpenForTesting() {
153  disable_external_open_for_testing_ = true;
154}
155
156void ChromeAppDelegate::InitWebContents(content::WebContents* web_contents) {
157  FaviconTabHelper::CreateForWebContents(web_contents);
158
159#if defined(ENABLE_PRINTING)
160#if defined(ENABLE_FULL_PRINTING)
161  printing::PrintViewManager::CreateForWebContents(web_contents);
162  printing::PrintPreviewMessageHandler::CreateForWebContents(web_contents);
163#else
164  printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
165#endif  // defined(ENABLE_FULL_PRINTING)
166#endif  // defined(ENABLE_PRINTING)
167}
168
169content::WebContents* ChromeAppDelegate::OpenURLFromTab(
170    content::BrowserContext* context,
171    content::WebContents* source,
172    const content::OpenURLParams& params) {
173  return OpenURLFromTabInternal(context, params);
174}
175
176void ChromeAppDelegate::AddNewContents(content::BrowserContext* context,
177                                       content::WebContents* new_contents,
178                                       WindowOpenDisposition disposition,
179                                       const gfx::Rect& initial_pos,
180                                       bool user_gesture,
181                                       bool* was_blocked) {
182  if (!disable_external_open_for_testing_) {
183    // We don't really want to open a window for |new_contents|, but we need to
184    // capture its intended navigation. Here we give ownership to the
185    // NewWindowContentsDelegate, which will dispose of the contents once
186    // a navigation is captured.
187    new_contents->SetDelegate(new_window_contents_delegate_.get());
188    return;
189  }
190  chrome::ScopedTabbedBrowserDisplayer displayer(
191      Profile::FromBrowserContext(context), chrome::GetActiveDesktop());
192  // Force all links to open in a new tab, even if they were trying to open a
193  // new window.
194  disposition =
195      disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
196  chrome::AddWebContents(displayer.browser(),
197                         NULL,
198                         new_contents,
199                         disposition,
200                         initial_pos,
201                         user_gesture,
202                         was_blocked);
203}
204
205content::ColorChooser* ChromeAppDelegate::ShowColorChooser(
206    content::WebContents* web_contents,
207    SkColor initial_color) {
208  return chrome::ShowColorChooser(web_contents, initial_color);
209}
210
211void ChromeAppDelegate::RunFileChooser(
212    content::WebContents* tab,
213    const content::FileChooserParams& params) {
214  FileSelectHelper::RunFileChooser(tab, params);
215}
216
217void ChromeAppDelegate::RequestMediaAccessPermission(
218    content::WebContents* web_contents,
219    const content::MediaStreamRequest& request,
220    const content::MediaResponseCallback& callback,
221    const extensions::Extension* extension) {
222  MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
223      web_contents, request, callback, extension);
224}
225
226int ChromeAppDelegate::PreferredIconSize() {
227#if defined(USE_ASH)
228  return ash::kShelfSize;
229#else
230  return extension_misc::EXTENSION_ICON_SMALL;
231#endif
232}
233
234void ChromeAppDelegate::SetWebContentsBlocked(
235    content::WebContents* web_contents,
236    bool blocked) {
237  // RenderViewHost may be NULL during shutdown.
238  content::RenderViewHost* host = web_contents->GetRenderViewHost();
239  if (host) {
240    host->Send(new ChromeViewMsg_SetVisuallyDeemphasized(host->GetRoutingID(),
241                                                         blocked));
242  }
243}
244
245bool ChromeAppDelegate::IsWebContentsVisible(
246    content::WebContents* web_contents) {
247  return platform_util::IsVisible(web_contents->GetNativeView());
248}
249