blob: 5ee9db4d2f1a0c69dfcb5c3c17416655facd2df5 [file] [log] [blame]
[email protected]bcd9580f2014-04-17 19:17:591// Copyright 2014 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]bcd9580f2014-04-17 19:17:595#include "extensions/renderer/script_context_set.h"
[email protected]2ee1e3a2011-10-04 15:04:046
[email protected]68275102013-07-17 23:54:207#include "base/message_loop/message_loop.h"
[email protected]a2ef54c2011-10-10 16:20:318#include "content/public/renderer/render_view.h"
[email protected]e4452d32013-11-15 23:07:419#include "extensions/common/extension.h"
[email protected]bcd9580f2014-04-17 19:17:5910#include "extensions/renderer/script_context.h"
[email protected]885c0e92012-11-13 20:27:4211#include "v8/include/v8.h"
[email protected]2ee1e3a2011-10-04 15:04:0412
[email protected]8fe74bf2012-08-07 21:08:4213namespace extensions {
14
[email protected]bcd9580f2014-04-17 19:17:5915ScriptContextSet::ScriptContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0416}
[email protected]bcd9580f2014-04-17 19:17:5917ScriptContextSet::~ScriptContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0418}
19
[email protected]bcd9580f2014-04-17 19:17:5920int ScriptContextSet::size() const {
[email protected]2ee1e3a2011-10-04 15:04:0421 return static_cast<int>(contexts_.size());
22}
23
[email protected]bcd9580f2014-04-17 19:17:5924void ScriptContextSet::Add(ScriptContext* context) {
[email protected]c02cb8012014-03-14 18:39:5325#if DCHECK_IS_ON
26 // It's OK to insert the same context twice, but we should only ever have
[email protected]bcd9580f2014-04-17 19:17:5927 // one ScriptContext per v8::Context.
[email protected]c02cb8012014-03-14 18:39:5328 for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
[email protected]bcd9580f2014-04-17 19:17:5929 ++iter) {
30 ScriptContext* candidate = *iter;
[email protected]c02cb8012014-03-14 18:39:5331 if (candidate != context)
32 DCHECK(candidate->v8_context() != context->v8_context());
[email protected]2ee1e3a2011-10-04 15:04:0433 }
[email protected]c02cb8012014-03-14 18:39:5334#endif
[email protected]2ee1e3a2011-10-04 15:04:0435 contexts_.insert(context);
36}
37
[email protected]bcd9580f2014-04-17 19:17:5938void ScriptContextSet::Remove(ScriptContext* context) {
[email protected]2ee1e3a2011-10-04 15:04:0439 if (contexts_.erase(context)) {
[email protected]4f1633f2013-03-09 14:26:2440 context->Invalidate();
[email protected]bb024fe2013-05-10 21:33:2641 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context);
[email protected]2ee1e3a2011-10-04 15:04:0442 }
43}
44
[email protected]bcd9580f2014-04-17 19:17:5945ScriptContextSet::ContextSet ScriptContextSet::GetAll() const {
[email protected]2ee1e3a2011-10-04 15:04:0446 return contexts_;
47}
48
[email protected]bcd9580f2014-04-17 19:17:5949ScriptContext* ScriptContextSet::GetCurrent() const {
[email protected]95c6b3012013-12-02 14:30:3150 v8::Isolate* isolate = v8::Isolate::GetCurrent();
51 return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext())
52 : NULL;
[email protected]ad6aa8f92013-06-22 15:34:1653}
54
[email protected]bcd9580f2014-04-17 19:17:5955ScriptContext* ScriptContextSet::GetCalling() const {
[email protected]95c6b3012013-12-02 14:30:3156 v8::Isolate* isolate = v8::Isolate::GetCurrent();
57 v8::Local<v8::Context> calling = isolate->GetCallingContext();
[email protected]ad6aa8f92013-06-22 15:34:1658 return calling.IsEmpty() ? NULL : GetByV8Context(calling);
[email protected]2ee1e3a2011-10-04 15:04:0459}
60
[email protected]bcd9580f2014-04-17 19:17:5961ScriptContext* ScriptContextSet::GetByV8Context(
[email protected]2ee1e3a2011-10-04 15:04:0462 v8::Handle<v8::Context> v8_context) const {
63 for (ContextSet::const_iterator iter = contexts_.begin();
[email protected]bcd9580f2014-04-17 19:17:5964 iter != contexts_.end();
65 ++iter) {
[email protected]2ee1e3a2011-10-04 15:04:0466 if ((*iter)->v8_context() == v8_context)
67 return *iter;
68 }
69
70 return NULL;
71}
72
[email protected]bcd9580f2014-04-17 19:17:5973void ScriptContextSet::ForEach(
[email protected]2ee1e3a2011-10-04 15:04:0474 const std::string& extension_id,
[email protected]68e63ea12013-06-05 05:00:5475 content::RenderView* render_view,
[email protected]bcd9580f2014-04-17 19:17:5976 const base::Callback<void(ScriptContext*)>& callback) const {
[email protected]2ee1e3a2011-10-04 15:04:0477 // We copy the context list, because calling into javascript may modify it
78 // out from under us.
79 ContextSet contexts = GetAll();
80
[email protected]bcd9580f2014-04-17 19:17:5981 for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
82 ScriptContext* context = *it;
[email protected]dd218902013-06-06 03:04:2583
84 // For the same reason as above, contexts may become invalid while we run.
85 if (!context->is_valid())
86 continue;
87
[email protected]a76226d2012-04-11 07:58:2988 if (!extension_id.empty()) {
[email protected]dd218902013-06-06 03:04:2589 const Extension* extension = context->extension();
[email protected]a76226d2012-04-11 07:58:2990 if (!extension || (extension_id != extension->id()))
91 continue;
92 }
[email protected]2ee1e3a2011-10-04 15:04:0493
[email protected]dd218902013-06-06 03:04:2594 content::RenderView* context_render_view = context->GetRenderView();
[email protected]2ee1e3a2011-10-04 15:04:0495 if (!context_render_view)
96 continue;
97
98 if (render_view && render_view != context_render_view)
99 continue;
100
[email protected]dd218902013-06-06 03:04:25101 callback.Run(context);
[email protected]2ee1e3a2011-10-04 15:04:04102 }
103}
[email protected]8fe74bf2012-08-07 21:08:42104
[email protected]bcd9580f2014-04-17 19:17:59105ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded(
[email protected]280055f2013-04-23 00:50:47106 const std::string& extension_id) {
[email protected]8c9311c2013-01-16 03:28:47107 ContextSet contexts = GetAll();
[email protected]280055f2013-04-23 00:50:47108 ContextSet removed;
[email protected]8c9311c2013-01-16 03:28:47109
110 // Clean up contexts belonging to the unloaded extension. This is done so
111 // that content scripts (which remain injected into the page) don't continue
112 // receiving events and sending messages.
[email protected]bcd9580f2014-04-17 19:17:59113 for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
[email protected]8c9311c2013-01-16 03:28:47114 if ((*it)->extension() && (*it)->extension()->id() == extension_id) {
115 (*it)->DispatchOnUnloadEvent();
[email protected]280055f2013-04-23 00:50:47116 removed.insert(*it);
[email protected]8c9311c2013-01-16 03:28:47117 Remove(*it);
118 }
119 }
[email protected]280055f2013-04-23 00:50:47120
121 return removed;
[email protected]8c9311c2013-01-16 03:28:47122}
123
[email protected]8fe74bf2012-08-07 21:08:42124} // namespace extensions