| OLD | NEW |
| 1 // Copyright (c) 2008, Google Inc. | 1 // Copyright (c) 2008, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 #include "config.h" | 30 #include "config.h" |
| 31 #include "ScriptController.h" | 31 #include "ScriptController.h" |
| 32 | 32 |
| 33 #include "CString.h" | 33 #include "bindings/npruntime.h" |
| 34 #include "Document.h" | 34 #include "c_instance.h" |
| 35 #include "DOMWindow.h" | |
| 36 #include "Event.h" | |
| 37 #include "EventListener.h" | |
| 38 #include "EventNames.h" | |
| 39 #include "Frame.h" | |
| 40 #include "Node.h" | |
| 41 #include "NotImplemented.h" | |
| 42 #include "npruntime_priv.h" | |
| 43 #include "np_v8object.h" | |
| 44 #include "PausedTimeouts.h" | |
| 45 #include "Widget.h" | |
| 46 | 35 |
| 47 #include "v8_proxy.h" | |
| 48 #include "v8_binding.h" | |
| 49 #include "v8_npobject.h" | |
| 50 | |
| 51 //TODO(eseidel): We should remove this glue dependency | |
| 52 #undef LOG // glue defines its own LOG macro | 36 #undef LOG // glue defines its own LOG macro |
| 53 #include "webkit/glue/webplugin_impl.h" | 37 #include "webkit/glue/webplugin_impl.h" |
| 54 | 38 |
| 55 NPRuntimeFunctions npruntime_functions = { | |
| 56 NPN_GetStringIdentifier, | |
| 57 NPN_GetStringIdentifiers, | |
| 58 NPN_GetIntIdentifier, | |
| 59 NPN_IdentifierIsString, | |
| 60 NPN_UTF8FromIdentifier, | |
| 61 NPN_IntFromIdentifier, | |
| 62 NPN_CreateObject, | |
| 63 NPN_RetainObject, | |
| 64 NPN_ReleaseObject, | |
| 65 NPN_Invoke, | |
| 66 NPN_InvokeDefault, | |
| 67 NPN_Evaluate, | |
| 68 NPN_GetProperty, | |
| 69 NPN_SetProperty, | |
| 70 NPN_RemoveProperty, | |
| 71 NPN_HasProperty, | |
| 72 NPN_HasMethod, | |
| 73 NPN_ReleaseVariantValue, | |
| 74 NPN_SetException | |
| 75 }; | |
| 76 | |
| 77 | |
| 78 namespace WebCore { | 39 namespace WebCore { |
| 79 | 40 |
| 80 bool ScriptController::m_recordPlaybackMode = false; | |
| 81 | |
| 82 void ScriptController::setFlags(const char* str, int length) | |
| 83 { | |
| 84 v8::V8::SetFlagsFromString(str, length); | |
| 85 } | |
| 86 | |
| 87 void ScriptController::setDomain(Frame* frame, const String&) | |
| 88 { | |
| 89 V8Proxy::DomainChanged(frame); | |
| 90 } | |
| 91 | |
| 92 Frame* ScriptController::retrieveActiveFrame() | |
| 93 { | |
| 94 return V8Proxy::retrieveActiveFrame(); | |
| 95 } | |
| 96 | |
| 97 bool ScriptController::isSafeScript(Frame* target) | |
| 98 { | |
| 99 return V8Proxy::CanAccessFrame(target, true); | |
| 100 } | |
| 101 | |
| 102 void ScriptController::gcProtectJSWrapper(void* dom_object) | |
| 103 { | |
| 104 V8Proxy::GCProtect(static_cast<Peerable*>(dom_object)); | |
| 105 } | |
| 106 | |
| 107 void ScriptController::gcUnprotectJSWrapper(void* dom_object) | |
| 108 { | |
| 109 V8Proxy::GCUnprotect(static_cast<Peerable*>(dom_object)); | |
| 110 } | |
| 111 | |
| 112 void ScriptController::pauseTimeouts(OwnPtr<PausedTimeouts>& result) | |
| 113 { | |
| 114 DOMWindow* window = m_frame->domWindow(); | |
| 115 if (!window) { | |
| 116 result.clear(); | |
| 117 return; | |
| 118 } | |
| 119 window->pauseTimeouts(result); | |
| 120 } | |
| 121 | |
| 122 void ScriptController::resumeTimeouts(OwnPtr<PausedTimeouts>& timeouts) | |
| 123 { | |
| 124 DOMWindow* window = m_frame->domWindow(); | |
| 125 if (!window) { | |
| 126 timeouts.clear(); | |
| 127 return; | |
| 128 } | |
| 129 window->resumeTimeouts(timeouts); | |
| 130 } | |
| 131 | |
| 132 ScriptController::ScriptController(Frame* frame) | |
| 133 : m_frame(frame) | |
| 134 , m_sourceURL(0) | |
| 135 , m_processingTimerCallback(false) | |
| 136 , m_paused(false) | |
| 137 , m_proxy(new V8Proxy(frame)) | |
| 138 #if ENABLE(NETSCAPE_PLUGIN_API) | |
| 139 , m_windowScriptNPObject(0) | |
| 140 #endif | |
| 141 { | |
| 142 } | |
| 143 | |
| 144 ScriptController::~ScriptController() | |
| 145 { | |
| 146 } | |
| 147 | |
| 148 void ScriptController::clearScriptObjects() | |
| 149 { | |
| 150 // TODO(eseidel): JSC handles binding root objects here, why don't we? | |
| 151 | |
| 152 #if ENABLE(NETSCAPE_PLUGIN_API) | |
| 153 if (m_windowScriptNPObject) { | |
| 154 // Call _NPN_DeallocateObject() instead of _NPN_ReleaseObject() so that
we don't leak if a plugin fails to release the window | |
| 155 // script object properly. | |
| 156 // This shouldn't cause any problems for plugins since they should have
already been stopped and destroyed at this point. | |
| 157 _NPN_DeallocateObject(m_windowScriptNPObject); | |
| 158 m_windowScriptNPObject = 0; | |
| 159 } | |
| 160 #endif | |
| 161 } | |
| 162 | |
| 163 void ScriptController::clearPluginObjects() | |
| 164 { | |
| 165 PluginObjectMap::iterator it = m_pluginObjects.begin(); | |
| 166 for (; it != m_pluginObjects.end(); ++it) { | |
| 167 _NPN_UnregisterObject(it->second); | |
| 168 NPN_ReleaseObject(it->second); | |
| 169 } | |
| 170 m_pluginObjects.clear(); | |
| 171 } | |
| 172 | |
| 173 // Disconnect the proxy from its owner frame; | |
| 174 void ScriptController::disconnectFrame() | |
| 175 { | |
| 176 m_proxy->disconnectFrame(); | |
| 177 } | |
| 178 | |
| 179 bool ScriptController::processingUserGesture() const | |
| 180 { | |
| 181 Frame* active_frame = V8Proxy::retrieveActiveFrame(); | |
| 182 // No script is running, must be run by users. | |
| 183 if (!active_frame) | |
| 184 return true; | |
| 185 | |
| 186 V8Proxy* active_proxy = active_frame->script()->proxy(); | |
| 187 | |
| 188 v8::HandleScope handle_scope; | |
| 189 v8::Handle<v8::Context> context = V8Proxy::GetContext(active_frame); | |
| 190 // TODO(fqian): find all cases context can be empty: | |
| 191 // 1) JS is disabled; | |
| 192 // 2) page is NULL; | |
| 193 if (context.IsEmpty()) | |
| 194 return true; | |
| 195 | |
| 196 v8::Context::Scope scope(context); | |
| 197 | |
| 198 v8::Handle<v8::Object> global = context->Global(); | |
| 199 v8::Handle<v8::Value> jsevent = global->Get(v8::String::NewSymbol("event")); | |
| 200 Event* event = V8Proxy::ToNativeEvent(jsevent); | |
| 201 | |
| 202 // Based on code from kjs_bindings.cpp. | |
| 203 // Note: This is more liberal than Firefox's implementation. | |
| 204 if (event) { | |
| 205 const AtomicString& type = event->type(); | |
| 206 bool event_ok = | |
| 207 // mouse events | |
| 208 type == EventNames::clickEvent || | |
| 209 type == EventNames::mousedownEvent || | |
| 210 type == EventNames::mouseupEvent || | |
| 211 type == EventNames::dblclickEvent || | |
| 212 // keyboard events | |
| 213 type == EventNames::keydownEvent || | |
| 214 type == EventNames::keypressEvent || | |
| 215 type == EventNames::keyupEvent || | |
| 216 // other accepted events | |
| 217 type == EventNames::selectEvent || | |
| 218 type == EventNames::changeEvent || | |
| 219 type == EventNames::focusEvent || | |
| 220 type == EventNames::blurEvent || | |
| 221 type == EventNames::submitEvent; | |
| 222 | |
| 223 if (event_ok) | |
| 224 return true; | |
| 225 } else if (active_proxy->inlineCode() && !active_proxy->timerCallback()) | |
| 226 // This is the <a href="javascript:window.open('...')> case -> we let it | |
| 227 // through | |
| 228 return true; | |
| 229 | |
| 230 // This is the <script>window.open(...)</script> case or a timer callback -> | |
| 231 // block it | |
| 232 return false; | |
| 233 } | |
| 234 | |
| 235 | |
| 236 // Evaluate a script file in the environment of this proxy. | |
| 237 String ScriptController::evaluate(const String& filename, int baseLine, | |
| 238 const String& code, Node* node, bool* succ) | |
| 239 { | |
| 240 if (succ) | |
| 241 *succ = false; | |
| 242 String result; | |
| 243 | |
| 244 v8::HandleScope hs; | |
| 245 v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); | |
| 246 if (context.IsEmpty()) | |
| 247 return result; | |
| 248 | |
| 249 v8::Context::Scope scope(context); | |
| 250 | |
| 251 // HTMLTokenizer used to use base zero line numbers for scripts, now it | |
| 252 // uses base 1. This confuses v8, which uses line offsets from the | |
| 253 // first line. | |
| 254 v8::Local<v8::Value> obj = m_proxy->Evaluate(filename, baseLine - 1, code, | |
| 255 node); | |
| 256 | |
| 257 if (obj.IsEmpty() || obj->IsUndefined()) | |
| 258 return result; | |
| 259 | |
| 260 // If the return value is not a string, return 0 (what KJS does). | |
| 261 if (!obj->IsString()) { | |
| 262 v8::TryCatch exception_block; | |
| 263 obj = obj->ToString(); | |
| 264 if (exception_block.HasCaught()) | |
| 265 obj = v8::String::New(""); | |
| 266 } | |
| 267 | |
| 268 result = ToWebCoreString(obj); | |
| 269 if (succ) | |
| 270 *succ = true; | |
| 271 | |
| 272 return result; | |
| 273 } | |
| 274 | |
| 275 v8::Persistent<v8::Value> ScriptController::evaluate(const String& filename, | |
| 276 int baseLine, | |
| 277 const String& code, | |
| 278 Node* node) | |
| 279 { | |
| 280 v8::HandleScope hs; | |
| 281 v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); | |
| 282 if (context.IsEmpty()) | |
| 283 return v8::Persistent<v8::Value>(); | |
| 284 | |
| 285 v8::Context::Scope scope(context); | |
| 286 | |
| 287 v8::Local<v8::Value> obj = m_proxy->Evaluate(filename, baseLine, code, node)
; | |
| 288 | |
| 289 if (obj.IsEmpty()) | |
| 290 return v8::Persistent<v8::Value>(); | |
| 291 | |
| 292 // TODO(fqian): keep track the global handle created. | |
| 293 return v8::Persistent<v8::Value>::New(obj); | |
| 294 } | |
| 295 | |
| 296 void ScriptController::disposeJSResult(v8::Persistent<v8::Value> result) | |
| 297 { | |
| 298 result.Dispose(); | |
| 299 result.Clear(); | |
| 300 } | |
| 301 | |
| 302 PassRefPtr<EventListener> ScriptController::createHTMLEventHandler( | |
| 303 const String& functionName, const String& code, Node* node) | |
| 304 { | |
| 305 return m_proxy->createHTMLEventHandler(functionName, code, node); | |
| 306 } | |
| 307 | |
| 308 #if ENABLE(SVG) | |
| 309 PassRefPtr<EventListener> ScriptController::createSVGEventHandler( | |
| 310 const String& functionName, const String& code, Node* node) | |
| 311 { | |
| 312 return m_proxy->createSVGEventHandler(functionName, code, node); | |
| 313 } | |
| 314 #endif | |
| 315 | |
| 316 void ScriptController::setEventHandlerLineno(int lineno) | |
| 317 { | |
| 318 m_proxy->setEventHandlerLineno(lineno); | |
| 319 } | |
| 320 | |
| 321 void ScriptController::finishedWithEvent(Event* evt) | |
| 322 { | |
| 323 m_proxy->finishedWithEvent(evt); | |
| 324 } | |
| 325 | |
| 326 void ScriptController::clearDocumentWrapper() | |
| 327 { | |
| 328 m_proxy->clearDocumentWrapper(); | |
| 329 } | |
| 330 | |
| 331 // Create a V8 object with an interceptor of NPObjectPropertyGetter | |
| 332 void ScriptController::BindToWindowObject(Frame* frame, const String& key, NPObj
ect* object) | |
| 333 { | |
| 334 v8::HandleScope handle_scope; | |
| 335 | |
| 336 v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); | |
| 337 if (context.IsEmpty()) | |
| 338 return; | |
| 339 | |
| 340 v8::Context::Scope scope(context); | |
| 341 | |
| 342 v8::Handle<v8::Object> value = CreateV8ObjectForNPObject(object, NULL); | |
| 343 | |
| 344 // Attach to the global object | |
| 345 v8::Handle<v8::Object> global = context->Global(); | |
| 346 global->Set(v8String(key), value); | |
| 347 } | |
| 348 | |
| 349 void ScriptController::collectGarbage() | |
| 350 { | |
| 351 v8::HandleScope hs; | |
| 352 v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); | |
| 353 if (context.IsEmpty()) | |
| 354 return; | |
| 355 | |
| 356 v8::Context::Scope scope(context); | |
| 357 | |
| 358 m_proxy->Evaluate("", 0, "if (window.gc) void(gc());", NULL); | |
| 359 } | |
| 360 | |
| 361 NPRuntimeFunctions* ScriptController::functions() | |
| 362 { | |
| 363 return &npruntime_functions; | |
| 364 } | |
| 365 | |
| 366 | |
| 367 bool ScriptController::haveInterpreter() const | |
| 368 { | |
| 369 return m_proxy->ContextInitialized(); | |
| 370 } | |
| 371 | |
| 372 bool ScriptController::isEnabled() const | |
| 373 { | |
| 374 return m_proxy->isEnabled(); | |
| 375 } | |
| 376 | |
| 377 JSInstanceHandle ScriptController::createScriptInstanceForWidget(Widget* widget) | 41 JSInstanceHandle ScriptController::createScriptInstanceForWidget(Widget* widget) |
| 378 { | 42 { |
| 379 ASSERT(widget != 0); | 43 ASSERT(widget != 0); |
| 380 | 44 |
| 381 if (widget->isFrameView()) | 45 if (widget->isFrameView()) |
| 382 return JSInstanceHolder::EmptyInstance(); | 46 return JSInstanceHolder::EmptyInstance(); |
| 383 | 47 |
| 384 // Note: We have to trust that the widget passed to us here | 48 // Note: We have to trust that the widget passed to us here |
| 385 // is a WebPluginImpl. There isn't a way to dynamically verify | 49 // is a WebPluginImpl. There isn't a way to dynamically verify |
| 386 // it, since the derived class (Widget) has no identifier. | 50 // it, since the derived class (Widget) has no identifier. |
| 387 WebPluginContainer* container = static_cast<WebPluginContainer*>(widget); | 51 WebPluginContainer* container = static_cast<WebPluginContainer*>(widget); |
| 388 if (!container) | 52 if (!container) |
| 389 return JSInstanceHolder::EmptyInstance(); | 53 return JSInstanceHolder::EmptyInstance(); |
| 390 | 54 |
| 391 NPObject* npObject = container->GetPluginScriptableObject(); | 55 NPObject* npObject = container->GetPluginScriptableObject(); |
| 392 if (!npObject) | 56 if (!npObject) |
| 393 return JSInstanceHolder::EmptyInstance(); | 57 return JSInstanceHolder::EmptyInstance(); |
| 394 | 58 |
| 395 #if USE(JSC) | |
| 396 // Register 'widget' with the frame so that we can teardown | 59 // Register 'widget' with the frame so that we can teardown |
| 397 // subobjects when the container goes away. | 60 // subobjects when the container goes away. |
| 398 RefPtr<KJS::Bindings::RootObject> root = script()->createRootObject(widget); | 61 RefPtr<JSC::Bindings::RootObject> root = createRootObject(widget); |
| 399 KJS::Bindings::Instance* instance = | 62 RefPtr<JSC::Bindings::Instance> instance = |
| 400 KJS::Bindings::Instance::createBindingForLanguageInstance( | 63 JSC::Bindings::CInstance::create(npObject, root.release()); |
| 401 KJS::Bindings::Instance::CLanguage, npObject, | |
| 402 root.release()); | |
| 403 // GetPluginScriptableObject returns a retained NPObject. | 64 // GetPluginScriptableObject returns a retained NPObject. |
| 404 // The caller is expected to release it. | 65 // The caller is expected to release it. |
| 405 NPN_ReleaseObject(npObject); | 66 NPN_ReleaseObject(npObject); |
| 406 return instance; | 67 return instance.release(); |
| 407 #elif USE(V8) | |
| 408 // Frame Memory Management for NPObjects | |
| 409 // ------------------------------------- | |
| 410 // NPObjects are treated differently than other objects wrapped by JS. | |
| 411 // NPObjects are not Peerable, and cannot be made peerable, since NPObjects | |
| 412 // can be created either by the browser (e.g. the main window object) or by | |
| 413 // the plugin (the main plugin object for a HTMLEmbedElement). Further, | |
| 414 // unlike most DOM Objects, the frame is especially careful to ensure | |
| 415 // NPObjects terminate at frame teardown because if a plugin leaks a | |
| 416 // reference, it could leak its objects (or the browser's objects). | |
| 417 // | |
| 418 // The Frame maintains a list of plugin objects (m_pluginObjects) | |
| 419 // which it can use to quickly find the wrapped embed object. | |
| 420 // | |
| 421 // Inside the NPRuntime, we've added a few methods for registering | |
| 422 // wrapped NPObjects. The purpose of the registration is because | |
| 423 // javascript garbage collection is non-deterministic, yet we need to | |
| 424 // be able to tear down the plugin objects immediately. When an object | |
| 425 // is registered, javascript can use it. When the object is destroyed, | |
| 426 // or when the object's "owning" object is destroyed, the object will | |
| 427 // be un-registered, and the javascript engine must not use it. | |
| 428 // | |
| 429 // Inside the javascript engine, the engine can keep a reference to the | |
| 430 // NPObject as part of its wrapper. However, before accessing the object | |
| 431 // it must consult the NPN_Registry. | |
| 432 | |
| 433 v8::Local<v8::Object> wrapper = CreateV8ObjectForNPObject(npObject, NULL); | |
| 434 | |
| 435 // Track the plugin object. We've been given a reference to the object. | |
| 436 m_pluginObjects.set(widget, npObject); | |
| 437 | |
| 438 JSInstance instance = wrapper; | |
| 439 return instance; | |
| 440 #endif | |
| 441 } | |
| 442 | |
| 443 void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) | |
| 444 { | |
| 445 PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle); | |
| 446 if (it == m_pluginObjects.end()) | |
| 447 return; | |
| 448 _NPN_UnregisterObject(it->second); | |
| 449 NPN_ReleaseObject(it->second); | |
| 450 m_pluginObjects.remove(it); | |
| 451 } | |
| 452 | |
| 453 static NPObject* createNoScriptObject() | |
| 454 { | |
| 455 notImplemented(); | |
| 456 return 0; | |
| 457 } | |
| 458 | |
| 459 static NPObject* createScriptObject(Frame* frame) | |
| 460 { | |
| 461 v8::HandleScope handleScope; | |
| 462 v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); | |
| 463 if (context.IsEmpty()) | |
| 464 return createNoScriptObject(); | |
| 465 | |
| 466 v8::Context::Scope scope(context); | |
| 467 DOMWindow* window = frame->domWindow(); | |
| 468 v8::Handle<v8::Value> global = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW,
window); | |
| 469 ASSERT(global->IsObject()); | |
| 470 return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(global), windo
w); | |
| 471 } | |
| 472 | |
| 473 NPObject* ScriptController::windowScriptNPObject() | |
| 474 { | |
| 475 if (m_windowScriptNPObject) | |
| 476 return m_windowScriptNPObject; | |
| 477 | |
| 478 if (isEnabled()) { | |
| 479 // JavaScript is enabled, so there is a JavaScript window object. | |
| 480 // Return an NPObject bound to the window object. | |
| 481 m_windowScriptNPObject = createScriptObject(m_frame); | |
| 482 _NPN_RegisterObject(m_windowScriptNPObject, NULL); | |
| 483 } else { | |
| 484 // JavaScript is not enabled, so we cannot bind the NPObject to the | |
| 485 // JavaScript window object. Instead, we create an NPObject of a | |
| 486 // different class, one which is not bound to a JavaScript object. | |
| 487 m_windowScriptNPObject = createNoScriptObject(); | |
| 488 } | |
| 489 return m_windowScriptNPObject; | |
| 490 } | |
| 491 | |
| 492 NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement
* plugin) | |
| 493 { | |
| 494 // Can't create NPObjects when JavaScript is disabled | |
| 495 if (!isEnabled()) | |
| 496 return createNoScriptObject(); | |
| 497 | |
| 498 v8::HandleScope handleScope; | |
| 499 v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); | |
| 500 if (context.IsEmpty()) | |
| 501 return createNoScriptObject(); | |
| 502 v8::Context::Scope scope(context); | |
| 503 | |
| 504 DOMWindow* window = m_frame->domWindow(); | |
| 505 v8::Handle<v8::Value> v8plugin = V8Proxy::ToV8Object(V8ClassIndex::HTMLEMBED
ELEMENT, plugin); | |
| 506 if (!v8plugin->IsObject()) | |
| 507 return createNoScriptObject(); | |
| 508 | |
| 509 return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), win
dow); | |
| 510 } | |
| 511 | |
| 512 | |
| 513 void ScriptController::clearWindowShell() | |
| 514 { | |
| 515 m_proxy->clearForNavigation(); | |
| 516 } | |
| 517 | |
| 518 void ScriptController::attachDebugger(void*) | |
| 519 { | |
| 520 notImplemented(); | |
| 521 } | |
| 522 | |
| 523 void ScriptController::updateDocument() | |
| 524 { | |
| 525 // TODO(eseidel): Should update document property on current window object | |
| 526 // and all previous window objects which may still be alive. | |
| 527 notImplemented(); | |
| 528 } | |
| 529 | |
| 530 | |
| 531 JSInstanceHolder::JSInstanceHolder() | |
| 532 { | |
| 533 } | |
| 534 | |
| 535 JSInstanceHolder::JSInstanceHolder(JSInstanceHandle instance) | |
| 536 { | |
| 537 *this = instance; | |
| 538 } | |
| 539 | |
| 540 JSInstanceHolder::~JSInstanceHolder() | |
| 541 { | |
| 542 Clear(); | |
| 543 } | |
| 544 | |
| 545 bool JSInstanceHolder::IsEmpty() | |
| 546 { | |
| 547 return m_instance.IsEmpty(); | |
| 548 } | |
| 549 | |
| 550 JSInstance JSInstanceHolder::Get() | |
| 551 { | |
| 552 return v8::Local<v8::Object>::New(m_instance); | |
| 553 } | |
| 554 | |
| 555 void JSInstanceHolder::Clear() | |
| 556 { | |
| 557 if (m_instance.IsEmpty()) | |
| 558 return; | |
| 559 v8::HandleScope scope; | |
| 560 v8::Persistent<v8::Object> handle(m_instance); | |
| 561 #ifndef NDEBUG | |
| 562 V8Proxy::UnregisterGlobalHandle(this, handle); | |
| 563 #endif | |
| 564 handle.Dispose(); | |
| 565 m_instance.Clear(); | |
| 566 } | |
| 567 | |
| 568 JSInstance JSInstanceHolder::EmptyInstance() | |
| 569 { | |
| 570 return v8::Local<v8::Object>(); | |
| 571 } | |
| 572 | |
| 573 JSInstanceHolder& JSInstanceHolder::operator=(JSInstanceHandle instance) | |
| 574 { | |
| 575 Clear(); | |
| 576 if (instance.IsEmpty()) | |
| 577 return *this; | |
| 578 | |
| 579 v8::Persistent<v8::Object> handle = | |
| 580 v8::Persistent<v8::Object>::New(instance); | |
| 581 m_instance = handle; | |
| 582 #ifndef NDEBUG | |
| 583 V8Proxy::RegisterGlobalHandle(JSINSTANCE, this, handle); | |
| 584 #endif | |
| 585 return *this; | |
| 586 } | 68 } |
| 587 | 69 |
| 588 } // namespace WebCpre | 70 } // namespace WebCpre |
| OLD | NEW |