IPC per-host content settings to the renderers.

BUG=32719
TEST=none

Review URL: http://codereview.chromium.org/549218

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37628 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/renderer_host/async_resource_handler.cc b/chrome/browser/renderer_host/async_resource_handler.cc
index 7b5e8c2..6cba3f4 100644
--- a/chrome/browser/renderer_host/async_resource_handler.cc
+++ b/chrome/browser/renderer_host/async_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -100,11 +100,11 @@
 
 bool AsyncResourceHandler::OnResponseStarted(int request_id,
                                              ResourceResponse* response) {
-  // For changes to the main frame, inform the renderer of the new URL's zoom
-  // level before the request actually commits.  This way the renderer will be
-  // able to set the zoom level precisely at the time the request commits,
-  // avoiding the possibility of zooming the old content or of having to layout
-  // the new content twice.
+  // For changes to the main frame, inform the renderer of the new URL's
+  // per-host settings before the request actually commits.  This way the
+  // renderer will be able to set these precisely at the time the
+  // request commits, avoiding the possibility of e.g. zooming the old content
+  // or of having to layout the new content twice.
   URLRequest* request = rdh_->GetURLRequest(
       GlobalRequestID(process_id_, request_id));
   ResourceDispatcherHostRequestInfo* info = rdh_->InfoForRequest(request);
@@ -113,6 +113,9 @@
     ChromeURLRequestContext* context =
         static_cast<ChromeURLRequestContext*>(request->context());
     if (!host.empty() && context) {
+      receiver_->Send(new ViewMsg_SetContentSettingsForLoadingHost(
+            info->route_id(), host,
+            context->host_content_settings_map()->GetContentSettings(host)));
       receiver_->Send(new ViewMsg_SetZoomLevelForLoadingHost(info->route_id(),
           host, context->host_zoom_map()->GetZoomLevel(host)));
     }
diff --git a/chrome/common/common_param_traits.cc b/chrome/common/common_param_traits.cc
index 5e6880e3..e213f6d 100644
--- a/chrome/common/common_param_traits.cc
+++ b/chrome/common/common_param_traits.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -179,6 +179,31 @@
   l->append(StringPrintf(L"(%d, %d)", p.width(), p.height()));
 }
 
+void ParamTraits<ContentSettings>::Write(
+    Message* m, const ContentSettings& settings) {
+  for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
+    WriteParam(m, static_cast<int>(settings.settings[i]));
+}
+
+bool ParamTraits<ContentSettings>::Read(
+    const Message* m, void** iter, ContentSettings* r) {
+  for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
+    int local_setting;
+    if (!m->ReadInt(iter, &local_setting))
+      return false;
+    if (local_setting < 0 ||
+        local_setting >= static_cast<int>(CONTENT_SETTING_NUM_SETTINGS))
+      return false;
+    r->settings[i] = static_cast<ContentSetting>(local_setting);
+  }
+  return true;
+}
+
+void ParamTraits<ContentSettings>::Log(
+    const ContentSettings& p, std::wstring* l) {
+  l->append(StringPrintf(L"<ContentSettings>"));
+}
+
 void ParamTraits<webkit_glue::WebApplicationInfo>::Write(
     Message* m, const webkit_glue::WebApplicationInfo& p) {
   WriteParam(m, p.title);
diff --git a/chrome/common/common_param_traits.h b/chrome/common/common_param_traits.h
index 98f6bfb1..c82d497 100644
--- a/chrome/common/common_param_traits.h
+++ b/chrome/common/common_param_traits.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "app/gfx/native_widget_types.h"
+#include "chrome/common/content_settings.h"
 #include "chrome/common/page_zoom.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/common/transport_dib.h"
@@ -88,6 +89,14 @@
 };
 
 template <>
