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