blob: 62a1144e640c795df80ae1cfe08565458287e8f6 [file] [log] [blame]
[email protected]a76226d2012-04-11 07:58:291// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]2ee1e3a2011-10-04 15:04:042// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]27131e72011-10-06 03:34:565#include "chrome/renderer/extensions/chrome_v8_context_set.h"
[email protected]2ee1e3a2011-10-04 15:04:046
7#include "base/logging.h"
8#include "base/message_loop.h"
9#include "base/tracked_objects.h"
[email protected]526476902011-10-06 20:34:0610#include "base/values.h"
[email protected]1c321ee2012-05-21 03:02:3411#include "chrome/common/extensions/extension.h"
[email protected]2a80aee2011-10-07 16:06:0312#include "chrome/common/url_constants.h"
[email protected]27131e72011-10-06 03:34:5613#include "chrome/renderer/extensions/chrome_v8_context.h"
[email protected]526476902011-10-06 20:34:0614#include "content/public/renderer/render_thread.h"
[email protected]8d86f13d2011-10-04 17:01:1915#include "content/public/renderer/v8_value_converter.h"
[email protected]a2ef54c2011-10-10 16:20:3116#include "content/public/renderer/render_view.h"
[email protected]2ee1e3a2011-10-04 15:04:0417#include "v8/include/v8.h"
18#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
19#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
[email protected]75bff522011-12-03 00:04:2020#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
21#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h"
[email protected]2ee1e3a2011-10-04 15:04:0422#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
23
[email protected]526476902011-10-06 20:34:0624using content::RenderThread;
[email protected]8d86f13d2011-10-04 17:01:1925using content::V8ValueConverter;
26
[email protected]8fe74bf2012-08-07 21:08:4227namespace extensions {
28
[email protected]2ee1e3a2011-10-04 15:04:0429namespace {
30
31// Returns true if the extension running in the given |render_view| has
32// sufficient permissions to access the data.
33//
34// TODO(aa): This looks super suspicious. Is it correct? Can we use something
35// else already in the system? Should it be moved elsewhere?
[email protected]a2ef54c2011-10-10 16:20:3136 bool HasSufficientPermissions(content::RenderView* render_view,
37 const GURL& event_url) {
[email protected]2ee1e3a2011-10-04 15:04:0438 // During unit tests, we might be invoked without a v8 context. In these
39 // cases, we only allow empty event_urls and short-circuit before retrieving
40 // the render view from the current context.
41 if (!event_url.is_valid())
42 return true;
43
44 WebKit::WebDocument document =
[email protected]a2ef54c2011-10-10 16:20:3145 render_view->GetWebView()->mainFrame()->document();
[email protected]2ee1e3a2011-10-04 15:04:0446 return GURL(document.url()).SchemeIs(chrome::kExtensionScheme) &&
47 document.securityOrigin().canRequest(event_url);
48}
49
50}
51
[email protected]27131e72011-10-06 03:34:5652ChromeV8ContextSet::ChromeV8ContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0453}
[email protected]27131e72011-10-06 03:34:5654ChromeV8ContextSet::~ChromeV8ContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0455}
56
[email protected]27131e72011-10-06 03:34:5657int ChromeV8ContextSet::size() const {
[email protected]2ee1e3a2011-10-04 15:04:0458 return static_cast<int>(contexts_.size());
59}
60
[email protected]27131e72011-10-06 03:34:5661void ChromeV8ContextSet::Add(ChromeV8Context* context) {
[email protected]2ee1e3a2011-10-04 15:04:0462#ifndef NDEBUG
63 // It's OK to insert the same context twice, but we should only ever have one
[email protected]27131e72011-10-06 03:34:5664 // ChromeV8Context per v8::Context.
[email protected]2ee1e3a2011-10-04 15:04:0465 for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
66 ++iter) {
[email protected]27131e72011-10-06 03:34:5667 ChromeV8Context* candidate = *iter;
[email protected]2ee1e3a2011-10-04 15:04:0468 if (candidate != context)
69 DCHECK(candidate->v8_context() != context->v8_context());
70 }
71#endif
72 contexts_.insert(context);
73}
74
[email protected]27131e72011-10-06 03:34:5675void ChromeV8ContextSet::Remove(ChromeV8Context* context) {
[email protected]2ee1e3a2011-10-04 15:04:0476 if (contexts_.erase(context)) {
77 context->clear_web_frame();
[email protected]380244092011-10-07 17:26:2778 MessageLoop::current()->DeleteSoon(FROM_HERE, context);
[email protected]2ee1e3a2011-10-04 15:04:0479 }
80}
81
[email protected]27131e72011-10-06 03:34:5682ChromeV8ContextSet::ContextSet ChromeV8ContextSet::GetAll()
[email protected]2ee1e3a2011-10-04 15:04:0483 const {
84 return contexts_;
85}
86
[email protected]27131e72011-10-06 03:34:5687ChromeV8Context* ChromeV8ContextSet::GetCurrent() const {
[email protected]2ee1e3a2011-10-04 15:04:0488 if (!v8::Context::InContext())
89 return NULL;
90 else
91 return GetByV8Context(v8::Context::GetCurrent());
92}
93
[email protected]27131e72011-10-06 03:34:5694ChromeV8Context* ChromeV8ContextSet::GetByV8Context(
[email protected]2ee1e3a2011-10-04 15:04:0495 v8::Handle<v8::Context> v8_context) const {
96 for (ContextSet::const_iterator iter = contexts_.begin();
97 iter != contexts_.end(); ++iter) {
98 if ((*iter)->v8_context() == v8_context)
99 return *iter;
100 }
101
102 return NULL;
103}
104
[email protected]27131e72011-10-06 03:34:56105void ChromeV8ContextSet::DispatchChromeHiddenMethod(
[email protected]2ee1e3a2011-10-04 15:04:04106 const std::string& extension_id,
107 const std::string& method_name,
108 const base::ListValue& arguments,
[email protected]a2ef54c2011-10-10 16:20:31109 content::RenderView* render_view,
[email protected]2ee1e3a2011-10-04 15:04:04110 const GURL& event_url) const {
111 v8::HandleScope handle_scope;
112
113 // We copy the context list, because calling into javascript may modify it
114 // out from under us.
115 ContextSet contexts = GetAll();
116
[email protected]8d86f13d2011-10-04 17:01:19117 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
[email protected]2ee1e3a2011-10-04 15:04:04118 for (ContextSet::iterator it = contexts.begin(); it != contexts.end();
119 ++it) {
120 if ((*it)->v8_context().IsEmpty())
121 continue;
122
[email protected]a76226d2012-04-11 07:58:29123 if (!extension_id.empty()) {
[email protected]8fe74bf2012-08-07 21:08:42124 const Extension* extension = (*it)->extension();
[email protected]a76226d2012-04-11 07:58:29125 if (!extension || (extension_id != extension->id()))
126 continue;
127 }
[email protected]2ee1e3a2011-10-04 15:04:04128
[email protected]a2ef54c2011-10-10 16:20:31129 content::RenderView* context_render_view = (*it)->GetRenderView();
[email protected]2ee1e3a2011-10-04 15:04:04130 if (!context_render_view)
131 continue;
132
133 if (render_view && render_view != context_render_view)
134 continue;
135
136 if (!HasSufficientPermissions(context_render_view, event_url))
137 continue;
138
139 v8::Local<v8::Context> context(*((*it)->v8_context()));
140 std::vector<v8::Handle<v8::Value> > v8_arguments;
141 for (size_t i = 0; i < arguments.GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37142 const base::Value* item = NULL;
[email protected]2ee1e3a2011-10-04 15:04:04143 CHECK(arguments.Get(i, &item));
[email protected]8d86f13d2011-10-04 17:01:19144 v8_arguments.push_back(converter->ToV8Value(item, context));
[email protected]2ee1e3a2011-10-04 15:04:04145 }
146
[email protected]2df5db742011-10-12 01:37:22147 v8::Handle<v8::Value> retval;
148 (*it)->CallChromeHiddenMethod(
149 method_name, v8_arguments.size(), &v8_arguments[0], &retval);
[email protected]2ee1e3a2011-10-04 15:04:04150 }
151}
[email protected]8fe74bf2012-08-07 21:08:42152
153} // namespace extensions