From a807bbeaaf2155a346ac946aefeed14620dbc17c Mon Sep 17 00:00:00 2001
From: "jochen@chromium.org"
 <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Wed, 14 Apr 2010 10:51:19 +0000
Subject: Reland 44348 Add support for restricting broadcasting events to
 extensions based on host permissions

BUG=38398
TEST=none
TBR=jochen@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44470 0039d316-1c4b-4281-b951-d872f2087c98
---
 chrome/renderer/extensions/event_bindings.cc       | 44 ++++++++++++++++++----
 chrome/renderer/extensions/event_bindings.h        |  6 ++-
 .../extensions/extension_process_bindings.cc       |  2 +-
 .../extensions/renderer_extension_bindings.cc      |  6 ++-
 .../extensions/renderer_extension_bindings.h       |  4 +-
 chrome/renderer/render_thread.cc                   |  6 ++-
 chrome/renderer/render_thread.h                    |  3 +-
 chrome/renderer/render_view.cc                     |  5 ++-
 chrome/renderer/render_view.h                      |  3 +-
 9 files changed, 60 insertions(+), 19 deletions(-)

(limited to 'chrome/renderer')

diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc
index f1dfa19..b1b7565 100644
--- a/chrome/renderer/extensions/event_bindings.cc
+++ b/chrome/renderer/extensions/event_bindings.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.
 
@@ -13,9 +13,12 @@
 #include "chrome/renderer/extensions/js_only_v8_extensions.h"
 #include "chrome/renderer/render_thread.h"
 #include "chrome/renderer/render_view.h"
+#include "googleurl/src/gurl.h"
 #include "grit/renderer_resources.h"
 #include "third_party/WebKit/WebKit/chromium/public/WebDataSource.h"
 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
 #include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
 
 using bindings_utils::CallFunctionInContext;
@@ -27,7 +30,10 @@ using bindings_utils::GetStringResource;
 using bindings_utils::ExtensionBase;
 using bindings_utils::GetPendingRequestMap;
 using bindings_utils::PendingRequestMap;
+using WebKit::WebDataSource;
 using WebKit::WebFrame;
+using WebKit::WebSecurityOrigin;
+using WebKit::WebURL;
 
 static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context,
                                          void*);
@@ -131,9 +137,29 @@ class ExtensionImpl : public ExtensionBase {
 // Returns true if the extension running in the given |context| has sufficient
 // permissions to access the data.
 static bool HasSufficientPermissions(ContextInfo* context,
-                                     bool requires_incognito_access) {
-  return (!requires_incognito_access ||
-          ExtensionProcessBindings::HasIncognitoEnabled(context->extension_id));
+                                     bool requires_incognito_access,
+                                     const GURL& event_url) {
+  v8::Context::Scope context_scope(context->context);
+
+  bool incognito_permissions_ok = (!requires_incognito_access ||
+      ExtensionProcessBindings::HasIncognitoEnabled(context->extension_id));
+  if (!incognito_permissions_ok)
+    return false;
+
+  // During unit tests, we might be invoked without a v8 context. In these
+  // cases, we only allow empty event_urls and short-circuit before retrieving
+  // the render view from the current context.
+  if (!event_url.is_valid())
+    return true;
+
+  RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
+  bool url_permissions_ok = (!event_url.is_valid() ||
+      (renderview &&
+       GURL(renderview->webview()->mainFrame()->url()).SchemeIs(
+           chrome::kExtensionScheme) &&
+       renderview->webview()->mainFrame()->securityOrigin().canRequest(
+          event_url)));
+  return url_permissions_ok;
 }
 
 }  // namespace
