Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: chrome/renderer/extensions/miscellaneous_bindings.cc

Issue 19670020: Run the Port cleanup code inside BindToGC in a setTimeout call to avoid (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use message loop Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/extensions/miscellaneous_bindings.h" 5 #include "chrome/renderer/extensions/miscellaneous_bindings.h"
6 6
7 #include <map> 7 #include <map>
8 #include <string> 8 #include <string>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/message_loop/message_loop.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "chrome/common/extensions/extension_messages.h" 15 #include "chrome/common/extensions/extension_messages.h"
15 #include "chrome/common/extensions/message_bundle.h" 16 #include "chrome/common/extensions/message_bundle.h"
16 #include "chrome/common/url_constants.h" 17 #include "chrome/common/url_constants.h"
17 #include "chrome/renderer/extensions/chrome_v8_context.h" 18 #include "chrome/renderer/extensions/chrome_v8_context.h"
18 #include "chrome/renderer/extensions/chrome_v8_context_set.h" 19 #include "chrome/renderer/extensions/chrome_v8_context_set.h"
19 #include "chrome/renderer/extensions/chrome_v8_extension.h" 20 #include "chrome/renderer/extensions/chrome_v8_extension.h"
20 #include "chrome/renderer/extensions/dispatcher.h" 21 #include "chrome/renderer/extensions/dispatcher.h"
21 #include "chrome/renderer/extensions/event_bindings.h" 22 #include "chrome/renderer/extensions/event_bindings.h"
22 #include "chrome/renderer/extensions/scoped_persistent.h" 23 #include "chrome/renderer/extensions/scoped_persistent.h"
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 154
154 int port_id = args[0]->Int32Value(); 155 int port_id = args[0]->Int32Value();
155 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { 156 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) {
156 // Send via the RenderThread because the RenderView might be closing. 157 // Send via the RenderThread because the RenderView might be closing.
157 content::RenderThread::Get()->Send( 158 content::RenderThread::Get()->Send(
158 new ExtensionHostMsg_CloseChannel(port_id, std::string())); 159 new ExtensionHostMsg_CloseChannel(port_id, std::string()));
159 ClearPortData(port_id); 160 ClearPortData(port_id);
160 } 161 }
161 } 162 }
162 163
163 struct GCCallbackArgs { 164 // Holds a |callback| to run sometime after |object| is GC'ed. |callback| will
164 GCCallbackArgs(v8::Handle<v8::Object> object, 165 // not be executed re-entrantly to avoid running JS in an unexpected state.
165 v8::Handle<v8::Function> callback) 166 //
166 : object(object), callback(callback) {} 167 // Bound to the lifetime of |object|.
167 168 class GCCallback {
168 extensions::ScopedPersistent<v8::Object> object; 169 public:
169 extensions::ScopedPersistent<v8::Function> callback; 170 GCCallback(v8::Handle<v8::Object> object, v8::Handle<v8::Function> callback)
171 : object_(object), callback_(callback) {
172 object_.MakeWeak(this, NearDeathCallback);
173 }
170 174
171 private: 175 private:
172 DISALLOW_COPY_AND_ASSIGN(GCCallbackArgs); 176 friend class base::DeleteHelper<GCCallback>;
177
178 static void NearDeathCallback(v8::Isolate* isolate,
179 v8::Persistent<v8::Object>* object,
180 GCCallback* self) {
adamk 2013/07/23 22:47:38 I think you want to call self->object_.reset() h
not at google - send to devlin 2013/07/23 22:55:04 ah good point.
Jeffrey Yasskin 2013/07/23 22:59:35 And possibly link to https://code.google.com/p/chr
not at google - send to devlin 2013/07/23 23:17:41 Added comment (though not to the source itself, ar
181 // Delete this and execute function in destructor to be safe across
182 // message loop shutdown and avoid leaking any v8 state.
183 base::MessageLoop::current()->DeleteSoon(FROM_HERE, self);
Jeffrey Yasskin 2013/07/23 22:59:35 I'd just PostTask(Bind(&GCCallback::DoStuff, Owned
Jeffrey Yasskin 2013/07/23 22:59:35 After posting to the MessageLoop, how do we know t
not at google - send to devlin 2013/07/23 23:17:41 Done.
not at google - send to devlin 2013/07/23 23:17:41 callback_ is Persistent, so it will "by definition
adamk 2013/07/23 23:43:21 All the entry points check for a dead Isolate befo
184 }
185
186 ~GCCallback() {
187 v8::HandleScope handle_scope;
188 v8::Handle<v8::Context> context = callback_->CreationContext();
adamk 2013/07/23 23:43:21 ...except that this Handle will be empty if the is
189 v8::Context::Scope context_scope(context);
190 WebKit::WebScopedMicrotaskSuppression suppression;
191 // Wrap in try/catch here so that we don't call into any message/exception
192 // handlers during GC. That is a recipe for pain.
193 v8::TryCatch trycatch;
194 callback_->Call(context->Global(), 0, NULL);
195 }
196
197 extensions::ScopedPersistent<v8::Object> object_;
198 extensions::ScopedPersistent<v8::Function> callback_;
199
200 DISALLOW_COPY_AND_ASSIGN(GCCallback);
173 }; 201 };
174 202
175 static void GCCallback(v8::Isolate* isolate, 203 // void BindToGC(object, callback)
176 v8::Persistent<v8::Object>* object, 204 //
177 GCCallbackArgs* args) { 205 // Binds |callback| to be invoked *sometime after* |object| is garbage
178 v8::HandleScope handle_scope; 206 // collected. We don't call the method re-entrantly so as to avoid executing
179 v8::Handle<v8::Context> context = args->callback->CreationContext(); 207 // JS in some bizarro undefined mid-GC state.
180 v8::Context::Scope context_scope(context);
181 WebKit::WebScopedMicrotaskSuppression suppression;
182 // Wrap in try/catch here so that we don't call into any message/exception
183 // handlers during GC. That is a recipe for pain.
184 v8::TryCatch trycatch;
185 args->callback->Call(context->Global(), 0, NULL);
186 delete args;
187 }
188
189 // Binds a callback to be invoked when the given object is garbage collected.
190 void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args) { 208 void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args) {
191 CHECK(args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction()); 209 CHECK(args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction());
192 GCCallbackArgs* context = new GCCallbackArgs( 210 new GCCallback(args[0].As<v8::Object>(), args[1].As<v8::Function>());
Jeffrey Yasskin 2013/07/23 22:59:35 If possible, I'd rather not have code that looks l
193 v8::Handle<v8::Object>::Cast(args[0]),
194 v8::Handle<v8::Function>::Cast(args[1]));
195 context->object.MakeWeak(context, GCCallback);
196 } 211 }
197 }; 212 };
198 213
199 } // namespace 214 } // namespace
200 215
201 namespace extensions { 216 namespace extensions {
202 217
203 ChromeV8Extension* MiscellaneousBindings::Get( 218 ChromeV8Extension* MiscellaneousBindings::Get(
204 Dispatcher* dispatcher, 219 Dispatcher* dispatcher,
205 ChromeV8Context* context) { 220 ChromeV8Context* context) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } else { 354 } else {
340 arguments.push_back(v8::Null()); 355 arguments.push_back(v8::Null());
341 } 356 }
342 (*it)->module_system()->CallModuleMethod("miscellaneous_bindings", 357 (*it)->module_system()->CallModuleMethod("miscellaneous_bindings",
343 "dispatchOnDisconnect", 358 "dispatchOnDisconnect",
344 &arguments); 359 &arguments);
345 } 360 }
346 } 361 }
347 362
348 } // namespace extensions 363 } // namespace extensions
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698