+struct ParamTraits<ContentSettings> {
+  typedef ContentSettings param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
 struct ParamTraits<gfx::NativeWindow> {
   typedef gfx::NativeWindow param_type;
   static void Write(Message* m, const param_type& p) {
@@ -105,7 +114,6 @@
   }
 };
 
-
 template <>
 struct ParamTraits<PageZoom::Function> {
   typedef PageZoom::Function param_type;
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index c4f89200..55414a77 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -21,6 +21,7 @@
 #include "base/shared_memory.h"
 #include "base/sync_socket.h"
 #include "base/values.h"
+#include "chrome/common/content_settings.h"
 #include "chrome/common/css_colors.h"
 #include "chrome/common/extensions/update_manifest.h"
 #include "chrome/common/nacl_types.h"
@@ -364,6 +365,19 @@
                        std::string /* host */,
                        int /* zoom_level */)
 
+  // Set the content settings for a particular hostname that the renderer is in
+  // the process of loading.  This will be stored, to be used if the load
+  // commits and ignored otherwise.
+  IPC_MESSAGE_ROUTED2(ViewMsg_SetContentSettingsForLoadingHost,
+                      std::string /* host */,
+                      ContentSettings /* content_settings */)
+
+  // Set the content settings for a particular hostname, so all render views
+  // displaying this host can update their content settings to match.
+  IPC_MESSAGE_CONTROL2(ViewMsg_SetContentSettingsForCurrentHost,
+                       std::string /* host */,
+                       ContentSettings /* content_settings */)  
+
   // Change encoding of page in the renderer.
   IPC_MESSAGE_ROUTED1(ViewMsg_SetPageEncoding,
                       std::string /*new encoding name*/)
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 2d47a43d..1123790 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -88,6 +88,7 @@
 using WebKit::WebCache;
 using WebKit::WebCrossOriginPreflightResultCache;
 using WebKit::WebFontCache;
+using WebKit::WebFrame;
 using WebKit::WebRuntimeFeatures;
 using WebKit::WebSecurityPolicy;
 using WebKit::WebScriptController;
@@ -139,6 +140,30 @@
 };
 #endif
 
+class RenderViewContentSettingsSetter : public RenderViewVisitor {
+ public:
+  RenderViewContentSettingsSetter(const std::string& host,
+                                  const ContentSettings& content_settings)
+      : host_(host),
+        content_settings_(content_settings) {
+  }
+
+  virtual bool Visit(RenderView* render_view) {
+    // |render_view->webview()| is guaranteed non-NULL.
+    WebFrame* frame = render_view->webview()->mainFrame();
+    if (GURL(frame->url()).host() == host_) {
+      render_view->ApplyContentSettings(frame, content_settings_);
+    }
+    return true;
+  }
+
+ private:
+  std::string host_;
+  ContentSettings content_settings_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderViewContentSettingsSetter);
+};
+
 class RenderViewZoomer : public RenderViewVisitor {
  public:
   RenderViewZoomer(const std::string& host, int zoom_level)
@@ -284,6 +309,13 @@
   WebView::resetVisitedLinkState();
 }
 
+void RenderThread::OnSetContentSettingsForCurrentHost(
+    const std::string& host,
+    const ContentSettings& content_settings) {
+  RenderViewContentSettingsSetter setter(host, content_settings);
+  RenderView::ForEach(&setter);
+}
+
 void RenderThread::OnSetZoomLevelForCurrentHost(const std::string& host,
                                                 int zoom_level) {
   RenderViewZoomer zoomer(host, zoom_level);
@@ -343,6 +375,8 @@
     IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)
     IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_Add, OnAddVisitedLinks)
     IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_Reset, OnResetVisitedLinks)
+    IPC_MESSAGE_HANDLER(ViewMsg_SetContentSettingsForCurrentHost,
+                        OnSetContentSettingsForCurrentHost)
     IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentHost,
                         OnSetZoomLevelForCurrentHost)
     IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index 559b7dc..4f992e4 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -38,6 +38,7 @@
 class UserScriptSlave;
 class URLPattern;
 
+struct ContentSettings;
 struct RendererPreferences;
 struct ViewMsg_DOMStorageEvent_Params;
 struct ViewMsg_New_Params;
@@ -159,6 +160,8 @@
   void OnAddVisitedLinks(const VisitedLinkSlave::Fingerprints& fingerprints);
   void OnResetVisitedLinks();
   void OnSetZoomLevelForCurrentHost(const std::string& host, int zoom_level);
+  void OnSetContentSettingsForCurrentHost(
+      const std::string& host, const ContentSettings& content_settings);
   void OnUpdateUserScripts(base::SharedMemoryHandle table);
   void OnSetExtensionFunctionNames(const std::vector<std::string>& names);
   void OnPageActionsUpdated(const std::string& extension_id,
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 98c754f15..183fbd3 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -494,6 +494,8 @@
     IPC_MESSAGE_HANDLER(ViewMsg_ExecuteEditCommand, OnExecuteEditCommand)
     IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
     IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
+    IPC_MESSAGE_HANDLER(ViewMsg_SetContentSettingsForLoadingHost,
+                        OnSetContentSettingsForLoadingHost)
     IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingHost,
                         OnSetZoomLevelForLoadingHost)
     IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
