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