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