[email protected] | a76226d | 2012-04-11 07:58:29 | [diff] [blame] | 1 | // Copyright (c) 2012 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] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 5 | #include "chrome/renderer/extensions/chrome_v8_context_set.h" |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 6 | |
7 | #include "base/logging.h" | ||||
[email protected] | 6827510 | 2013-07-17 23:54:20 | [diff] [blame] | 8 | #include "base/message_loop/message_loop.h" |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 9 | #include "base/tracked_objects.h" |
[email protected] | 52647690 | 2011-10-06 20:34:06 | [diff] [blame] | 10 | #include "base/values.h" |
[email protected] | 2a80aee | 2011-10-07 16:06:03 | [diff] [blame] | 11 | #include "chrome/common/url_constants.h" |
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 12 | #include "chrome/renderer/extensions/chrome_v8_context.h" |
[email protected] | 52647690 | 2011-10-06 20:34:06 | [diff] [blame] | 13 | #include "content/public/renderer/render_thread.h" |
[email protected] | a2ef54c | 2011-10-10 16:20:31 | [diff] [blame] | 14 | #include "content/public/renderer/render_view.h" |
[email protected] | 885c0e9 | 2012-11-13 20:27:42 | [diff] [blame] | 15 | #include "extensions/common/constants.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame^] | 16 | #include "extensions/common/extension.h" |
[email protected] | e48cf4f | 2013-05-30 12:40:12 | [diff] [blame] | 17 | #include "third_party/WebKit/public/platform/WebURL.h" |
18 | #include "third_party/WebKit/public/platform/WebURLRequest.h" | ||||
[email protected] | 2255a933 | 2013-06-17 05:12:31 | [diff] [blame] | 19 | #include "third_party/WebKit/public/web/WebDocument.h" |
20 | #include "third_party/WebKit/public/web/WebFrame.h" | ||||
21 | #include "third_party/WebKit/public/web/WebView.h" | ||||
[email protected] | 885c0e9 | 2012-11-13 20:27:42 | [diff] [blame] | 22 | #include "v8/include/v8.h" |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 23 | |
[email protected] | 52647690 | 2011-10-06 20:34:06 | [diff] [blame] | 24 | using content::RenderThread; |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 25 | |
[email protected] | 8fe74bf | 2012-08-07 21:08:42 | [diff] [blame] | 26 | namespace extensions { |
27 | |||||
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 28 | ChromeV8ContextSet::ChromeV8ContextSet() { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 29 | } |
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 30 | ChromeV8ContextSet::~ChromeV8ContextSet() { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 31 | } |
32 | |||||
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 33 | int ChromeV8ContextSet::size() const { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 34 | return static_cast<int>(contexts_.size()); |
35 | } | ||||
36 | |||||
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 37 | void ChromeV8ContextSet::Add(ChromeV8Context* context) { |
[email protected] | bd82ccea | 2013-02-20 09:56:20 | [diff] [blame] | 38 | if (DCHECK_IS_ON()) { |
39 | // It's OK to insert the same context twice, but we should only ever have | ||||
40 | // one ChromeV8Context per v8::Context. | ||||
41 | for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end(); | ||||
42 | ++iter) { | ||||
43 | ChromeV8Context* candidate = *iter; | ||||
44 | if (candidate != context) | ||||
45 | DCHECK(candidate->v8_context() != context->v8_context()); | ||||
46 | } | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 47 | } |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 48 | contexts_.insert(context); |
49 | } | ||||
50 | |||||
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 51 | void ChromeV8ContextSet::Remove(ChromeV8Context* context) { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 52 | if (contexts_.erase(context)) { |
[email protected] | 4f1633f | 2013-03-09 14:26:24 | [diff] [blame] | 53 | context->Invalidate(); |
[email protected] | bb024fe | 2013-05-10 21:33:26 | [diff] [blame] | 54 | base::MessageLoop::current()->DeleteSoon(FROM_HERE, context); |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 55 | } |
56 | } | ||||
57 | |||||
[email protected] | 8c9311c | 2013-01-16 03:28:47 | [diff] [blame] | 58 | ChromeV8ContextSet::ContextSet ChromeV8ContextSet::GetAll() const { |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 59 | return contexts_; |
60 | } | ||||
61 | |||||
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 62 | ChromeV8Context* ChromeV8ContextSet::GetCurrent() const { |
[email protected] | ad6aa8f9 | 2013-06-22 15:34:16 | [diff] [blame] | 63 | return v8::Context::InContext() ? |
64 | GetByV8Context(v8::Context::GetCurrent()) : NULL; | ||||
65 | } | ||||
66 | |||||
67 | ChromeV8Context* ChromeV8ContextSet::GetCalling() const { | ||||
68 | v8::Local<v8::Context> calling = v8::Context::GetCalling(); | ||||
69 | return calling.IsEmpty() ? NULL : GetByV8Context(calling); | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 70 | } |
71 | |||||
[email protected] | 27131e7 | 2011-10-06 03:34:56 | [diff] [blame] | 72 | ChromeV8Context* ChromeV8ContextSet::GetByV8Context( |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 73 | v8::Handle<v8::Context> v8_context) const { |
74 | for (ContextSet::const_iterator iter = contexts_.begin(); | ||||
75 | iter != contexts_.end(); ++iter) { | ||||
76 | if ((*iter)->v8_context() == v8_context) | ||||
77 | return *iter; | ||||
78 | } | ||||
79 | |||||
80 | return NULL; | ||||
81 | } | ||||
82 | |||||
[email protected] | 68e63ea1 | 2013-06-05 05:00:54 | [diff] [blame] | 83 | void ChromeV8ContextSet::ForEach( |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 84 | const std::string& extension_id, |
[email protected] | 68e63ea1 | 2013-06-05 05:00:54 | [diff] [blame] | 85 | content::RenderView* render_view, |
86 | const base::Callback<void(ChromeV8Context*)>& callback) const { | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 87 | // We copy the context list, because calling into javascript may modify it |
88 | // out from under us. | ||||
89 | ContextSet contexts = GetAll(); | ||||
90 | |||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 91 | for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); |
92 | ++it) { | ||||
[email protected] | dd21890 | 2013-06-06 03:04:25 | [diff] [blame] | 93 | ChromeV8Context* context = *it; |
94 | |||||
95 | // For the same reason as above, contexts may become invalid while we run. | ||||
96 | if (!context->is_valid()) | ||||
97 | continue; | ||||
98 | |||||
[email protected] | a76226d | 2012-04-11 07:58:29 | [diff] [blame] | 99 | if (!extension_id.empty()) { |
[email protected] | dd21890 | 2013-06-06 03:04:25 | [diff] [blame] | 100 | const Extension* extension = context->extension(); |
[email protected] | a76226d | 2012-04-11 07:58:29 | [diff] [blame] | 101 | if (!extension || (extension_id != extension->id())) |
102 | continue; | ||||
103 | } | ||||
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 104 | |
[email protected] | dd21890 | 2013-06-06 03:04:25 | [diff] [blame] | 105 | content::RenderView* context_render_view = context->GetRenderView(); |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 106 | if (!context_render_view) |
107 | continue; | ||||
108 | |||||
109 | if (render_view && render_view != context_render_view) | ||||
110 | continue; | ||||
111 | |||||
[email protected] | dd21890 | 2013-06-06 03:04:25 | [diff] [blame] | 112 | callback.Run(context); |
[email protected] | 2ee1e3a | 2011-10-04 15:04:04 | [diff] [blame] | 113 | } |
114 | } | ||||
[email protected] | 8fe74bf | 2012-08-07 21:08:42 | [diff] [blame] | 115 | |
[email protected] | 280055f | 2013-04-23 00:50:47 | [diff] [blame] | 116 | ChromeV8ContextSet::ContextSet ChromeV8ContextSet::OnExtensionUnloaded( |
117 | const std::string& extension_id) { | ||||
[email protected] | 8c9311c | 2013-01-16 03:28:47 | [diff] [blame] | 118 | ContextSet contexts = GetAll(); |
[email protected] | 280055f | 2013-04-23 00:50:47 | [diff] [blame] | 119 | ContextSet removed; |
[email protected] | 8c9311c | 2013-01-16 03:28:47 | [diff] [blame] | 120 | |
121 | // Clean up contexts belonging to the unloaded extension. This is done so | ||||
122 | // that content scripts (which remain injected into the page) don't continue | ||||
123 | // receiving events and sending messages. | ||||
124 | for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); | ||||
125 | ++it) { | ||||
126 | if ((*it)->extension() && (*it)->extension()->id() == extension_id) { | ||||
127 | (*it)->DispatchOnUnloadEvent(); | ||||
[email protected] | 280055f | 2013-04-23 00:50:47 | [diff] [blame] | 128 | removed.insert(*it); |
[email protected] | 8c9311c | 2013-01-16 03:28:47 | [diff] [blame] | 129 | Remove(*it); |
130 | } | ||||
131 | } | ||||
[email protected] | 280055f | 2013-04-23 00:50:47 | [diff] [blame] | 132 | |
133 | return removed; | ||||
[email protected] | 8c9311c | 2013-01-16 03:28:47 | [diff] [blame] | 134 | } |
135 | |||||
[email protected] | 8fe74bf | 2012-08-07 21:08:42 | [diff] [blame] | 136 | } // namespace extensions |