@@ -225,7 +251,7 @@ void EventBindings::HandleContextCreated(WebFrame* frame, bool content_script) {
 
   // Figure out the frame's URL.  If the frame is loading, use its provisional
   // URL, since we get this notification before commit.
-  WebKit::WebDataSource* ds = frame->provisionalDataSource();
+  WebDataSource* ds = frame->provisionalDataSource();
   if (!ds)
     ds = frame->dataSource();
   GURL url = ds->request().url();
@@ -299,7 +325,8 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) {
 void EventBindings::CallFunction(const std::string& function_name,
                                  int argc, v8::Handle<v8::Value>* argv,
                                  RenderView* render_view,
-                                 bool requires_incognito_access) {
+                                 bool requires_incognito_access,
+                                 const GURL& event_url) {
   // We copy the context list, because calling into javascript may modify it
   // out from under us. We also guard against deleted contexts by checking if
   // they have been cleared first.
@@ -313,8 +340,11 @@ void EventBindings::CallFunction(const std::string& function_name,
     if ((*it)->context.IsEmpty())
       continue;
 
-    if (!HasSufficientPermissions(it->get(), requires_incognito_access))
+    if (!HasSufficientPermissions(it->get(),
+                                  requires_incognito_access,
+                                  event_url)) {
       continue;
+    }
 
     v8::Handle<v8::Value> retval = CallFunctionInContext((*it)->context,
         function_name, argc, argv);
diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h
index 74edb68..dd396ee 100644
--- a/chrome/renderer/extensions/event_bindings.h
+++ b/chrome/renderer/extensions/event_bindings.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.
 
@@ -9,6 +9,7 @@
 
 #include "v8/include/v8.h"
 
+class GURL;
 class RenderThreadBase;
 class RenderView;
 
@@ -40,7 +41,8 @@ class EventBindings {
   static void CallFunction(const std::string& function_name, int argc,
                            v8::Handle<v8::Value>* argv,
                            RenderView* render_view,
-                           bool requires_incognito_access);
+                           bool requires_incognito_access,
+                           const GURL& event_url);
 };
 
 #endif  // CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index 3232237..fe8abcd 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -87,7 +87,7 @@ static PermissionsMap* GetPermissionsMap(const std::string& extension_id) {
   return &Singleton<SingletonData>()->permissions_[extension_id];
 }
 
-static std::map<std::string, bool>* GetIncognitoEnabledMap() {
+static IncognitoEnabledMap* GetIncognitoEnabledMap() {
   return &Singleton<SingletonData>()->incognito_enabled_map_;
 }
 
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc
index d393089..6c43944 100644
--- a/chrome/renderer/extensions/renderer_extension_bindings.cc
+++ b/chrome/renderer/extensions/renderer_extension_bindings.cc
@@ -299,12 +299,14 @@ v8::Extension* RendererExtensionBindings::Get() {
 void RendererExtensionBindings::Invoke(const std::string& function_name,
                                        const ListValue& args,
                                        RenderView* renderview,
-                                       bool requires_incognito_access) {
+                                       bool requires_incognito_access,
+                                       const GURL& event_url) {
   v8::HandleScope handle_scope;
   std::vector< v8::Handle<v8::Value> > argv = ListValueToV8(args);
   EventBindings::CallFunction(function_name,
                               argv.size(),
                               &argv[0],
                               renderview,
-                              requires_incognito_access);
+                              requires_incognito_access,
+                              event_url);
 }
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h
index 04233f6..3e70e8f 100644
--- a/chrome/renderer/extensions/renderer_extension_bindings.h
+++ b/chrome/renderer/extensions/renderer_extension_bindings.h
@@ -9,6 +9,7 @@
 
 #include <string>
 
+class GURL;
 class ListValue;
 class RenderView;
 
@@ -24,7 +25,8 @@ class RendererExtensionBindings {
 
   // Call the given javascript function with the specified arguments.
   static void Invoke(const std::string& function_name, const ListValue& args,
-                     RenderView* renderview, bool requires_incognito_access);
+                     RenderView* renderview, bool requires_incognito_access,
+                     const GURL& event_url);
 };
 
 #endif  // CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 3a0385a..fc243d8 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -917,8 +917,10 @@ void RenderThread::ScheduleIdleHandler(double initial_delay_s) {
 
 void RenderThread::OnExtensionMessageInvoke(const std::string& function_name,
                                             const ListValue& args,
-                                            bool requires_incognito_access) {
-  RendererExtensionBindings::Invoke(function_name, args, NULL, requires_incognito_access);
+                                            bool requires_incognito_access,
+                                            const GURL& event_url) {
+  RendererExtensionBindings::Invoke(
+      function_name, args, NULL, requires_incognito_access, event_url);
 
   // Reset the idle handler each time there's any activity like event or message
   // dispatch, for which Invoke is the chokepoint.
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index 2294e05..3c45dd5 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -226,7 +226,8 @@ class RenderThread : public RenderThreadBase,
 
   void OnExtensionMessageInvoke(const std::string& function_name,
                                 const ListValue& args,
-                                bool requires_incognito_access);
+                                bool requires_incognito_access,
+                                const GURL& event_url);
   void OnPurgeMemory();
   void OnPurgePluginListCache(bool reload_pages);
 
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index d7f350a..da9d7eb 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -4304,9 +4304,10 @@ void RenderView::InjectToolstripCSS() {
 
 void RenderView::OnExtensionMessageInvoke(const std::string& function_name,
                                           const ListValue& args,
-                                          bool requires_incognito_access) {
+                                          bool requires_incognito_access,
+                                          const GURL& event_url) {
   RendererExtensionBindings::Invoke(
-      function_name, args, this, requires_incognito_access);
+      function_name, args, this, requires_incognito_access, event_url);
 }
 
 // Dump all load time histograms.
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index c3a0190..9545245 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -727,7 +727,8 @@ class RenderView : public RenderWidget,
 
   void OnExtensionMessageInvoke(const std::string& function_name,
                                 const ListValue& args,
-                                bool requires_incognito_access);
+                                bool requires_incognito_access,
+                                const GURL& event_url);
 
   void OnMoveOrResizeStarted();
 
-- 
cgit v1.1