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/ScriptCallStackFactory.h" | 36 #include "bindings/core/v8/ScriptCallStackFactory.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 { | 83 { |
88 if (!frame) | 84 if (!frame) |
89 return false; | 85 return false; |
90 v8::Isolate* isolate = toIsolate(frame); | 86 v8::Isolate* isolate = toIsolate(frame); |
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 Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearFo
rClose", (currentTime() - start) * 1000, 0, 10000, 50); | 111 Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearFo
rClose", (currentTime() - start) * 1000, 0, 10000, 50); |
138 } | 112 } |
139 | 113 |
140 void ScriptController::updateSecurityOrigin(SecurityOrigin* origin) | 114 void ScriptController::updateSecurityOrigin(SecurityOrigin* origin) |
141 { | 115 { |
142 m_windowProxyManager->mainWorldProxy()->updateSecurityOrigin(origin); | 116 m_windowProxyManager->mainWorldProxy()->updateSecurityOrigin(origin); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 } | 202 } |
229 | 203 |
230 TextPosition ScriptController::eventHandlerPosition() const | 204 TextPosition ScriptController::eventHandlerPosition() const |
231 { | 205 { |
232 ScriptableDocumentParser* parser = frame()->document()->scriptableDocumentPa
rser(); | 206 ScriptableDocumentParser* parser = frame()->document()->scriptableDocumentPa
rser(); |
233 if (parser) | 207 if (parser) |
234 return parser->textPosition(); | 208 return parser->textPosition(); |
235 return TextPosition::minimumPosition(); | 209 return TextPosition::minimumPosition(); |
236 } | 210 } |
237 | 211 |
238 // Create a V8 object with an interceptor of NPObjectPropertyGetter. | |
239 bool ScriptController::bindToWindowObject(LocalFrame* frame, const String& key,
NPObject* object) | |
240 { | |
241 ScriptState* scriptState = ScriptState::forMainWorld(frame); | |
242 if (!scriptState->contextIsValid()) | |
243 return false; | |
244 | |
245 ScriptState::Scope scope(scriptState); | |
246 v8::Local<v8::Object> value = createV8ObjectForNPObject(isolate(), object, 0
); | |
247 | |
248 // Attach to the global object. | |
249 return v8CallBoolean(scriptState->context()->Global()->Set(scriptState->cont
ext(), v8String(isolate(), key), value)); | |
250 } | |
251 | |
252 void ScriptController::enableEval() | 212 void ScriptController::enableEval() |
253 { | 213 { |
254 if (!m_windowProxyManager->mainWorldProxy()->isContextInitialized()) | 214 if (!m_windowProxyManager->mainWorldProxy()->isContextInitialized()) |
255 return; | 215 return; |
256 v8::HandleScope handleScope(isolate()); | 216 v8::HandleScope handleScope(isolate()); |
257 m_windowProxyManager->mainWorldProxy()->context()->AllowCodeGenerationFromSt
rings(true); | 217 m_windowProxyManager->mainWorldProxy()->context()->AllowCodeGenerationFromSt
rings(true); |
258 } | 218 } |
259 | 219 |
260 void ScriptController::disableEval(const String& errorMessage) | 220 void ScriptController::disableEval(const String& errorMessage) |
261 { | 221 { |
(...skipping 11 matching lines...) Expand all Loading... |
273 | 233 |
274 if (!widget->isPluginView()) | 234 if (!widget->isPluginView()) |
275 return nullptr; | 235 return nullptr; |
276 | 236 |
277 v8::HandleScope handleScope(isolate()); | 237 v8::HandleScope handleScope(isolate()); |
278 v8::Local<v8::Object> scriptableObject = toPluginView(widget)->scriptableObj
ect(isolate()); | 238 v8::Local<v8::Object> scriptableObject = toPluginView(widget)->scriptableObj
ect(isolate()); |
279 | 239 |
280 if (scriptableObject.IsEmpty()) | 240 if (scriptableObject.IsEmpty()) |
281 return nullptr; | 241 return nullptr; |
282 | 242 |
283 // LocalFrame Memory Management for NPObjects | |
284 // ------------------------------------- | |
285 // NPObjects are treated differently than other objects wrapped by JS. | |
286 // NPObjects can be created either by the browser (e.g. the main | |
287 // window object) or by the plugin (the main plugin object | |
288 // for a HTMLEmbedElement). Further, unlike most DOM Objects, the frame | |
289 // is especially careful to ensure NPObjects terminate at frame teardown bec
ause | |
290 // if a plugin leaks a reference, it could leak its objects (or the browser'
s objects). | |
291 // | |
292 // The LocalFrame maintains a list of plugin objects (m_pluginObjects) | |
293 // which it can use to quickly find the wrapped embed object. | |
294 // | |
295 // Inside the NPRuntime, we've added a few methods for registering | |
296 // wrapped NPObjects. The purpose of the registration is because | |
297 // javascript garbage collection is non-deterministic, yet we need to | |
298 // be able to tear down the plugin objects immediately. When an object | |
299 // is registered, javascript can use it. When the object is destroyed, | |
300 // or when the object's "owning" object is destroyed, the object will | |
301 // be un-registered, and the javascript engine must not use it. | |
302 // | |
303 // Inside the javascript engine, the engine can keep a reference to the | |
304 // NPObject as part of its wrapper. However, before accessing the object | |
305 // it must consult the _NPN_Registry. | |
306 | |
307 if (isWrappedNPObject(scriptableObject)) { | |
308 // Track the plugin object. We've been given a reference to the object. | |
309 m_pluginObjects.set(widget, v8ObjectToNPObject(scriptableObject)); | |
310 } | |
311 | |
312 return SharedPersistent<v8::Object>::create(scriptableObject, isolate()); | 243 return SharedPersistent<v8::Object>::create(scriptableObject, isolate()); |
313 } | 244 } |
314 | 245 |
315 void ScriptController::cleanupScriptObjectsForPlugin(Widget* nativeHandle) | |
316 { | |
317 PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle); | |
318 if (it == m_pluginObjects.end()) | |
319 return; | |
320 _NPN_UnregisterObject(it->value); | |
321 _NPN_ReleaseObject(it->value); | |
322 m_pluginObjects.remove(it); | |
323 } | |
324 | |
325 V8Extensions& ScriptController::registeredExtensions() | 246 V8Extensions& ScriptController::registeredExtensions() |
326 { | 247 { |
327 DEFINE_STATIC_LOCAL(V8Extensions, extensions, ()); | 248 DEFINE_STATIC_LOCAL(V8Extensions, extensions, ()); |
328 return extensions; | 249 return extensions; |
329 } | 250 } |
330 | 251 |
331 void ScriptController::registerExtensionIfNeeded(v8::Extension* extension) | 252 void ScriptController::registerExtensionIfNeeded(v8::Extension* extension) |
332 { | 253 { |
333 const V8Extensions& extensions = registeredExtensions(); | 254 const V8Extensions& extensions = registeredExtensions(); |
334 for (size_t i = 0; i < extensions.size(); ++i) { | 255 for (size_t i = 0; i < extensions.size(); ++i) { |
335 if (extensions[i] == extension) | 256 if (extensions[i] == extension) |
336 return; | 257 return; |
337 } | 258 } |
338 v8::RegisterExtension(extension); | 259 v8::RegisterExtension(extension); |
339 registeredExtensions().append(extension); | 260 registeredExtensions().append(extension); |
340 } | 261 } |
341 | 262 |
342 static NPObject* createNoScriptObject() | |
343 { | |
344 notImplemented(); | |
345 return 0; | |
346 } | |
347 | |
348 static NPObject* createScriptObject(LocalFrame* frame, v8::Isolate* isolate) | |
349 { | |
350 ScriptState* scriptState = ScriptState::forMainWorld(frame); | |
351 if (!scriptState->contextIsValid()) | |
352 return createNoScriptObject(); | |
353 | |
354 ScriptState::Scope scope(scriptState); | |
355 LocalDOMWindow* window = frame->localDOMWindow(); | |
356 v8::Local<v8::Value> global = toV8(window, scriptState->context()->Global(),
scriptState->isolate()); | |
357 if (global.IsEmpty()) | |
358 return createNoScriptObject(); | |
359 ASSERT(global->IsObject()); | |
360 return npCreateV8ScriptObject(isolate, 0, v8::Local<v8::Object>::Cast(global
), window); | |
361 } | |
362 | |
363 NPObject* ScriptController::windowScriptNPObject() | |
364 { | |
365 if (m_windowScriptNPObject) | |
366 return m_windowScriptNPObject; | |
367 | |
368 if (canExecuteScripts(NotAboutToExecuteScript)) { | |
369 // JavaScript is enabled, so there is a JavaScript window object. | |
370 // Return an NPObject bound to the window object. | |
371 m_windowScriptNPObject = createScriptObject(frame(), isolate()); | |
372 _NPN_RegisterObject(m_windowScriptNPObject, 0); | |
373 } else { | |
374 // JavaScript is not enabled, so we cannot bind the NPObject to the | |
375 // JavaScript window object. Instead, we create an NPObject of a | |
376 // different class, one which is not bound to a JavaScript object. | |
377 m_windowScriptNPObject = createNoScriptObject(); | |
378 } | |
379 return m_windowScriptNPObject; | |
380 } | |
381 | |
382 NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement
* plugin) | |
383 { | |
384 // Can't create NPObjects when JavaScript is disabled. | |
385 if (!canExecuteScripts(NotAboutToExecuteScript)) | |
386 return createNoScriptObject(); | |
387 | |
388 ScriptState* scriptState = ScriptState::forMainWorld(frame()); | |
389 if (!scriptState->contextIsValid()) | |
390 return createNoScriptObject(); | |
391 | |
392 ScriptState::Scope scope(scriptState); | |
393 LocalDOMWindow* window = frame()->localDOMWindow(); | |
394 v8::Local<v8::Value> v8plugin = toV8(plugin, scriptState->context()->Global(
), scriptState->isolate()); | |
395 if (v8plugin.IsEmpty() || !v8plugin->IsObject()) | |
396 return createNoScriptObject(); | |
397 | |
398 return npCreateV8ScriptObject(scriptState->isolate(), 0, v8::Local<v8::Objec
t>::Cast(v8plugin), window); | |
399 } | |
400 | |
401 void ScriptController::clearWindowProxy() | 263 void ScriptController::clearWindowProxy() |
402 { | 264 { |
403 // V8 binding expects ScriptController::clearWindowProxy only be called | 265 // V8 binding expects ScriptController::clearWindowProxy only be called |
404 // when a frame is loading a new page. This creates a new context for the ne
w page. | 266 // when a frame is loading a new page. This creates a new context for the ne
w page. |
405 | 267 |
406 double start = currentTime(); | 268 double start = currentTime(); |
407 // The V8 context must be available for |clearScriptObjects()|. | |
408 // The below call must be before |clearForNavigation()| which disposes the V
8 context. | |
409 clearScriptObjects(); | |
410 | 269 |
411 m_windowProxyManager->clearForNavigation(); | 270 m_windowProxyManager->clearForNavigation(); |
412 Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearWi
ndowProxy", (currentTime() - start) * 1000, 0, 10000, 50); | 271 Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearWi
ndowProxy", (currentTime() - start) * 1000, 0, 10000, 50); |
413 } | 272 } |
414 | 273 |
415 void ScriptController::setCaptureCallStackForUncaughtExceptions(v8::Isolate* iso
late, bool value) | 274 void ScriptController::setCaptureCallStackForUncaughtExceptions(v8::Isolate* iso
late, bool value) |
416 { | 275 { |
417 isolate->SetCaptureStackTraceForUncaughtExceptions(value, ScriptCallStack::m
axCallStackSizeToCapture, stackTraceOptions); | 276 isolate->SetCaptureStackTraceForUncaughtExceptions(value, ScriptCallStack::m
axCallStackSizeToCapture, stackTraceOptions); |
418 } | 277 } |
419 | 278 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 for (size_t i = 0; i < resultArray->Length(); ++i) { | 455 for (size_t i = 0; i < resultArray->Length(); ++i) { |
597 v8::Local<v8::Value> value; | 456 v8::Local<v8::Value> value; |
598 if (!resultArray->Get(scriptState->context(), i).ToLocal(&value)) | 457 if (!resultArray->Get(scriptState->context(), i).ToLocal(&value)) |
599 return; | 458 return; |
600 results->append(value); | 459 results->append(value); |
601 } | 460 } |
602 } | 461 } |
603 } | 462 } |
604 | 463 |
605 } // namespace blink | 464 } // namespace blink |
OLD | NEW |