Home | History | Annotate | Download | only in tab_contents
      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