OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/event_bindings.h" | 5 #include "chrome/renderer/extensions/event_bindings.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/singleton.h" | 8 #include "base/singleton.h" |
9 #include "chrome/common/render_messages.h" | 9 #include "chrome/common/render_messages.h" |
10 #include "chrome/common/url_constants.h" | 10 #include "chrome/common/url_constants.h" |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 void EventBindings::SetRenderThread(RenderThreadBase* thread) { | 115 void EventBindings::SetRenderThread(RenderThreadBase* thread) { |
116 render_thread = thread; | 116 render_thread = thread; |
117 in_unit_tests = true; | 117 in_unit_tests = true; |
118 } | 118 } |
119 | 119 |
120 // static | 120 // static |
121 RenderThreadBase* EventBindings::GetRenderThread() { | 121 RenderThreadBase* EventBindings::GetRenderThread() { |
122 return render_thread ? render_thread : RenderThread::current(); | 122 return render_thread ? render_thread : RenderThread::current(); |
123 } | 123 } |
124 | 124 |
| 125 static void DeferredUnload(v8::Persistent<v8::Context> context) { |
| 126 v8::HandleScope handle_scope; |
| 127 CallFunctionInContext(context, "dispatchOnUnload", 0, NULL); |
| 128 context.Dispose(); |
| 129 context.Clear(); |
| 130 } |
| 131 |
125 static void HandleContextDestroyed(ContextList::iterator context_iter, | 132 static void HandleContextDestroyed(ContextList::iterator context_iter, |
126 bool callUnload) { | 133 bool in_gc) { |
127 // Notify the bindings that they're going away. | 134 // Notify the bindings that they're going away. |
128 if (callUnload) { | 135 if (in_gc) { |
129 CallFunctionInContext((*context_iter)->context, "dispatchOnUnload", 0, | 136 // We shouldn't call back into javascript during a garbage collect. Do it |
130 NULL); | 137 // later. We'll hang onto the context until this DeferredUnload is called. |
| 138 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction( |
| 139 DeferredUnload, (*context_iter)->context)); |
| 140 } else { |
| 141 CallFunctionInContext((*context_iter)->context, "dispatchOnUnload", |
| 142 0, NULL); |
131 } | 143 } |
132 | 144 |
133 // Remove all pending requests for this context. | 145 // Remove all pending requests for this context. |
134 PendingRequestMap& pending_requests = GetPendingRequestMap(); | 146 PendingRequestMap& pending_requests = GetPendingRequestMap(); |
135 for (PendingRequestMap::iterator it = pending_requests.begin(); | 147 for (PendingRequestMap::iterator it = pending_requests.begin(); |
136 it != pending_requests.end(); ) { | 148 it != pending_requests.end(); ) { |
137 PendingRequestMap::iterator current = it++; | 149 PendingRequestMap::iterator current = it++; |
138 if (current->second->context == (*context_iter)->context) { | 150 if (current->second->context == (*context_iter)->context) { |
139 current->second->context.Dispose(); | 151 current->second->context.Dispose(); |
140 current->second->context.Clear(); | 152 current->second->context.Clear(); |
141 pending_requests.erase(current); | 153 pending_requests.erase(current); |
142 } | 154 } |
143 } | 155 } |
144 | 156 |
145 // Unload any content script contexts for this frame. | 157 // Unload any content script contexts for this frame. |
146 for (ContextList::iterator it = GetContexts().begin(); | 158 for (ContextList::iterator it = GetContexts().begin(); |
147 it != GetContexts().end(); ) { | 159 it != GetContexts().end(); ) { |
148 ContextList::iterator current = it++; | 160 ContextList::iterator current = it++; |
149 if ((*current)->parent_context == (*context_iter)->context) | 161 if ((*current)->parent_context == (*context_iter)->context) |
150 HandleContextDestroyed(current, callUnload); | 162 HandleContextDestroyed(current, in_gc); |
151 } | 163 } |
152 | 164 |
153 // Remove it from our registered contexts. | |
154 (*context_iter)->context.ClearWeak(); | |
155 (*context_iter)->context.Dispose(); | |
156 (*context_iter)->context.Clear(); | |
157 | |
158 if (!(*context_iter)->parent_context.IsEmpty()) { | 165 if (!(*context_iter)->parent_context.IsEmpty()) { |
159 (*context_iter)->parent_context.Dispose(); | 166 (*context_iter)->parent_context.Dispose(); |
160 (*context_iter)->parent_context.Clear(); | 167 (*context_iter)->parent_context.Clear(); |
161 } | 168 } |
162 | 169 |
| 170 // Remove it from our registered contexts. |
| 171 (*context_iter)->context.ClearWeak(); |
| 172 if (!in_gc) { |
| 173 (*context_iter)->context.Dispose(); |
| 174 (*context_iter)->context.Clear(); |
| 175 } |
| 176 |
163 GetContexts().erase(context_iter); | 177 GetContexts().erase(context_iter); |
164 } | 178 } |
165 | 179 |
166 static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, | 180 static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, |
167 void*) { | 181 void*) { |
168 for (ContextList::iterator it = GetContexts().begin(); | 182 for (ContextList::iterator it = GetContexts().begin(); |
169 it != GetContexts().end(); ++it) { | 183 it != GetContexts().end(); ++it) { |
170 if ((*it)->context == context) { | 184 if ((*it)->context == context) { |
171 HandleContextDestroyed(it, false); | 185 HandleContextDestroyed(it, true); |
172 return; | 186 return; |
173 } | 187 } |
174 } | 188 } |
175 | 189 |
176 NOTREACHED(); | 190 NOTREACHED(); |
177 } | 191 } |
178 | 192 |
179 void EventBindings::HandleContextCreated(WebFrame* frame, bool content_script) { | 193 void EventBindings::HandleContextCreated(WebFrame* frame, bool content_script) { |
180 if (!bindings_registered) | 194 if (!bindings_registered) |
181 return; | 195 return; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 void EventBindings::HandleContextDestroyed(WebFrame* frame) { | 251 void EventBindings::HandleContextDestroyed(WebFrame* frame) { |
238 if (!bindings_registered) | 252 if (!bindings_registered) |
239 return; | 253 return; |
240 | 254 |
241 v8::HandleScope handle_scope; | 255 v8::HandleScope handle_scope; |
242 v8::Local<v8::Context> context = frame->GetScriptContext(); | 256 v8::Local<v8::Context> context = frame->GetScriptContext(); |
243 DCHECK(!context.IsEmpty()); | 257 DCHECK(!context.IsEmpty()); |
244 | 258 |
245 ContextList::iterator context_iter = bindings_utils::FindContext(context); | 259 ContextList::iterator context_iter = bindings_utils::FindContext(context); |
246 if (context_iter != GetContexts().end()) | 260 if (context_iter != GetContexts().end()) |
247 ::HandleContextDestroyed(context_iter, true); | 261 ::HandleContextDestroyed(context_iter, false); |
248 } | 262 } |
249 | 263 |
250 // static | 264 // static |
251 void EventBindings::CallFunction(const std::string& function_name, | 265 void EventBindings::CallFunction(const std::string& function_name, |
252 int argc, v8::Handle<v8::Value>* argv, | 266 int argc, v8::Handle<v8::Value>* argv, |
253 RenderView* render_view) { | 267 RenderView* render_view) { |
254 for (ContextList::iterator it = GetContexts().begin(); | 268 for (ContextList::iterator it = GetContexts().begin(); |
255 it != GetContexts().end(); ++it) { | 269 it != GetContexts().end(); ++it) { |
256 if (render_view && render_view != (*it)->render_view) | 270 if (render_view && render_view != (*it)->render_view) |
257 continue; | 271 continue; |
258 CallFunctionInContext((*it)->context, function_name, argc, argv); | 272 CallFunctionInContext((*it)->context, function_name, argc, argv); |
259 } | 273 } |
260 } | 274 } |
OLD | NEW |