Home | History | Annotate | Download | only in apps
      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_window_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/render_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 
     40 namespace {
     41 
     42 bool disable_external_open_for_testing_ = false;
     43 
     44 // Opens a URL with Chromium (not external browser) with the right profile.
     45 content::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.
     68 class 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 
    106 class ChromeAppWindowDelegate::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 
    120 content::WebContents*
    121 ChromeAppWindowDelegate::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     // ChromeAppWindowDelegate::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 
    145 ChromeAppWindowDelegate::ChromeAppWindowDelegate()
    146     : new_window_contents_delegate_(new NewWindowContentsDelegate()) {}
    147 
    148 ChromeAppWindowDelegate::~ChromeAppWindowDelegate() {}
    149 
    150 void ChromeAppWindowDelegate::DisableExternalOpenForTesting() {
    151   disable_external_open_for_testing_ = true;
    152 }
    153 
    154 void ChromeAppWindowDelegate::InitWebContents(
    155     content::WebContents* web_contents) {
    156   FaviconTabHelper::CreateForWebContents(web_contents);
    157 
    158 #if defined(ENABLE_PRINTING)
    159 #if defined(ENABLE_FULL_PRINTING)
    160   printing::PrintViewManager::CreateForWebContents(web_contents);
    161   printing::PrintPreviewMessageHandler::CreateForWebContents(web_contents);
    162 #else
    163   printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
    164 #endif  // defined(ENABLE_FULL_PRINTING)
    165 #endif  // defined(ENABLE_PRINTING)
    166 }
    167 
    168 apps::NativeAppWindow* ChromeAppWindowDelegate::CreateNativeAppWindow(
    169     apps::AppWindow* window,
    170     const apps::AppWindow::CreateParams& params) {
    171   return CreateNativeAppWindowImpl(window, params);
    172 }
    173 
    174 content::WebContents* ChromeAppWindowDelegate::OpenURLFromTab(
    175     content::BrowserContext* context,
    176     content::WebContents* source,
    177     const content::OpenURLParams& params) {
    178   return OpenURLFromTabInternal(context, params);
    179 }
    180 
    181 void ChromeAppWindowDelegate::AddNewContents(content::BrowserContext* context,
    182                                              content::WebContents* new_contents,
    183                                              WindowOpenDisposition disposition,
    184                                              const gfx::Rect& initial_pos,
    185                                              bool user_gesture,
    186                                              bool* was_blocked) {
    187   if (!disable_external_open_for_testing_) {
    188     // We don't really want to open a window for |new_contents|, but we need to
    189     // capture its intended navigation. Here we give ownership to the
    190     // NewWindowContentsDelegate, which will dispose of the contents once
    191     // a navigation is captured.
    192     new_contents->SetDelegate(new_window_contents_delegate_.get());
    193     return;
    194   }
    195   chrome::ScopedTabbedBrowserDisplayer displayer(
    196       Profile::FromBrowserContext(context), chrome::GetActiveDesktop());
    197   // Force all links to open in a new tab, even if they were trying to open a
    198   // new window.
    199   disposition =
    200       disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
    201   chrome::AddWebContents(displayer.browser(), NULL, new_contents, disposition,
    202                          initial_pos, user_gesture, was_blocked);
    203 }
    204 
    205 content::ColorChooser* ChromeAppWindowDelegate::ShowColorChooser(
    206     content::WebContents* web_contents,
    207     SkColor initial_color) {
    208   return chrome::ShowColorChooser(web_contents, initial_color);
    209 }
    210 
    211 void ChromeAppWindowDelegate::RunFileChooser(
    212     content::WebContents* tab,
    213     const content::FileChooserParams& params) {
    214   FileSelectHelper::RunFileChooser(tab, params);
    215 }
    216 
    217 void ChromeAppWindowDelegate::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 
    226 int ChromeAppWindowDelegate::PreferredIconSize() {
    227 #if defined(USE_ASH)
    228   return ash::kShelfSize;
    229 #else
    230   return extension_misc::EXTENSION_ICON_SMALL;
    231 #endif
    232 }
    233 
    234 void ChromeAppWindowDelegate::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(
    241         host->GetRoutingID(), blocked));
    242   }
    243 }
    244 
    245 bool ChromeAppWindowDelegate::IsWebContentsVisible(
    246     content::WebContents* web_contents) {
    247   return platform_util::IsVisible(web_contents->GetNativeView());
    248 }
    249