OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008, 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009 Google Inc. All rights reserved. |
3 * Copyright (C) 2009 Apple Inc. All rights reserved. | 3 * Copyright (C) 2009 Apple Inc. All rights reserved. |
4 * Copyright (C) 2014 Opera Software ASA. All rights reserved. | 4 * Copyright (C) 2014 Opera Software ASA. All rights reserved. |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions are | 7 * modification, are permitted provided that the following conditions are |
8 * met: | 8 * met: |
9 * | 9 * |
10 * * Redistributions of source code must retain the above copyright | 10 * * Redistributions of source code must retain the above copyright |
(...skipping 15 matching lines...) Expand all Loading... |
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 */ | 31 */ |
32 | 32 |
33 #include "bindings/core/v8/ScriptController.h" | 33 #include "bindings/core/v8/ScriptController.h" |
34 | 34 |
35 #include "bindings/core/v8/BindingSecurity.h" | 35 #include "bindings/core/v8/BindingSecurity.h" |
36 #include "bindings/core/v8/NPV8Object.h" | |
37 #include "bindings/core/v8/ScriptCallStack.h" | 36 #include "bindings/core/v8/ScriptCallStack.h" |
38 #include "bindings/core/v8/ScriptSourceCode.h" | 37 #include "bindings/core/v8/ScriptSourceCode.h" |
39 #include "bindings/core/v8/ScriptValue.h" | 38 #include "bindings/core/v8/ScriptValue.h" |
40 #include "bindings/core/v8/V8Binding.h" | 39 #include "bindings/core/v8/V8Binding.h" |
41 #include "bindings/core/v8/V8Event.h" | 40 #include "bindings/core/v8/V8Event.h" |
42 #include "bindings/core/v8/V8GCController.h" | 41 #include "bindings/core/v8/V8GCController.h" |
43 #include "bindings/core/v8/V8HTMLElement.h" | 42 #include "bindings/core/v8/V8HTMLElement.h" |
44 #include "bindings/core/v8/V8NPObject.h" | |
45 #include "bindings/core/v8/V8PerContextData.h" | 43 #include "bindings/core/v8/V8PerContextData.h" |
46 #include "bindings/core/v8/V8ScriptRunner.h" | 44 #include "bindings/core/v8/V8ScriptRunner.h" |
47 #include "bindings/core/v8/V8Window.h" | 45 #include "bindings/core/v8/V8Window.h" |
48 #include "bindings/core/v8/WindowProxy.h" | 46 #include "bindings/core/v8/WindowProxy.h" |
49 #include "bindings/core/v8/npruntime_impl.h" | |
50 #include "bindings/core/v8/npruntime_priv.h" | |
51 #include "core/dom/Document.h" | 47 #include "core/dom/Document.h" |
52 #include "core/dom/Node.h" | 48 #include "core/dom/Node.h" |
53 #include "core/dom/ScriptableDocumentParser.h" | 49 #include "core/dom/ScriptableDocumentParser.h" |
54 #include "core/events/Event.h" | 50 #include "core/events/Event.h" |
55 #include "core/events/EventListener.h" | 51 #include "core/events/EventListener.h" |
56 #include "core/frame/LocalDOMWindow.h" | 52 #include "core/frame/LocalDOMWindow.h" |
57 #include "core/frame/Settings.h" | 53 #include "core/frame/Settings.h" |
58 #include "core/frame/UseCounter.h" | 54 #include "core/frame/UseCounter.h" |
59 #include "core/frame/csp/ContentSecurityPolicy.h" | 55 #include "core/frame/csp/ContentSecurityPolicy.h" |
60 #include "core/html/HTMLPlugInElement.h" | 56 #include "core/html/HTMLPlugInElement.h" |
(...skipping 26 matching lines...) Expand all Loading... |
87 bool ScriptController::canAccessFromCurrentOrigin(v8::Isolate* isolate, Frame* f
rame) | 83 bool ScriptController::canAccessFromCurrentOrigin(v8::Isolate* isolate, Frame* f
rame) |
88 { | 84 { |
89 if (!frame) | 85 if (!frame) |
90 return false; | 86 return false; |
91 return !isolate->InContext() || BindingSecurity::shouldAllowAccessToFrame(is
olate, callingDOMWindow(isolate), frame, ReportSecurityError); | 87 return !isolate->InContext() || BindingSecurity::shouldAllowAccessToFrame(is
olate, callingDOMWindow(isolate), frame, ReportSecurityError); |
92 } | 88 } |
93 | 89 |
94 ScriptController::ScriptController(LocalFrame* frame) | 90 ScriptController::ScriptController(LocalFrame* frame) |
95 : m_windowProxyManager(WindowProxyManager::create(*frame)) | 91 : m_windowProxyManager(WindowProxyManager::create(*frame)) |
96 , m_sourceURL(0) | 92 , m_sourceURL(0) |
97 , m_windowScriptNPObject(0) | |
98 { | 93 { |
99 } | 94 } |
100 | 95 |
101 ScriptController::~ScriptController() | 96 ScriptController::~ScriptController() |
102 { | 97 { |
103 } | 98 } |
104 | 99 |
105 DEFINE_TRACE(ScriptController) | 100 DEFINE_TRACE(ScriptController) |
106 { | 101 { |
107 #if ENABLE(OILPAN) | 102 #if ENABLE(OILPAN) |
108 visitor->trace(m_windowProxyManager); | 103 visitor->trace(m_windowProxyManager); |
109 visitor->trace(m_pluginObjects); | |
110 #endif | 104 #endif |
111 } | 105 } |
112 | 106 |
113 void ScriptController::clearScriptObjects() | |
114 { | |
115 PluginObjectMap::iterator it = m_pluginObjects.begin(); | |
116 for (; it != m_pluginObjects.end(); ++it) { | |
117 _NPN_UnregisterObject(it->value); | |
118 _NPN_ReleaseObject(it->value); | |
119 } | |
120 m_pluginObjects.clear(); | |
121 | |
122 if (m_windowScriptNPObject) { | |
123 // Dispose of the underlying V8 object before releasing our reference | |
124 // to it, so that if a plugin fails to release it properly we will | |
125 // only leak the NPObject wrapper, not the object, its document, or | |
126 // anything else they reference. | |
127 disposeUnderlyingV8Object(isolate(), m_windowScriptNPObject); | |
128 _NPN_ReleaseObject(m_windowScriptNPObject); | |
129 m_windowScriptNPObject = 0; | |
130 } | |
131 } | |
132 | |
133 void ScriptController::clearForClose() | 107 void ScriptController::clearForClose() |
134 { | 108 { |
135 double start = currentTime(); | 109 double start = currentTime(); |
136 m_windowProxyManager->clearForClose(); | 110 m_windowProxyManager->clearForClose(); |
137 double end = currentTime(); | 111 double end = currentTime(); |
138 DEFINE_STATIC_LOCAL(CustomCountHistogram, clearForCloseHistogram, ("WebCore.
ScriptController.clearForClose", 0, 10000, 50)); | 112 DEFINE_STATIC_LOCAL(CustomCountHistogram, clearForCloseHistogram, ("WebCore.
ScriptController.clearForClose", 0, 10000, 50)); |
139 clearForCloseHistogram.count((end - start) * 1000); | 113 clearForCloseHistogram.count((end - start) * 1000); |
140 } | 114 } |
141 | 115 |
142 void ScriptController::updateSecurityOrigin(SecurityOrigin* origin) | 116 void ScriptController::updateSecurityOrigin(SecurityOrigin* origin) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 } | 204 } |
231 | 205 |
232 TextPosition ScriptController::eventHandlerPosition() const | 206 TextPosition ScriptController::eventHandlerPosition() const |
233 { | 207 { |
234 ScriptableDocumentParser* parser = frame()->document()->scriptableDocumentPa
rser(); | 208 ScriptableDocumentParser* parser = frame()->document()->scriptableDocumentPa
rser(); |
235 if (parser) | 209 if (parser) |
236 return parser->textPosition(); | 210 return parser->textPosition(); |
237 return TextPosition::minimumPosition(); | 211 return TextPosition::minimumPosition(); |
238 } | 212 } |
239 | 213 |
240 // Create a V8 object with an interceptor of NPObjectPropertyGetter. | |
241 bool ScriptController::bindToWindowObject(LocalFrame* frame, const String& key,
NPObject* object) | |
242 { | |
243 ScriptState* scriptState = ScriptState::forMainWorld(frame); | |
244 if (!scriptState) | |
245 return false; | |
246 | |
247 ScriptState::Scope scope(scriptState); | |
248 v8::Local<v8::Object> value = createV8ObjectForNPObject(isolate(), object, 0
); | |
249 | |
250 // Attach to the global object. | |
251 return v8CallBoolean(scriptState->context()->Global()->Set(scriptState->cont
ext(), v8String(isolate(), key), value)); | |
252 } | |
253 | |
254 void ScriptController::enableEval() | 214 void ScriptController::enableEval() |
255 { | 215 { |
256 v8::HandleScope handleScope(isolate()); | 216 v8::HandleScope handleScope(isolate()); |
257 v8::Local<v8::Context> v8Context = m_windowProxyManager->mainWorldProxy()->c
ontextIfInitialized(); | 217 v8::Local<v8::Context> v8Context = m_windowProxyManager->mainWorldProxy()->c
ontextIfInitialized(); |
258 if (v8Context.IsEmpty()) | 218 if (v8Context.IsEmpty()) |
259 return; | 219 return; |
260 v8Context->AllowCodeGenerationFromStrings(true); | 220 v8Context->AllowCodeGenerationFromStrings(true); |
261 } | 221 } |
262 | 222 |
263 void ScriptController::disableEval(const String& errorMessage) | 223 void ScriptController::disableEval(const String& errorMessage) |
(...skipping 12 matching lines...) Expand all Loading... |
276 | 236 |
277 if (!widget->isPluginView()) | 237 if (!widget->isPluginView()) |
278 return nullptr; | 238 return nullptr; |
279 | 239 |
280 v8::HandleScope handleScope(isolate()); | 240 v8::HandleScope handleScope(isolate()); |
281 v8::Local<v8::Object> scriptableObject = toPluginView(widget)->scriptableObj
ect(isolate()); | 241 v8::Local<v8::Object> scriptableObject = toPluginView(widget)->scriptableObj
ect(isolate()); |
282 | 242 |
283 if (scriptableObject.IsEmpty()) | 243 if (scriptableObject.IsEmpty()) |
284 return nullptr; | 244 return nullptr; |
285 | 245 |
286 // LocalFrame Memory Management for NPObjects | |
287 // ------------------------------------- | |
288 // NPObjects are treated differently than other objects wrapped by JS. | |
289 // NPObjects can be created either by the browser (e.g. the main | |
290 // window object) or by the plugin (the main plugin object | |
291 // for a HTMLEmbedElement). Further, unlike most DOM Objects, the frame | |
292 // is especially careful to ensure NPObjects terminate at frame teardown bec
ause | |
293 // if a plugin leaks a reference, it could leak its objects (or the browser'
s objects). | |
294 // | |
295 // The LocalFrame maintains a list of plugin objects (m_pluginObjects) | |
296 // which it can use to quickly find the wrapped embed object. | |
297 // | |
298 // Inside the NPRuntime, we've added a few methods for registering | |
299 // wrapped NPObjects. The purpose of the registration is because | |
300 // javascript garbage collection is non-deterministic, yet we need to | |
301 // be able to tear down the plugin objects immediately. When an object | |
302 // is registered, javascript can use it. When the object is destroyed, | |
303 // or when the object's "owning" object is destroyed, the object will | |
304 // be un-registered, and the javascript engine must not use it. | |
305 // | |
306 // Inside the javascript engine, the engine can keep a reference to the | |
307 // NPObject as part of its wrapper. However, before accessing the object | |
308 // it must consult the _NPN_Registry. | |
309 | |
310 if (isWrappedNPObject(scriptableObject)) { | |
311 // Track the plugin object. We've been given a reference to the object. | |
312 m_pluginObjects.set(widget, v8ObjectToNPObject(scriptableObject)); | |
313 } | |
314 | |
315 return SharedPersistent<v8::Object>::create(scriptableObject, isolate()); | 246 return SharedPersistent<v8::Object>::create(scriptableObject, isolate()); |
316 } | 247 } |
317 | 248 |
318 void ScriptController::cleanupScriptObjectsForPlugin(Widget* nativeHandle) | |
319 { | |
320 PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle); | |
321 if (it == m_pluginObjects.end()) | |
322 return; | |
323 _NPN_UnregisterObject(it->value); | |
324 _NPN_ReleaseObject(it->value); | |
325 m_pluginObjects.remove(it); | |
326 } | |
327 | |
328 V8Extensions& ScriptController::registeredExtensions() | 249 V8Extensions& ScriptController::registeredExtensions() |
329 { | 250 { |
330 DEFINE_STATIC_LOCAL(V8Extensions, extensions, ()); | 251 DEFINE_STATIC_LOCAL(V8Extensions, extensions, ()); |
331 return extensions; | 252 return extensions; |
332 } | 253 } |
333 | 254 |
334 void ScriptController::registerExtensionIfNeeded(v8::Extension* extension) | 255 void ScriptController::registerExtensionIfNeeded(v8::Extension* extension) |
335 { | 256 { |
336 const V8Extensions& extensions = registeredExtensions(); | 257 const V8Extensions& extensions = registeredExtensions(); |
337 for (size_t i = 0; i < extensions.size(); ++i) { | 258 for (size_t i = 0; i < extensions.size(); ++i) { |
338 if (extensions[i] == extension) | 259 if (extensions[i] == extension) |
339 return; | 260 return; |
340 } | 261 } |
341 v8::RegisterExtension(extension); | 262 v8::RegisterExtension(extension); |
342 registeredExtensions().append(extension); | 263 registeredExtensions().append(extension); |
343 } | 264 } |
344 | 265 |
345 static NPObject* createNoScriptObject() | |
346 { | |
347 notImplemented(); | |
348 return 0; | |
349 } | |
350 | |
351 static NPObject* createScriptObject(LocalFrame* frame, v8::Isolate* isolate) | |
352 { | |
353 ScriptState* scriptState = ScriptState::forMainWorld(frame); | |
354 if (!scriptState) | |
355 return createNoScriptObject(); | |
356 | |
357 ScriptState::Scope scope(scriptState); | |
358 LocalDOMWindow* window = frame->localDOMWindow(); | |
359 v8::Local<v8::Value> global = toV8(window, scriptState->context()->Global(),
scriptState->isolate()); | |
360 if (global.IsEmpty()) | |
361 return createNoScriptObject(); | |
362 ASSERT(global->IsObject()); | |
363 return npCreateV8ScriptObject(isolate, 0, v8::Local<v8::Object>::Cast(global
), window); | |
364 } | |
365 | |
366 NPObject* ScriptController::windowScriptNPObject() | |
367 { | |
368 if (m_windowScriptNPObject) | |
369 return m_windowScriptNPObject; | |
370 | |
371 if (canExecuteScripts(NotAboutToExecuteScript)) { | |
372 // JavaScript is enabled, so there is a JavaScript window object. | |
373 // Return an NPObject bound to the window object. | |
374 m_windowScriptNPObject = createScriptObject(frame(), isolate()); | |
375 _NPN_RegisterObject(m_windowScriptNPObject, 0); | |
376 } else { | |
377 // JavaScript is not enabled, so we cannot bind the NPObject to the | |
378 // JavaScript window object. Instead, we create an NPObject of a | |
379 // different class, one which is not bound to a JavaScript object. | |
380 m_windowScriptNPObject = createNoScriptObject(); | |
381 } | |
382 return m_windowScriptNPObject; | |
383 } | |
384 | |
385 NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement
* plugin) | |
386 { | |
387 // Can't create NPObjects when JavaScript is disabled. | |
388 if (!canExecuteScripts(NotAboutToExecuteScript)) | |
389 return createNoScriptObject(); | |
390 | |
391 ScriptState* scriptState = ScriptState::forMainWorld(frame()); | |
392 if (!scriptState) | |
393 return createNoScriptObject(); | |
394 | |
395 ScriptState::Scope scope(scriptState); | |
396 LocalDOMWindow* window = frame()->localDOMWindow(); | |
397 v8::Local<v8::Value> v8plugin = toV8(plugin, scriptState->context()->Global(
), scriptState->isolate()); | |
398 if (v8plugin.IsEmpty() || !v8plugin->IsObject()) | |
399 return createNoScriptObject(); | |
400 | |
401 return npCreateV8ScriptObject(scriptState->isolate(), 0, v8::Local<v8::Objec
t>::Cast(v8plugin), window); | |
402 } | |
403 | |
404 void ScriptController::clearWindowProxy() | 266 void ScriptController::clearWindowProxy() |
405 { | 267 { |
406 // V8 binding expects ScriptController::clearWindowProxy only be called | 268 // V8 binding expects ScriptController::clearWindowProxy only be called |
407 // when a frame is loading a new page. This creates a new context for the ne
w page. | 269 // when a frame is loading a new page. This creates a new context for the ne
w page. |
408 | 270 |
409 double start = currentTime(); | 271 double start = currentTime(); |
410 // The V8 context must be available for |clearScriptObjects()|. | |
411 // The below call must be before |clearForNavigation()| which disposes the V
8 context. | |
412 clearScriptObjects(); | |
413 | 272 |
414 m_windowProxyManager->clearForNavigation(); | 273 m_windowProxyManager->clearForNavigation(); |
415 double end = currentTime(); | 274 double end = currentTime(); |
416 DEFINE_STATIC_LOCAL(CustomCountHistogram, clearWindowProxyHistogram, ("WebCo
re.ScriptController.clearWindowProxy", 0, 10000, 50)); | 275 DEFINE_STATIC_LOCAL(CustomCountHistogram, clearWindowProxyHistogram, ("WebCo
re.ScriptController.clearWindowProxy", 0, 10000, 50)); |
417 clearWindowProxyHistogram.count((end - start) * 1000); | 276 clearWindowProxyHistogram.count((end - start) * 1000); |
418 } | 277 } |
419 | 278 |
420 void ScriptController::setCaptureCallStackForUncaughtExceptions(v8::Isolate* iso
late, bool value) | 279 void ScriptController::setCaptureCallStackForUncaughtExceptions(v8::Isolate* iso
late, bool value) |
421 { | 280 { |
422 isolate->SetCaptureStackTraceForUncaughtExceptions(value, V8StackTrace::maxC
allStackSizeToCapture, stackTraceOptions); | 281 isolate->SetCaptureStackTraceForUncaughtExceptions(value, V8StackTrace::maxC
allStackSizeToCapture, stackTraceOptions); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 for (size_t i = 0; i < resultArray->Length(); ++i) { | 460 for (size_t i = 0; i < resultArray->Length(); ++i) { |
602 v8::Local<v8::Value> value; | 461 v8::Local<v8::Value> value; |
603 if (!resultArray->Get(scriptState->context(), i).ToLocal(&value)) | 462 if (!resultArray->Get(scriptState->context(), i).ToLocal(&value)) |
604 return; | 463 return; |
605 results->append(value); | 464 results->append(value); |
606 } | 465 } |
607 } | 466 } |
608 } | 467 } |
609 | 468 |
610 } // namespace blink | 469 } // namespace blink |
OLD | NEW |