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