1 // Copyright (c) 2011 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/tab_contents/render_view_host_delegate_helper.h" 6 7 #include <string> 8 9 #include "base/command_line.h" 10 #include "base/string_util.h" 11 #include "base/utf_string_conversions.h" 12 #include "chrome/browser/background_contents_service.h" 13 #include "chrome/browser/background_contents_service_factory.h" 14 #include "chrome/browser/character_encoding.h" 15 #include "chrome/browser/extensions/extension_service.h" 16 #include "chrome/browser/gpu_data_manager.h" 17 #include "chrome/browser/prefs/pref_service.h" 18 #include "chrome/browser/prefs/scoped_user_pref_update.h" 19 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/tab_contents/background_contents.h" 21 #include "chrome/browser/user_style_sheet_watcher.h" 22 #include "chrome/common/chrome_switches.h" 23 #include "chrome/common/pref_names.h" 24 #include "content/browser/renderer_host/render_view_host.h" 25 #include "content/browser/renderer_host/render_process_host.h" 26 #include "content/browser/renderer_host/render_widget_fullscreen_host.h" 27 #include "content/browser/renderer_host/render_widget_host.h" 28 #include "content/browser/renderer_host/render_widget_host_view.h" 29 #include "content/browser/site_instance.h" 30 #include "content/browser/tab_contents/tab_contents.h" 31 #include "content/browser/tab_contents/tab_contents_view.h" 32 #include "content/browser/webui/web_ui.h" 33 34 RenderViewHostDelegateViewHelper::RenderViewHostDelegateViewHelper() {} 35 36 RenderViewHostDelegateViewHelper::~RenderViewHostDelegateViewHelper() {} 37 38 BackgroundContents* 39 RenderViewHostDelegateViewHelper::MaybeCreateBackgroundContents( 40 int route_id, 41 Profile* profile, 42 SiteInstance* site, 43 const GURL& opener_url, 44 const string16& frame_name) { 45 ExtensionService* extensions_service = profile->GetExtensionService(); 46 47 if (!opener_url.is_valid() || 48 frame_name.empty() || 49 !extensions_service || 50 !extensions_service->is_ready()) 51 return NULL; 52 53 // Only hosted apps have web extents, so this ensures that only hosted apps 54 // can create BackgroundContents. We don't have to check for background 55 // permission as that is checked in RenderMessageFilter when the CreateWindow 56 // message is processed. 57 const Extension* extension = 58 extensions_service->GetExtensionByWebExtent(opener_url); 59 if (!extension) 60 return NULL; 61 62 // If the extension manifest specifies a background page, then don't allow one 63 // to be created here. 64 if (extension->background_url().is_valid()) 65 return NULL; 66 67 // Only allow a single background contents per app. 68 BackgroundContentsService* service = 69 BackgroundContentsServiceFactory::GetForProfile(profile); 70 if (!service || service->GetAppBackgroundContents( 71 ASCIIToUTF16(extension->id()))) 72 return NULL; 73 74 // Ensure that we're trying to open this from the extension's process. 75 ExtensionProcessManager* process_manager = 76 profile->GetExtensionProcessManager(); 77 if (!site->GetProcess() || !process_manager || 78 site->GetProcess() != process_manager->GetExtensionProcess(opener_url)) 79 return NULL; 80 81 // Passed all the checks, so this should be created as a BackgroundContents. 82 return service->CreateBackgroundContents(site, route_id, profile, frame_name, 83 ASCIIToUTF16(extension->id())); 84 } 85 86 TabContents* RenderViewHostDelegateViewHelper::CreateNewWindow( 87 int route_id, 88 Profile* profile, 89 SiteInstance* site, 90 WebUI::TypeID webui_type, 91 RenderViewHostDelegate* opener, 92 WindowContainerType window_container_type, 93 const string16& frame_name) { 94 if (window_container_type == WINDOW_CONTAINER_TYPE_BACKGROUND) { 95 BackgroundContents* contents = MaybeCreateBackgroundContents( 96 route_id, 97 profile, 98 site, 99 opener->GetURL(), 100 frame_name); 101 if (contents) { 102 pending_contents_[route_id] = contents->render_view_host(); 103 return NULL; 104 } 105 } 106 107 // Create the new web contents. This will automatically create the new 108 // TabContentsView. In the future, we may want to create the view separately. 109 TabContents* new_contents = 110 new TabContents(profile, 111 site, 112 route_id, 113 opener->GetAsTabContents(), 114 NULL); 115 new_contents->set_opener_web_ui_type(webui_type); 116 TabContentsView* new_view = new_contents->view(); 117 118 // TODO(brettw) it seems bogus that we have to call this function on the 119 // newly created object and give it one of its own member variables. 120 new_view->CreateViewForWidget(new_contents->render_view_host()); 121 122 // Save the created window associated with the route so we can show it later. 123 pending_contents_[route_id] = new_contents->render_view_host(); 124 return new_contents; 125 } 126 127 RenderWidgetHostView* RenderViewHostDelegateViewHelper::CreateNewWidget( 128 int route_id, WebKit::WebPopupType popup_type, RenderProcessHost* process) { 129 RenderWidgetHost* widget_host = 130 new RenderWidgetHost(process, route_id); 131 RenderWidgetHostView* widget_view = 132 RenderWidgetHostView::CreateViewForWidget(widget_host); 133 // Popups should not get activated. 134 widget_view->set_popup_type(popup_type); 135 // Save the created widget associated with the route so we can show it later. 136 pending_widget_views_[route_id] = widget_view; 137 return widget_view; 138 } 139 140 RenderWidgetHostView* 141 RenderViewHostDelegateViewHelper::CreateNewFullscreenWidget( 142 int route_id, RenderProcessHost* process) { 143 RenderWidgetFullscreenHost* fullscreen_widget_host = 144 new RenderWidgetFullscreenHost(process, route_id); 145 RenderWidgetHostView* widget_view = 146 RenderWidgetHostView::CreateViewForWidget(fullscreen_widget_host); 147 pending_widget_views_[route_id] = widget_view; 148 return widget_view; 149 } 150 151 TabContents* RenderViewHostDelegateViewHelper::GetCreatedWindow(int route_id) { 152 PendingContents::iterator iter = pending_contents_.find(route_id); 153 if (iter == pending_contents_.end()) { 154 DCHECK(false); 155 return NULL; 156 } 157 158 RenderViewHost* new_rvh = iter->second; 159 pending_contents_.erase(route_id); 160 161 // The renderer crashed or it is a TabContents and has no view. 162 if (!new_rvh->process()->HasConnection() || 163 (new_rvh->delegate()->GetAsTabContents() && !new_rvh->view())) 164 return NULL; 165 166 // TODO(brettw) this seems bogus to reach into here and initialize the host. 167 new_rvh->Init(); 168 return new_rvh->delegate()->GetAsTabContents(); 169 } 170 171 RenderWidgetHostView* RenderViewHostDelegateViewHelper::GetCreatedWidget( 172 int route_id) { 173 PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); 174 if (iter == pending_widget_views_.end()) { 175 DCHECK(false); 176 return NULL; 177 } 178 179 RenderWidgetHostView* widget_host_view = iter->second; 180 pending_widget_views_.erase(route_id); 181 182 RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); 183 if (!widget_host->process()->HasConnection()) { 184 // The view has gone away or the renderer crashed. Nothing to do. 185 return NULL; 186 } 187 188 return widget_host_view; 189 } 190 191 void RenderViewHostDelegateViewHelper::RenderWidgetHostDestroyed( 192 RenderWidgetHost* host) { 193 for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); 194 i != pending_widget_views_.end(); ++i) { 195 if (host->view() == i->second) { 196 pending_widget_views_.erase(i); 197 return; 198 } 199 } 200 } 201 202 bool RenderViewHostDelegateHelper::gpu_enabled_ = true; 203 204 // static 205 WebPreferences RenderViewHostDelegateHelper::GetWebkitPrefs( 206 Profile* profile, bool is_web_ui) { 207 PrefService* prefs = profile->GetPrefs(); 208 WebPreferences web_prefs; 209 210 web_prefs.standard_font_family = 211 UTF8ToUTF16(prefs->GetString(prefs::kWebKitStandardFontFamily)); 212 web_prefs.fixed_font_family = 213 UTF8ToUTF16(prefs->GetString(prefs::kWebKitFixedFontFamily)); 214 web_prefs.serif_font_family = 215 UTF8ToUTF16(prefs->GetString(prefs::kWebKitSerifFontFamily)); 216 web_prefs.sans_serif_font_family = 217 UTF8ToUTF16(prefs->GetString(prefs::kWebKitSansSerifFontFamily)); 218 web_prefs.cursive_font_family = 219 UTF8ToUTF16(prefs->GetString(prefs::kWebKitCursiveFontFamily)); 220 web_prefs.fantasy_font_family = 221 UTF8ToUTF16(prefs->GetString(prefs::kWebKitFantasyFontFamily)); 222 223 web_prefs.default_font_size = 224 prefs->GetInteger(prefs::kWebKitDefaultFontSize); 225 web_prefs.default_fixed_font_size = 226 prefs->GetInteger(prefs::kWebKitDefaultFixedFontSize); 227 web_prefs.minimum_font_size = 228 prefs->GetInteger(prefs::kWebKitMinimumFontSize); 229 web_prefs.minimum_logical_font_size = 230 prefs->GetInteger(prefs::kWebKitMinimumLogicalFontSize); 231 232 web_prefs.default_encoding = prefs->GetString(prefs::kDefaultCharset); 233 234 web_prefs.javascript_can_open_windows_automatically = 235 prefs->GetBoolean(prefs::kWebKitJavascriptCanOpenWindowsAutomatically); 236 web_prefs.dom_paste_enabled = 237 prefs->GetBoolean(prefs::kWebKitDomPasteEnabled); 238 web_prefs.shrinks_standalone_images_to_fit = 239 prefs->GetBoolean(prefs::kWebKitShrinksStandaloneImagesToFit); 240 const DictionaryValue* inspector_settings = 241 prefs->GetDictionary(prefs::kWebKitInspectorSettings); 242 if (inspector_settings) { 243 for (DictionaryValue::key_iterator iter(inspector_settings->begin_keys()); 244 iter != inspector_settings->end_keys(); ++iter) { 245 std::string value; 246 if (inspector_settings->GetStringWithoutPathExpansion(*iter, &value)) 247 web_prefs.inspector_settings.push_back( 248 std::make_pair(*iter, value)); 249 } 250 } 251 web_prefs.tabs_to_links = prefs->GetBoolean(prefs::kWebkitTabsToLinks); 252 253 { // Command line switches are used for preferences with no user interface. 254 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 255 web_prefs.developer_extras_enabled = 256 !command_line.HasSwitch(switches::kDisableDevTools); 257 web_prefs.javascript_enabled = 258 !command_line.HasSwitch(switches::kDisableJavaScript) && 259 prefs->GetBoolean(prefs::kWebKitJavascriptEnabled); 260 web_prefs.web_security_enabled = 261 !command_line.HasSwitch(switches::kDisableWebSecurity) && 262 prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled); 263 web_prefs.plugins_enabled = 264 !command_line.HasSwitch(switches::kDisablePlugins) && 265 prefs->GetBoolean(prefs::kWebKitPluginsEnabled); 266 web_prefs.java_enabled = 267 !command_line.HasSwitch(switches::kDisableJava) && 268 prefs->GetBoolean(prefs::kWebKitJavaEnabled); 269 web_prefs.loads_images_automatically = 270 prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically); 271 web_prefs.uses_page_cache = 272 command_line.HasSwitch(switches::kEnableFastback); 273 web_prefs.remote_fonts_enabled = 274 !command_line.HasSwitch(switches::kDisableRemoteFonts); 275 web_prefs.xss_auditor_enabled = 276 !command_line.HasSwitch(switches::kDisableXSSAuditor); 277 web_prefs.application_cache_enabled = 278 !command_line.HasSwitch(switches::kDisableApplicationCache); 279 280 web_prefs.local_storage_enabled = 281 !command_line.HasSwitch(switches::kDisableLocalStorage); 282 web_prefs.databases_enabled = 283 !command_line.HasSwitch(switches::kDisableDatabases); 284 web_prefs.webaudio_enabled = 285 command_line.HasSwitch(switches::kEnableWebAudio); 286 web_prefs.experimental_webgl_enabled = 287 gpu_enabled() && 288 !command_line.HasSwitch(switches::kDisable3DAPIs) && 289 !command_line.HasSwitch(switches::kDisableExperimentalWebGL); 290 web_prefs.gl_multisampling_enabled = 291 !command_line.HasSwitch(switches::kDisableGLMultisampling); 292 web_prefs.site_specific_quirks_enabled = 293 !command_line.HasSwitch(switches::kDisableSiteSpecificQuirks); 294 web_prefs.allow_file_access_from_file_urls = 295 command_line.HasSwitch(switches::kAllowFileAccessFromFiles); 296 web_prefs.show_composited_layer_borders = 297 command_line.HasSwitch(switches::kShowCompositedLayerBorders); 298 web_prefs.show_composited_layer_tree = 299 command_line.HasSwitch(switches::kShowCompositedLayerTree); 300 web_prefs.show_fps_counter = 301 command_line.HasSwitch(switches::kShowFPSCounter); 302 web_prefs.accelerated_compositing_enabled = 303 gpu_enabled() && 304 !command_line.HasSwitch(switches::kDisableAcceleratedCompositing); 305 web_prefs.force_compositing_mode = 306 command_line.HasSwitch(switches::kForceCompositingMode); 307 web_prefs.accelerated_2d_canvas_enabled = 308 gpu_enabled() && 309 command_line.HasSwitch(switches::kEnableAccelerated2dCanvas); 310 web_prefs.accelerated_drawing_enabled = 311 gpu_enabled() && 312 command_line.HasSwitch(switches::kEnableAcceleratedDrawing); 313 web_prefs.accelerated_layers_enabled = 314 !command_line.HasSwitch(switches::kDisableAcceleratedLayers); 315 web_prefs.composite_to_texture_enabled = 316 command_line.HasSwitch(switches::kEnableCompositeToTexture); 317 web_prefs.accelerated_plugins_enabled = 318 command_line.HasSwitch(switches::kEnableAcceleratedPlugins); 319 web_prefs.accelerated_video_enabled = 320 !command_line.HasSwitch(switches::kDisableAcceleratedVideo); 321 web_prefs.memory_info_enabled = 322 command_line.HasSwitch(switches::kEnableMemoryInfo); 323 web_prefs.interactive_form_validation_enabled = 324 !command_line.HasSwitch(switches::kDisableInteractiveFormValidation); 325 web_prefs.fullscreen_enabled = 326 command_line.HasSwitch(switches::kEnableFullScreen); 327 328 // The user stylesheet watcher may not exist in a testing profile. 329 if (profile->GetUserStyleSheetWatcher()) { 330 web_prefs.user_style_sheet_enabled = true; 331 web_prefs.user_style_sheet_location = 332 profile->GetUserStyleSheetWatcher()->user_style_sheet(); 333 } else { 334 web_prefs.user_style_sheet_enabled = false; 335 } 336 } 337 338 { // Certain GPU features might have been blacklisted. 339 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); 340 DCHECK(gpu_data_manager); 341 uint32 blacklist_flags = gpu_data_manager->GetGpuFeatureFlags().flags(); 342 if (blacklist_flags & GpuFeatureFlags::kGpuFeatureAcceleratedCompositing) 343 web_prefs.accelerated_compositing_enabled = false; 344 if (blacklist_flags & GpuFeatureFlags::kGpuFeatureWebgl) 345 web_prefs.experimental_webgl_enabled = false; 346 if (blacklist_flags & GpuFeatureFlags::kGpuFeatureMultisampling) 347 web_prefs.gl_multisampling_enabled = false; 348 } 349 350 web_prefs.uses_universal_detector = 351 prefs->GetBoolean(prefs::kWebKitUsesUniversalDetector); 352 web_prefs.text_areas_are_resizable = 353 prefs->GetBoolean(prefs::kWebKitTextAreasAreResizable); 354 web_prefs.hyperlink_auditing_enabled = 355 prefs->GetBoolean(prefs::kEnableHyperlinkAuditing); 356 357 // Make sure we will set the default_encoding with canonical encoding name. 358 web_prefs.default_encoding = 359 CharacterEncoding::GetCanonicalEncodingNameByAliasName( 360 web_prefs.default_encoding); 361 if (web_prefs.default_encoding.empty()) { 362 prefs->ClearPref(prefs::kDefaultCharset); 363 web_prefs.default_encoding = prefs->GetString(prefs::kDefaultCharset); 364 } 365 DCHECK(!web_prefs.default_encoding.empty()); 366 367 if (is_web_ui) { 368 web_prefs.loads_images_automatically = true; 369 web_prefs.javascript_enabled = true; 370 } 371 372 return web_prefs; 373 } 374 375 void RenderViewHostDelegateHelper::UpdateInspectorSetting( 376 Profile* profile, const std::string& key, const std::string& value) { 377 DictionaryPrefUpdate update(profile->GetPrefs(), 378 prefs::kWebKitInspectorSettings); 379 DictionaryValue* inspector_settings = update.Get(); 380 inspector_settings->SetWithoutPathExpansion(key, 381 Value::CreateStringValue(value)); 382 } 383 384 void RenderViewHostDelegateHelper::ClearInspectorSettings(Profile* profile) { 385 profile->GetPrefs()->ClearPref(prefs::kWebKitInspectorSettings); 386 } 387