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

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, 4 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:
169 static void Bind(v8::Handle<v8::Object> object,
170 v8::Handle<v8::Function> callback) {
171 new GCCallback(object, callback);
Jeffrey Yasskin 2013/07/23 23:52:47 Now this looks like an obvious leak. Just move the
not at google - send to devlin 2013/07/24 00:09:28 Not obvious to me, but ok done.
172 }
167 173
168 extensions::ScopedPersistent<v8::Object> object; 174 // Public for base::Owned.
169 extensions::ScopedPersistent<v8::Function> callback; 175 ~GCCallback() {
176 v8::HandleScope handle_scope;
177 v8::Handle<v8::Context> context = callback_->CreationContext();
178 v8::Context::Scope context_scope(context);
179 WebKit::WebScopedMicrotaskSuppression suppression;
180 callback_->Call(context->Global(), 0, NULL);
181 }
170 182
171 private: 183 private:
172 DISALLOW_COPY_AND_ASSIGN(GCCallbackArgs); 184 static void NearDeathCallback(v8::Isolate* isolate,
185 v8::Persistent<v8::Object>* object,
186 GCCallback* self) {
187 // v8 says we need to explicitly reset weak handles from their callbacks.
188 // It's not implicit as one might expect.
189 self->object_.reset();
190 // Delete this to execute |callback| in destructor to be safe across
191 // message loop shutdown and avoid leaking any v8 state.
192 base::MessageLoop::current()->PostTask(FROM_HERE,
193 base::Bind(&GCCallback::Nothing, base::Owned(self)));
194 }
195
196 GCCallback(v8::Handle<v8::Object> object, v8::Handle<v8::Function> callback)
197 : object_(object), callback_(callback) {
198 object_.MakeWeak(this, NearDeathCallback);
199 }
200
201 void Nothing() {
202 // Just something to bind to so that this can be deleted via base::Owned.
Jeffrey Yasskin 2013/07/23 23:52:47 Do the work in here, not in the destructor. Destru
not at google - send to devlin 2013/07/24 00:09:28 Done.
203 }
204
205 extensions::ScopedPersistent<v8::Object> object_;
206 extensions::ScopedPersistent<v8::Function> callback_;
207
208 DISALLOW_COPY_AND_ASSIGN(GCCallback);
173 }; 209 };
174 210
175 static void GCCallback(v8::Isolate* isolate, 211 // void BindToGC(object, callback)
176 v8::Persistent<v8::Object>* object, 212 //
177 GCCallbackArgs* args) { 213 // Binds |callback| to be invoked *sometime after* |object| is garbage
178 v8::HandleScope handle_scope; 214 // collected. We don't call the method re-entrantly so as to avoid executing
179 v8::Handle<v8::Context> context = args->callback->CreationContext(); 215 // 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) { 216 void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args) {
191 CHECK(args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction()); 217 CHECK(args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction());
192 GCCallbackArgs* context = new GCCallbackArgs( 218 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 } 219 }
197 }; 220 };
198 221
199 } // namespace 222 } // namespace
200 223
201 namespace extensions { 224 namespace extensions {
202 225
203 ChromeV8Extension* MiscellaneousBindings::Get( 226 ChromeV8Extension* MiscellaneousBindings::Get(
204 Dispatcher* dispatcher, 227 Dispatcher* dispatcher,
205 ChromeV8Context* context) { 228 ChromeV8Context* context) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } else { 362 } else {
340 arguments.push_back(v8::Null()); 363 arguments.push_back(v8::Null());
341 } 364 }
342 (*it)->module_system()->CallModuleMethod("miscellaneous_bindings", 365 (*it)->module_system()->CallModuleMethod("miscellaneous_bindings",
343 "dispatchOnDisconnect", 366 "dispatchOnDisconnect",
344 &arguments); 367 &arguments);
345 } 368 }
346 } 369 }
347 370
348 } // namespace extensions 371 } // 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