[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. | ||||
4 | |||||
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 5 | #include "extensions/renderer/script_context_set.h" |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 6 | |
[email protected] | 6827510 | 2013-07-17 23:54:20 | [diff] [blame] | 7 | #include "base/message_loop/message_loop.h" |
[email protected] | a2ef54c | 2011-10-10 16:20:31 | [diff] [blame] | 8 | #include "content/public/renderer/render_view.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 9 | #include "extensions/common/extension.h" |
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 10 | #include "extensions/renderer/script_context.h" |
[email protected] | 885c0e9 | 2012-11-13 20:27:42 | [diff] [blame] | 11 | #include "v8/include/v8.h" |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 12 | |
[email protected] | 8fe74bf | 2012-08-07 21:08:42 | [diff] [blame] | 13 | namespace extensions { |
14 | |||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 15 | ScriptContextSet::ScriptContextSet() { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 16 | } |
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 17 | ScriptContextSet::~ScriptContextSet() { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 18 | } |
19 | |||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 20 | int ScriptContextSet::size() const { |
21 | return static_cast<int>(contexts_.size()); | ||||
22 | } | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 23 | |
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 24 | void ScriptContextSet::Add(ScriptContext* context) { |
25 | #if DCHECK_IS_ON() | ||||
26 | // It's OK to insert the same context twice, but we should only ever have | ||||
27 | // one ScriptContext per v8::Context. | ||||
28 | for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end(); | ||||
29 | ++iter) { | ||||
30 | ScriptContext* candidate = *iter; | ||||
31 | if (candidate != context) | ||||
32 | DCHECK(candidate->v8_context() != context->v8_context()); | ||||
33 | } | ||||
34 | #endif | ||||
35 | contexts_.insert(context); | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 36 | } |
37 | |||||
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 38 | void ScriptContextSet::Remove(ScriptContext* context) { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 39 | if (contexts_.erase(context)) { |
[email protected] | 4f1633f | 2013-03-09 14:26:24 | [diff] [blame] | 40 | context->Invalidate(); |
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 41 | base::MessageLoop::current()->DeleteSoon(FROM_HERE, context); |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 42 | } |
43 | } | ||||
44 | |||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 45 | ScriptContextSet::ContextSet ScriptContextSet::GetAll() const { |
46 | return contexts_; | ||||
47 | } | ||||
48 | |||||
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 49 | ScriptContext* ScriptContextSet::GetCurrent() const { |
[email protected] | 95c6b301 | 2013-12-02 14:30:31 | [diff] [blame] | 50 | v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
51 | return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext()) | ||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 52 | : NULL; |
[email protected] | ad6aa8f9 | 2013-06-22 15:34:16 | [diff] [blame] | 53 | } |
54 | |||||
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 55 | ScriptContext* ScriptContextSet::GetCalling() const { |
[email protected] | 95c6b301 | 2013-12-02 14:30:31 | [diff] [blame] | 56 | v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
57 | v8::Local<v8::Context> calling = isolate->GetCallingContext(); | ||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 58 | return calling.IsEmpty() ? NULL : GetByV8Context(calling); |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 59 | } |
60 | |||||
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 61 | ScriptContext* ScriptContextSet::GetByV8Context( |
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 62 | v8::Handle<v8::Context> v8_context) const { |
63 | for (ContextSet::const_iterator iter = contexts_.begin(); | ||||
64 | iter != contexts_.end(); ++iter) { | ||||
65 | if ((*iter)->v8_context() == v8_context) | ||||
66 | return *iter; | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 67 | } |
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 68 | |
69 | return NULL; | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 70 | } |
71 | |||||
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 72 | void ScriptContextSet::ForEach( |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 73 | const std::string& extension_id, |
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 74 | content::RenderView* render_view, |
[email protected] | bcd9580f | 2014-04-17 19:17:59 | [diff] [blame] | 75 | const base::Callback<void(ScriptContext*)>& callback) const { |
kozyatinskiy | 441ece5 | 2015-04-01 23:46:32 | [diff] [blame] | 76 | // We copy the context list, because calling into javascript may modify it |
77 | // out from under us. | ||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 78 | ContextSet contexts = GetAll(); |
79 | |||||
80 | for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) { | ||||
81 | ScriptContext* context = *it; | ||||
82 | |||||
kozyatinskiy | 441ece5 | 2015-04-01 23:46:32 | [diff] [blame] | 83 | // For the same reason as above, contexts may become invalid while we run. |
84 | if (!context->is_valid()) | ||||
85 | continue; | ||||
86 | |||||
87 | if (!extension_id.empty()) { | ||||
88 | const Extension* extension = context->extension(); | ||||
89 | if (!extension || (extension_id != extension->id())) | ||||
90 | continue; | ||||
91 | } | ||||
92 | |||||
93 | content::RenderView* context_render_view = context->GetRenderView(); | ||||
94 | if (!context_render_view) | ||||
95 | continue; | ||||
96 | |||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 97 | if (render_view && render_view != context_render_view) |
kozyatinskiy | 441ece5 | 2015-04-01 23:46:32 | [diff] [blame] | 98 | continue; |
99 | |||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 100 | callback.Run(context); |
101 | } | ||||
102 | } | ||||
kozyatinskiy | 441ece5 | 2015-04-01 23:46:32 | [diff] [blame] | 103 | |
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 104 | ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded( |
105 | const std::string& extension_id) { | ||||
106 | ContextSet contexts = GetAll(); | ||||
107 | ContextSet removed; | ||||
108 | |||||
109 | // Clean up contexts belonging to the unloaded extension. This is done so | ||||
110 | // that content scripts (which remain injected into the page) don't continue | ||||
111 | // receiving events and sending messages. | ||||
112 | for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) { | ||||
113 | if ((*it)->extension() && (*it)->extension()->id() == extension_id) { | ||||
114 | (*it)->DispatchOnUnloadEvent(); | ||||
115 | removed.insert(*it); | ||||
116 | Remove(*it); | ||||
kozyatinskiy | 441ece5 | 2015-04-01 23:46:32 | [diff] [blame] | 117 | } |
118 | } | ||||
kalman | 62b5911d | 2015-04-04 02:33:09 | [diff] [blame^] | 119 | |
120 | return removed; | ||||
kozyatinskiy | 441ece5 | 2015-04-01 23:46:32 | [diff] [blame] | 121 | } |
122 | |||||
[email protected] | 8fe74bf | 2012-08-07 21:08:42 | [diff] [blame] | 123 | } // namespace extensions |