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

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: more 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/bind_helpers.h"
12 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
14 #include "base/message_loop/message_loop.h"
13 #include "base/values.h" 15 #include "base/values.h"
14 #include "chrome/common/extensions/extension_messages.h" 16 #include "chrome/common/extensions/extension_messages.h"
15 #include "chrome/common/extensions/message_bundle.h" 17 #include "chrome/common/extensions/message_bundle.h"
16 #include "chrome/common/url_constants.h" 18 #include "chrome/common/url_constants.h"
17 #include "chrome/renderer/extensions/chrome_v8_context.h" 19 #include "chrome/renderer/extensions/chrome_v8_context.h"
18 #include "chrome/renderer/extensions/chrome_v8_context_set.h" 20 #include "chrome/renderer/extensions/chrome_v8_context_set.h"
19 #include "chrome/renderer/extensions/chrome_v8_extension.h" 21 #include "chrome/renderer/extensions/chrome_v8_extension.h"
20 #include "chrome/renderer/extensions/dispatcher.h" 22 #include "chrome/renderer/extensions/dispatcher.h"
21 #include "chrome/renderer/extensions/event_bindings.h" 23 #include "chrome/renderer/extensions/event_bindings.h"
22 #include "chrome/renderer/extensions/scoped_persistent.h" 24 #include "chrome/renderer/extensions/scoped_persistent.h"
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 155
154 int port_id = args[0]->Int32Value(); 156 int port_id = args[0]->Int32Value();
155 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { 157 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) {
156 // Send via the RenderThread because the RenderView might be closing. 158 // Send via the RenderThread because the RenderView might be closing.
157 content::RenderThread::Get()->Send( 159 content::RenderThread::Get()->Send(
158 new ExtensionHostMsg_CloseChannel(port_id, std::string())); 160 new ExtensionHostMsg_CloseChannel(port_id, std::string()));
159 ClearPortData(port_id); 161 ClearPortData(port_id);
160 } 162 }
161 } 163 }
162 164
163 struct GCCallbackArgs { 165 // Holds a |callback| to run sometime after |object| is GC'ed. |callback| will
164 GCCallbackArgs(v8::Handle<v8::Object> object, 166 // not be executed re-entrantly to avoid running JS in an unexpected state.
165 v8::Handle<v8::Function> callback) 167 class GCCallback {
166 : object(object), callback(callback) {} 168 public:
167 169 static void Bind(v8::Handle<v8::Object> object,
168 extensions::ScopedPersistent<v8::Object> object; 170 v8::Handle<v8::Function> callback) {
169 extensions::ScopedPersistent<v8::Function> callback; 171 GCCallback* cb = new GCCallback(object, callback);
172 cb->object_.MakeWeak(cb, NearDeathCallback);
173 }
170 174
171 private: 175 private:
172 DISALLOW_COPY_AND_ASSIGN(GCCallbackArgs); 176 static void NearDeathCallback(v8::Isolate* isolate,
177 v8::Persistent<v8::Object>* object,
178 GCCallback* self) {
179 // v8 says we need to explicitly reset weak handles from their callbacks.
180 // It's not implicit as one might expect.
181 self->object_.reset();
182 // Delete this to execute |callback| in destructor to be safe across
Jeffrey Yasskin 2013/07/24 00:20:17 This comment is out of date. Probably you don't ne
183 // message loop shutdown and avoid leaking any v8 state.
184 base::MessageLoop::current()->PostTask(FROM_HERE,
185 base::Bind(&GCCallback::RunCallback, base::Owned(self)));
186 }
187
188 GCCallback(v8::Handle<v8::Object> object, v8::Handle<v8::Function> callback)
189 : object_(object), callback_(callback) {
190 }
191
192 void RunCallback() {
193 v8::HandleScope handle_scope;
194 v8::Handle<v8::Context> context = callback_->CreationContext();
adamk 2013/07/24 00:18:05 I would recommend checking for non-emptyness on th
not at google - send to devlin 2013/07/24 00:21:09 CreationContext of an object can be empty?
adamk 2013/07/24 00:24:47 It can return an empty handle if the V8 heap is in
195 v8::Context::Scope context_scope(context);
196 WebKit::WebScopedMicrotaskSuppression suppression;
197 callback_->Call(context->Global(), 0, NULL);
198 }
199
200 extensions::ScopedPersistent<v8::Object> object_;
201 extensions::ScopedPersistent<v8::Function> callback_;
202
203 DISALLOW_COPY_AND_ASSIGN(GCCallback);
173 }; 204 };
174 205
175 static void GCCallback(v8::Isolate* isolate, 206 // void BindToGC(object, callback)
176 v8::Persistent<v8::Object>* object, 207 //
177 GCCallbackArgs* args) { 208 // Binds |callback| to be invoked *sometime after* |object| is garbage
178 v8::HandleScope handle_scope; 209 // collected. We don't call the method re-entrantly so as to avoid executing
179 v8::Handle<v8::Context> context = args->callback->CreationContext(); 210 // 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) { 211 void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args) {
191 CHECK(args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction()); 212 CHECK(args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction());
192 GCCallbackArgs* context = new GCCallbackArgs( 213 GCCallback::Bind(args[0].As<v8::Object>(), args[1].As<v8::Function>());
193 v8::Handle<v8::Object>::Cast(args[0]),
194 v8::Handle<v8::Function>::Cast(args[1]));
195 context->object.MakeWeak(context, GCCallback);
196 } 214 }
197 }; 215 };
198 216
199 } // namespace 217 } // namespace
200 218
201 namespace extensions { 219 namespace extensions {
202 220
203 ChromeV8Extension* MiscellaneousBindings::Get( 221 ChromeV8Extension* MiscellaneousBindings::Get(
204 Dispatcher* dispatcher, 222 Dispatcher* dispatcher,
205 ChromeV8Context* context) { 223 ChromeV8Context* context) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } else { 357 } else {
340 arguments.push_back(v8::Null()); 358 arguments.push_back(v8::Null());
341 } 359 }
342 (*it)->module_system()->CallModuleMethod("miscellaneous_bindings", 360 (*it)->module_system()->CallModuleMethod("miscellaneous_bindings",
343 "dispatchOnDisconnect", 361 "dispatchOnDisconnect",
344 &arguments); 362 &arguments);
345 } 363 }
346 } 364 }
347 365
348 } // namespace extensions 366 } // 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