PassRefPtr<SharedPersistent<v8::Object>> ScriptController::createPluginWrapper(Widget* widget) { ASSERT(widget); if (!widget->isPluginView()) return nullptr; v8::HandleScope handleScope(isolate()); v8::Local<v8::Object> scriptableObject = toPluginView(widget)->scriptableObject(isolate()); if (scriptableObject.IsEmpty()) return nullptr; // LocalFrame Memory Management for NPObjects // ------------------------------------- // NPObjects are treated differently than other objects wrapped by JS. // NPObjects can be created either by the browser (e.g. the main // window object) or by the plugin (the main plugin object // for a HTMLEmbedElement). Further, unlike most DOM Objects, the frame // is especially careful to ensure NPObjects terminate at frame teardown because // if a plugin leaks a reference, it could leak its objects (or the browser's objects). // // The LocalFrame maintains a list of plugin objects (m_pluginObjects) // which it can use to quickly find the wrapped embed object. // // Inside the NPRuntime, we've added a few methods for registering // wrapped NPObjects. The purpose of the registration is because // javascript garbage collection is non-deterministic, yet we need to // be able to tear down the plugin objects immediately. When an object // is registered, javascript can use it. When the object is destroyed, // or when the object's "owning" object is destroyed, the object will // be un-registered, and the javascript engine must not use it. // // Inside the javascript engine, the engine can keep a reference to the // NPObject as part of its wrapper. However, before accessing the object // it must consult the _NPN_Registry. if (isWrappedNPObject(scriptableObject)) { // Track the plugin object. We've been given a reference to the object. m_pluginObjects.set(widget, v8ObjectToNPObject(scriptableObject)); } return SharedPersistent<v8::Object>::create(scriptableObject, isolate()); }
NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, LocalDOMWindow* root, v8::Isolate* isolate) { // Check to see if this object is already wrapped. if (isWrappedNPObject(object)) { NPObject* returnValue = v8ObjectToNPObject(object); _NPN_RetainObject(returnValue); return returnValue; } V8NPObjectVector* objectVector = 0; if (V8PerContextData* perContextData = V8PerContextData::from(object->CreationContext())) { int v8ObjectHash = object->GetIdentityHash(); ASSERT(v8ObjectHash); V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap(); V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash); if (iter != v8NPObjectMap->end()) { V8NPObjectVector& objects = iter->value; for (size_t index = 0; index < objects.size(); ++index) { V8NPObject* v8npObject = objects.at(index); if (v8npObject->v8Object == object && v8npObject->rootObject == root) { _NPN_RetainObject(&v8npObject->object); return reinterpret_cast<NPObject*>(v8npObject); } } objectVector = &iter->value; } else { objectVector = &v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).storedValue->value; } } V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass)); // This is uninitialized memory, we need to clear it so that // Persistent::Reset won't try to Dispose anything bogus. new (&v8npObject->v8Object) v8::Persistent<v8::Object>(); v8npObject->v8Object.Reset(isolate, object); v8npObject->rootObject = root; if (objectVector) objectVector->append(v8npObject); return reinterpret_cast<NPObject*>(v8npObject); }