| 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 |