• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RenderViewHostDelegateViewHelper()34 RenderViewHostDelegateViewHelper::RenderViewHostDelegateViewHelper() {}
35 
~RenderViewHostDelegateViewHelper()36 RenderViewHostDelegateViewHelper::~RenderViewHostDelegateViewHelper() {}
37 
38 BackgroundContents*
MaybeCreateBackgroundContents(int route_id,Profile * profile,SiteInstance * site,const GURL & opener_url,const string16 & frame_name)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 
CreateNewWindow(int route_id,Profile * profile,SiteInstance * site,WebUI::TypeID webui_type,RenderViewHostDelegate * opener,WindowContainerType window_container_type,const string16 & frame_name)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 
CreateNewWidget(int route_id,WebKit::WebPopupType popup_type,RenderProcessHost * process)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*
CreateNewFullscreenWidget(int route_id,RenderProcessHost * process)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 
GetCreatedWindow(int route_id)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 
GetCreatedWidget(int route_id)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 
RenderWidgetHostDestroyed(RenderWidgetHost * host)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
GetWebkitPrefs(Profile * profile,bool is_web_ui)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 
UpdateInspectorSetting(Profile * profile,const std::string & key,const std::string & value)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 
ClearInspectorSettings(Profile * profile)384 void RenderViewHostDelegateHelper::ClearInspectorSettings(Profile* profile) {
385   profile->GetPrefs()->ClearPref(prefs::kWebKitInspectorSettings);
386 }
387