@@ -1082,6 +1084,18 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+void RenderView::ApplyContentSettings(
+    WebKit::WebFrame* frame,
+    const ContentSettings& settings) {
+  // CONTENT_SETTING_ASK is only valid for cookies.
+  allowImages(frame, settings.settings[CONTENT_SETTINGS_TYPE_IMAGES] ==
+      CONTENT_SETTING_ALLOW);
+  allowScript(frame, settings.settings[CONTENT_SETTINGS_TYPE_JAVASCRIPT] ==
+      CONTENT_SETTING_ALLOW);
+  allowPlugins(frame, settings.settings[CONTENT_SETTINGS_TYPE_PLUGINS] ==
+      CONTENT_SETTING_ALLOW);
+}
+
 // Tell the embedding application that the URL of the active page has changed
 void RenderView::UpdateURL(WebFrame* frame) {
   WebDataSource* ds = frame->dataSource();
@@ -1135,15 +1149,27 @@
   if (!frame->parent()) {
     // Top-level navigation.
 
+    // Set content settings.
+    HostContentSettings::iterator host_content_settings =
+        host_content_settings_.find(GURL(request.url()).host());
+    if (host_content_settings != host_content_settings_.end()) {
+      ApplyContentSettings(frame, host_content_settings->second);
+
+      // These content settings were merely recorded transiently for this load.
+      // We can erase them now.  If at some point we reload this page, the
+      // browser will send us new, up-to-date content settings.
+      host_content_settings_.erase(host_content_settings);
+    }
+
     // Set zoom level.
-    HostZoomLevels::iterator host =
+    HostZoomLevels::iterator host_zoom =
         host_zoom_levels_.find(GURL(request.url()).host());
-    if (host != host_zoom_levels_.end()) {
-      webview()->setZoomLevel(false, host->second);
+    if (host_zoom != host_zoom_levels_.end()) {
+      webview()->setZoomLevel(false, host_zoom->second);
       // This zoom level was merely recorded transiently for this load.  We can
       // erase it now.  If at some point we reload this page, the browser will
       // send us a new, up-to-date zoom level.
-      host_zoom_levels_.erase(host);
+      host_zoom_levels_.erase(host_zoom);
     }
 
     // Drop the translated nodes.
@@ -3155,6 +3181,12 @@
     Send(new ViewHostMsg_DidZoomHost(host, new_zoom_level));
 }
 
+void RenderView::OnSetContentSettingsForLoadingHost(
+    std::string host,
+    const ContentSettings& content_settings) {
+  host_content_settings_[host] = content_settings;
+}
+
 void RenderView::OnSetZoomLevelForLoadingHost(std::string host,
                                               int zoom_level) {
   host_zoom_levels_[host] = zoom_level;
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 940b404..c94229c 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,6 +22,7 @@
 #include "base/values.h"
 #include "base/weak_ptr.h"
 #include "build/build_config.h"
+#include "chrome/common/content_settings.h"
 #include "chrome/common/edit_command.h"
 #include "chrome/common/navigation_gesture.h"
 #include "chrome/common/notification_type.h"
@@ -261,6 +262,10 @@
     return notification_provider_.get();
   }
 
+  // Shortcut for calling allowImages(), allowScripts(), allowPlugins().
+  void ApplyContentSettings(WebKit::WebFrame* frame,
+                            const ContentSettings& settings);
+
   // WebKit::WebWidgetClient
   // Most methods are handled by RenderWidget.
   virtual void show(WebKit::WebNavigationPolicy policy);
@@ -478,6 +483,7 @@
   FRIEND_TEST(RenderViewTest, MacTestCmdUp);
 #endif
 
+  typedef std::map<std::string, ContentSettings> HostContentSettings;
   typedef std::map<std::string, int> HostZoomLevels;
 
   explicit RenderView(RenderThreadBase* render_thread,
@@ -582,6 +588,8 @@
   void OnCancelDownload(int32 download_id);
   void OnFind(int request_id, const string16&, const WebKit::WebFindOptions&);
   void OnDeterminePageLanguage();
+  void OnSetContentSettingsForLoadingHost(
+      std::string host, const ContentSettings& content_settings);
   void OnZoom(PageZoom::Function function);
   void OnSetZoomLevelForLoadingHost(std::string host, int zoom_level);
   void OnSetPageEncoding(const std::string& encoding_name);
@@ -1024,6 +1032,7 @@
 
   typedef std::map<WebKit::WebView*, RenderView*> ViewMap;
 
+  HostContentSettings host_content_settings_;
   HostZoomLevels host_zoom_levels_;
 
   // The SessionStorage namespace that we're assigned to has an ID, and that ID