blob: 03ffdd4f711cdc02b12f0fc3d07a74b7be3f069f [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]a2ef54c2011-10-10 16:20:3115#include "content/public/renderer/render_view.h"
[email protected]885c0e92012-11-13 20:27:4216#include "content/public/renderer/v8_value_converter.h"
17#include "extensions/common/constants.h"
[email protected]e48cf4f2013-05-30 12:40:1218#include "third_party/WebKit/public/platform/WebURL.h"
19#include "third_party/WebKit/public/platform/WebURLRequest.h"
[email protected]885c0e92012-11-13 20:27:4220#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
21#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
[email protected]2ee1e3a2011-10-04 15:04:0422#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
[email protected]885c0e92012-11-13 20:27:4223#include "v8/include/v8.h"
[email protected]2ee1e3a2011-10-04 15:04:0424
[email protected]526476902011-10-06 20:34:0625using content::RenderThread;
[email protected]8d86f13d2011-10-04 17:01:1926using content::V8ValueConverter;
27
[email protected]8fe74bf2012-08-07 21:08:4228namespace extensions {
29
[email protected]27131e72011-10-06 03:34:5630ChromeV8ContextSet::ChromeV8ContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0431}
[email protected]27131e72011-10-06 03:34:5632ChromeV8ContextSet::~ChromeV8ContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0433}
34
[email protected]27131e72011-10-06 03:34:5635int ChromeV8ContextSet::size() const {
[email protected]2ee1e3a2011-10-04 15:04:0436 return static_cast<int>(contexts_.size());
37}
38
[email protected]27131e72011-10-06 03:34:5639void ChromeV8ContextSet::Add(ChromeV8Context* context) {
[email protected]bd82ccea2013-02-20 09:56:2040 if (DCHECK_IS_ON()) {
41 // It's OK to insert the same context twice, but we should only ever have
42 // one ChromeV8Context per v8::Context.
43 for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
44 ++iter) {
45 ChromeV8Context* candidate = *iter;
46 if (candidate != context)
47 DCHECK(candidate->v8_context() != context->v8_context());
48 }
[email protected]2ee1e3a2011-10-04 15:04:0449 }
[email protected]2ee1e3a2011-10-04 15:04:0450 contexts_.insert(context);
51}
52
[email protected]27131e72011-10-06 03:34:5653void ChromeV8ContextSet::Remove(ChromeV8Context* context) {
[email protected]2ee1e3a2011-10-04 15:04:0454 if (contexts_.erase(context)) {
[email protected]4f1633f2013-03-09 14:26:2455 context->Invalidate();
[email protected]bb024fe2013-05-10 21:33:2656 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context);
[email protected]2ee1e3a2011-10-04 15:04:0457 }
58}
59
[email protected]8c9311c2013-01-16 03:28:4760ChromeV8ContextSet::ContextSet ChromeV8ContextSet::GetAll() const {
[email protected]2ee1e3a2011-10-04 15:04:0461 return contexts_;
62}
63
[email protected]27131e72011-10-06 03:34:5664ChromeV8Context* ChromeV8ContextSet::GetCurrent() const {
[email protected]2ee1e3a2011-10-04 15:04:0465 if (!v8::Context::InContext())
66 return NULL;
67 else
68 return GetByV8Context(v8::Context::GetCurrent());
69}
70
[email protected]27131e72011-10-06 03:34:5671ChromeV8Context* ChromeV8ContextSet::GetByV8Context(
[email protected]2ee1e3a2011-10-04 15:04:0472 v8::Handle<v8::Context> v8_context) const {
73 for (ContextSet::const_iterator iter = contexts_.begin();
74 iter != contexts_.end(); ++iter) {
75 if ((*iter)->v8_context() == v8_context)
76 return *iter;
77 }
78
79 return NULL;
80}
81
[email protected]27131e72011-10-06 03:34:5682void ChromeV8ContextSet::DispatchChromeHiddenMethod(
[email protected]2ee1e3a2011-10-04 15:04:0483 const std::string& extension_id,
84 const std::string& method_name,
85 const base::ListValue& arguments,
[email protected]1ada5672013-05-30 00:35:2386 content::RenderView* render_view) const {
[email protected]2ee1e3a2011-10-04 15:04:0487 v8::HandleScope handle_scope;
88
89 // We copy the context list, because calling into javascript may modify it
90 // out from under us.
91 ContextSet contexts = GetAll();
92
[email protected]8d86f13d2011-10-04 17:01:1993 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
[email protected]2ee1e3a2011-10-04 15:04:0494 for (ContextSet::iterator it = contexts.begin(); it != contexts.end();
95 ++it) {
96 if ((*it)->v8_context().IsEmpty())
97 continue;
98
[email protected]a76226d2012-04-11 07:58:2999 if (!extension_id.empty()) {
[email protected]8fe74bf2012-08-07 21:08:42100 const Extension* extension = (*it)->extension();
[email protected]a76226d2012-04-11 07:58:29101 if (!extension || (extension_id != extension->id()))
102 continue;
103 }
[email protected]2ee1e3a2011-10-04 15:04:04104
[email protected]a2ef54c2011-10-10 16:20:31105 content::RenderView* context_render_view = (*it)->GetRenderView();
[email protected]2ee1e3a2011-10-04 15:04:04106 if (!context_render_view)
107 continue;
108
109 if (render_view && render_view != context_render_view)
110 continue;
111
[email protected]2ee1e3a2011-10-04 15:04:04112 v8::Local<v8::Context> context(*((*it)->v8_context()));
113 std::vector<v8::Handle<v8::Value> > v8_arguments;
114 for (size_t i = 0; i < arguments.GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37115 const base::Value* item = NULL;
[email protected]2ee1e3a2011-10-04 15:04:04116 CHECK(arguments.Get(i, &item));
[email protected]8d86f13d2011-10-04 17:01:19117 v8_arguments.push_back(converter->ToV8Value(item, context));
[email protected]2ee1e3a2011-10-04 15:04:04118 }
119
[email protected]2df5db742011-10-12 01:37:22120 v8::Handle<v8::Value> retval;
121 (*it)->CallChromeHiddenMethod(
122 method_name, v8_arguments.size(), &v8_arguments[0], &retval);
[email protected]2ee1e3a2011-10-04 15:04:04123 }
124}
[email protected]8fe74bf2012-08-07 21:08:42125
[email protected]280055f2013-04-23 00:50:47126ChromeV8ContextSet::ContextSet ChromeV8ContextSet::OnExtensionUnloaded(
127 const std::string& extension_id) {
[email protected]8c9311c2013-01-16 03:28:47128 ContextSet contexts = GetAll();
[email protected]280055f2013-04-23 00:50:47129 ContextSet removed;
[email protected]8c9311c2013-01-16 03:28:47130
131 // Clean up contexts belonging to the unloaded extension. This is done so
132 // that content scripts (which remain injected into the page) don't continue
133 // receiving events and sending messages.
134 for (ContextSet::iterator it = contexts.begin(); it != contexts.end();
135 ++it) {
136 if ((*it)->extension() && (*it)->extension()->id() == extension_id) {
137 (*it)->DispatchOnUnloadEvent();
[email protected]280055f2013-04-23 00:50:47138 removed.insert(*it);
[email protected]8c9311c2013-01-16 03:28:47139 Remove(*it);
140 }
141 }
[email protected]280055f2013-04-23 00:50:47142
143 return removed;
[email protected]8c9311c2013-01-16 03:28:47144}
145
[email protected]8fe74bf2012-08-07 21:08:42146} // namespace extensions