Changeset 54783 in webkit


Ignore:
Timestamp:
Feb 15, 2010 11:16:21 AM (14 years ago)
Author:
ap@apple.com
Message:

Reviewed by Kevin Decker.

<rdar://problem/7130641> Browser objects identity is not preserved by Safari

Test: plugins/netscape-browser-object-identity.html

  • bridge/runtime_root.h: (JSC::Bindings::RootObject::addInvalidationCallback): RootObject can now call out during invalidation, making it possible for other code to know when this happens.
  • bridge/runtime_root.cpp: (JSC::Bindings::RootObject::InvalidationCallback::~InvalidationCallback): Empty destructor, in cpp file since it's virtual. (JSC::Bindings::RootObject::invalidate): Invoke invalidation callbacks.
  • bridge/NP_jsobject.cpp: (ObjectMap): Keep a JSObject->NPObject map for each RootObject. It somewhat cleaner to keep it outside RootObject, because (1) it is agnostic of what kinds of objects can wrap JSObject, and (2) out of process NPAPI implementation also keeps its corresponding map separately, due to supporting per-instance granularity (as opposed to per-RootObject here). (jsDeallocate): Remove the corresponding map entry. (_NPN_CreateScriptObject): Try to fetch existing object from the map, incrementing refcount.
Location:
trunk
Files:
3 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r54780 r54783  
     12010-02-12  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Reviewed by Kevin Decker.
     4
     5        <rdar://problem/7130641> Browser objects identity is not preserved by Safari
     6
     7        * plugins/netscape-browser-object-identity-expected.txt: Added.
     8        * plugins/netscape-browser-object-identity.html: Added.
     9        * plugins/script-tests/netscape-browser-object-identity.js: Added.
     10
    1112010-02-15  Pavel Feldman  <pfeldman@chromium.org>
    212
  • trunk/WebCore/ChangeLog

    r54782 r54783  
     12010-02-12  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Reviewed by Kevin Decker.
     4
     5        <rdar://problem/7130641> Browser objects identity is not preserved by Safari
     6
     7        Test: plugins/netscape-browser-object-identity.html
     8
     9        * bridge/runtime_root.h: (JSC::Bindings::RootObject::addInvalidationCallback):
     10        RootObject can now call out during invalidation, making it possible for other code to know
     11        when this happens.
     12
     13        * bridge/runtime_root.cpp:
     14        (JSC::Bindings::RootObject::InvalidationCallback::~InvalidationCallback): Empty destructor,
     15        in cpp file since it's virtual.
     16        (JSC::Bindings::RootObject::invalidate): Invoke invalidation callbacks.
     17
     18        * bridge/NP_jsobject.cpp:
     19        (ObjectMap): Keep a JSObject->NPObject map for each RootObject. It somewhat cleaner to
     20        keep it outside RootObject, because (1) it is agnostic of what kinds of objects can wrap
     21        JSObject, and (2) out of process NPAPI implementation also keeps its corresponding map
     22        separately, due to supporting per-instance granularity (as opposed to per-RootObject here).
     23        (jsDeallocate): Remove the corresponding map entry.
     24        (_NPN_CreateScriptObject): Try to fetch existing object from the map, incrementing refcount.
     25
    1262010-02-15  Philippe Normand  <pnormand@igalia.com>
    227
  • trunk/WebCore/bridge/NP_jsobject.cpp

    r54614 r54783  
    5252using namespace WebCore;
    5353
     54class ObjectMap {
     55public:
     56    NPObject* get(RootObject* rootObject, JSObject* jsObject)
     57    {
     58        return m_map.get(rootObject).get(jsObject);
     59    }
     60
     61    void add(RootObject* rootObject, JSObject* jsObject, NPObject* npObject)
     62    {
     63        HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject);
     64        if (iter == m_map.end()) {
     65            rootObject->addInvalidationCallback(&m_invalidationCallback);
     66            iter = m_map.add(rootObject, JSToNPObjectMap()).first;
     67        }
     68
     69        ASSERT(iter->second.find(jsObject) == iter->second.end());
     70        iter->second.add(jsObject, npObject);
     71    }
     72
     73    void remove(RootObject* rootObject)
     74    {
     75        HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject);
     76        ASSERT(iter != m_map.end());
     77        m_map.remove(iter);
     78    }
     79
     80    void remove(RootObject* rootObject, JSObject* jsObject)
     81    {
     82        HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject);
     83        ASSERT(iter != m_map.end());
     84        ASSERT(iter->second.find(jsObject) != iter->second.end());
     85
     86        iter->second.remove(jsObject);
     87    }
     88
     89private:
     90    struct RootObjectInvalidationCallback : public RootObject::InvalidationCallback {
     91        virtual void operator()(RootObject*);
     92    };
     93    RootObjectInvalidationCallback m_invalidationCallback;
     94
     95    // JSObjects are protected by RootObject.
     96    typedef HashMap<JSObject*, NPObject*> JSToNPObjectMap;
     97    HashMap<RootObject*, JSToNPObjectMap> m_map;
     98};
     99
     100
     101static ObjectMap& objectMap()
     102{
     103    DEFINE_STATIC_LOCAL(ObjectMap, map, ());
     104    return map;
     105}
     106
     107void ObjectMap::RootObjectInvalidationCallback::operator()(RootObject* rootObject)
     108{
     109    objectMap().remove(rootObject);
     110}
     111
    54112static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, MarkedArgumentBuffer& aList)
    55113{
     
    67125    JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(npObj);
    68126
    69     if (obj->rootObject && obj->rootObject->isValid())
     127    if (obj->rootObject && obj->rootObject->isValid()) {
     128        objectMap().remove(obj->rootObject, obj->imp);
    70129        obj->rootObject->gcUnprotect(obj->imp);
     130    }
    71131
    72132    if (obj->rootObject)
     
    84144NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject)
    85145{
     146    if (NPObject* object = objectMap().get(rootObject.get(), imp))
     147        return _NPN_RetainObject(object);
     148
    86149    JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(_NPN_CreateObject(npp, NPScriptObjectClass));
    87150
    88151    obj->rootObject = rootObject.releaseRef();
    89152
    90     if (obj->rootObject)
     153    if (obj->rootObject) {
    91154        obj->rootObject->gcProtect(imp);
     155        objectMap().add(obj->rootObject, imp, reinterpret_cast<NPObject*>(obj));
     156    }
     157
    92158    obj->imp = imp;
    93159
  • trunk/WebCore/bridge/runtime_root.cpp

    r53464 r54783  
    7272}
    7373
     74RootObject::InvalidationCallback::~InvalidationCallback()
     75{
     76}
     77
    7478PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, JSGlobalObject* globalObject)
    7579{
     
    109113    m_nativeHandle = 0;
    110114    m_globalObject = 0;
     115
     116    {
     117        HashSet<InvalidationCallback*>::iterator end = m_invalidationCallbacks.end();
     118        for (HashSet<InvalidationCallback*>::iterator iter = m_invalidationCallbacks.begin(); iter != end; ++iter)
     119            (**iter)(this);
     120
     121        m_invalidationCallbacks.clear();
     122    }
    111123
    112124    ProtectCountSet::iterator end = m_protectCountSet.end();
  • trunk/WebCore/bridge/runtime_root.h

    r49754 r54783  
    7373    void addRuntimeObject(RuntimeObjectImp*);
    7474    void removeRuntimeObject(RuntimeObjectImp*);
     75
     76    struct InvalidationCallback {
     77        virtual void operator()(RootObject*) = 0;
     78        virtual ~InvalidationCallback();
     79    };
     80    void addInvalidationCallback(InvalidationCallback* callback) { m_invalidationCallbacks.add(callback); }
     81
    7582private:
    7683    RootObject(const void* nativeHandle, JSGlobalObject*);
     
    8087    const void* m_nativeHandle;
    8188    ProtectedPtr<JSGlobalObject> m_globalObject;
     89
    8290    ProtectCountSet m_protectCountSet;
     91    HashSet<RuntimeObjectImp*> m_runtimeObjects;   
    8392
    84     HashSet<RuntimeObjectImp*> m_runtimeObjects;   
     93    HashSet<InvalidationCallback*> m_invalidationCallbacks;
    8594};
    8695
  • trunk/WebKit/mac/ChangeLog

    r54733 r54783  
     12010-02-12  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Reviewed by Kevin Decker.
     4
     5        <rdar://problem/7130641> Browser objects identity is not preserved by Safari
     6
     7        Out of process part.
     8
     9        To avoid excessive IPC, plugin process doesn't send each NPObject release/retain call to
     10        Safari. It only sends one when the last one is removed, and it can destroy the proxy
     11        NPObject.
     12
     13        However, the browser may be sending the same object out to plug-in as a function call
     14        argument at the same time - neither side can know what the other one is up to. The solution
     15        is to make the "destroying object" call return a boolean result, making it possible for
     16        the browser to make plugin host keep the proxy with zero refcount for a little longer.
     17
     18        * Plugins/Hosted/NetscapePluginHostProxy.mm:
     19        (WKPCForgetBrowserObject): This function (that used to be named ReleaseObject) is only
     20        called when plug-in releases all of its references, so renamed it. Its boolean result
     21        is returned as call success or failure.
     22
     23        * Plugins/Hosted/NetscapePluginInstanceProxy.h:
     24        (WebKit::NetscapePluginInstanceProxy::LocalObjectMap): Made the numeric ID to JSObject map
     25        two-way.
     26
     27        * Plugins/Hosted/NetscapePluginInstanceProxy.mm:
     28        (WebKit::NetscapePluginInstanceProxy::LocalObjectMap::idForObject): This method is tricky
     29        in that it creates objects with refcount of 1, but doesn't increase refcount when returning
     30        found objects. This extra count accounts for the "reference" kept by plugin process.
     31        (WebKit::NetscapePluginInstanceProxy::LocalObjectMap::retain): Only retaining for the
     32        duration of calls out to plug-in, which means that refcount is almost always equal to 1.
     33        Note that we can't use "++" here, due to how std::pair works!
     34        (WebKit::NetscapePluginInstanceProxy::LocalObjectMap::release): Ditto.
     35        (WebKit::NetscapePluginInstanceProxy::LocalObjectMap::clear): Clear all references when
     36        stopping plug-in.
     37        (WebKit::NetscapePluginInstanceProxy::LocalObjectMap::forget): Like release(), but only
     38        functional when recount is 1 (meaning that the object is not being sent out to plug-in at
     39        the moment).
     40        (WebKit::NetscapePluginInstanceProxy::NetscapePluginInstanceProxy): Updated for other changes.
     41        (WebKit::NetscapePluginInstanceProxy::cleanup): Ditto.
     42        (WebKit::NetscapePluginInstanceProxy::getWindowNPObject): Ditto.
     43        (WebKit::NetscapePluginInstanceProxy::getPluginElementNPObject): Ditto.
     44        (WebKit::NetscapePluginInstanceProxy::forgetBrowserObjectID): Ditto.
     45        (WebKit::NetscapePluginInstanceProxy::evaluate): Ditto.
     46        (WebKit::NetscapePluginInstanceProxy::invoke): Ditto.
     47        (WebKit::NetscapePluginInstanceProxy::invokeDefault): Ditto.
     48        (WebKit::NetscapePluginInstanceProxy::construct): Ditto.
     49        (WebKit::NetscapePluginInstanceProxy::getProperty): Ditto.
     50        (WebKit::NetscapePluginInstanceProxy::setProperty): Ditto.
     51        (WebKit::NetscapePluginInstanceProxy::removeProperty): Ditto.
     52        (WebKit::NetscapePluginInstanceProxy::hasProperty): Ditto.
     53        (WebKit::NetscapePluginInstanceProxy::hasMethod): Ditto.
     54        (WebKit::NetscapePluginInstanceProxy::enumerate): Ditto.
     55        (WebKit::NetscapePluginInstanceProxy::addValueToArray): Ditto.
     56        (WebKit::NetscapePluginInstanceProxy::demarshalValueFromArray): Ditto.
     57        (WebKit::NetscapePluginInstanceProxy::retainLocalObject): Helper for calling retain when
     58        making calls out to plug-in. No-op for objects that aren't wrapped to be sent (i.e. for
     59        objects wrapping ProxyInstance wrappers for plug-in objects being sent bak).
     60        (WebKit::NetscapePluginInstanceProxy::releaseLocalObject): Ditto.
     61
     62        * Plugins/Hosted/ProxyInstance.mm:
     63        (WebKit::ProxyInstance::invoke): Retain/release arguments during call.
     64        (WebKit::ProxyInstance::setFieldValue): Ditto.
     65
     66        * Plugins/Hosted/WebKitPluginClient.defs: Renamed PCReleaseObject to PCForgetBrowserObject.
     67
    1682010-02-12  Darin Adler  <darin@apple.com>
    269
  • trunk/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm

    r54516 r54783  
    547547}
    548548
    549 kern_return_t WKPCReleaseObject(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID)
    550 {
    551     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
    552     if (!hostProxy)
    553         return KERN_FAILURE;
    554    
    555     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
    556     if (!instanceProxy)
    557         return KERN_FAILURE;
    558 
    559     instanceProxy->releaseObject(objectID);
    560     return KERN_SUCCESS;
     549kern_return_t WKPCForgetBrowserObject(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID)
     550{
     551    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
     552    if (!hostProxy)
     553        return KERN_FAILURE;
     554   
     555    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
     556    if (!instanceProxy)
     557        return KERN_FAILURE;
     558
     559    return instanceProxy->forgetBrowserObjectID(objectID) ? KERN_SUCCESS : KERN_FAILURE;
    561560}
    562561
  • trunk/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h

    r54504 r54783  
    112112    bool getWindowNPObject(uint32_t& objectID);
    113113    bool getPluginElementNPObject(uint32_t& objectID);
    114     void releaseObject(uint32_t objectID);
    115    
     114    bool forgetBrowserObjectID(uint32_t objectID); // Will fail if the ID is being sent to plug-in right now (i.e., retain/release calls aren't balanced).
     115
    116116    bool evaluate(uint32_t objectID, const WebCore::String& script, data_t& resultData, mach_msg_type_number_t& resultLength, bool allowPopups);
    117117    bool invoke(uint32_t objectID, const JSC::Identifier& methodName, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
     
    144144    PassRefPtr<JSC::Bindings::Instance> createBindingsInstance(PassRefPtr<JSC::Bindings::RootObject>);
    145145    RetainPtr<NSData *> marshalValues(JSC::ExecState*, const JSC::ArgList& args);
    146     void marshalValue(JSC::ExecState*, JSC::JSValue value, data_t& resultData, mach_msg_type_number_t& resultLength);
     146    void marshalValue(JSC::ExecState*, JSC::JSValue, data_t& resultData, mach_msg_type_number_t& resultLength);
    147147    JSC::JSValue demarshalValue(JSC::ExecState*, const char* valueData, mach_msg_type_number_t valueLength);
     148
     149    // No-op if the value does not contain a local object.
     150    void retainLocalObject(JSC::JSValue);
     151    void releaseLocalObject(JSC::JSValue);
    148152
    149153    void addInstance(ProxyInstance*);
     
    301305   
    302306    // NPRuntime
    303     uint32_t idForObject(JSC::JSObject*);
    304    
     307
    305308    void addValueToArray(NSMutableArray *, JSC::ExecState* exec, JSC::JSValue value);
    306309   
     
    308311    void demarshalValues(JSC::ExecState*, data_t valuesData, mach_msg_type_number_t valuesLength, JSC::MarkedArgumentBuffer& result);
    309312
    310     uint32_t m_objectIDCounter;
    311     typedef HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> > ObjectMap;
    312     ObjectMap m_objects;
    313    
     313    class LocalObjectMap {
     314    public:
     315        LocalObjectMap();
     316        uint32_t idForObject(JSC::JSObject*);
     317        void retain(JSC::JSObject*);
     318        void release(JSC::JSObject*);
     319        void clear();
     320        bool forget(uint32_t);
     321        bool contains(uint32_t objectID) const { return m_idToJSObjectMap.contains(objectID); }
     322        JSC::JSObject* get(uint32_t objectID) const { return m_idToJSObjectMap.get(objectID); }
     323
     324    private:
     325        HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> > m_idToJSObjectMap;
     326        // The pair consists of object ID and a reference count. One reference belongs to remote plug-in,
     327        // and the proxy will add transient references for arguments that are being sent out.
     328        HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> > m_jsObjectToIDMap;
     329        uint32_t m_objectIDCounter;
     330    };
     331
     332    LocalObjectMap m_localObjects;
     333
    314334    typedef HashSet<ProxyInstance*> ProxyInstanceSet;
    315335    ProxyInstanceSet m_instances;
  • trunk/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm

    r54504 r54783  
    101101};
    102102
     103NetscapePluginInstanceProxy::LocalObjectMap::LocalObjectMap()
     104    : m_objectIDCounter(0)
     105{
     106}
     107
     108uint32_t NetscapePluginInstanceProxy::LocalObjectMap::idForObject(JSObject* object)
     109{
     110    // This method creates objects with refcount of 1, but doesn't increase refcount when returning
     111    // found objects. This extra count accounts for the main "reference" kept by plugin process.
     112
     113    // To avoid excessive IPC, plugin process doesn't send each NPObject release/retain call to
     114    // Safari. It only sends one when the last reference is removed, and it can destroy the proxy
     115    // NPObject.
     116
     117    // However, the browser may be sending the same object out to plug-in as a function call
     118    // argument at the same time - neither side can know what the other one is doing. So,
     119    // is to make PCForgetBrowserObject call return a boolean result, making it possible for
     120    // the browser to make plugin host keep the proxy with zero refcount for a little longer.
     121
     122    uint32_t objectID = 0;
     123   
     124    HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
     125    if (iter != m_jsObjectToIDMap.end())
     126        return iter->second.first;
     127   
     128    do {
     129        objectID = ++m_objectIDCounter;
     130    } while (!m_objectIDCounter || m_objectIDCounter == static_cast<uint32_t>(-1) || m_idToJSObjectMap.contains(objectID));
     131
     132    m_idToJSObjectMap.set(objectID, object);
     133    m_jsObjectToIDMap.set(object, make_pair<uint32_t, uint32_t>(objectID, 1));
     134
     135    return objectID;
     136}
     137
     138void NetscapePluginInstanceProxy::LocalObjectMap::retain(JSC::JSObject* object)
     139{
     140    HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
     141    ASSERT(iter != m_jsObjectToIDMap.end());
     142
     143    iter->second.second = iter->second.second + 1;
     144}
     145
     146void NetscapePluginInstanceProxy::LocalObjectMap::release(JSC::JSObject* object)
     147{
     148    HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
     149    ASSERT(iter != m_jsObjectToIDMap.end());
     150
     151    ASSERT(iter->second.second > 0);
     152    iter->second.second = iter->second.second - 1;
     153    if (!iter->second.second) {
     154        m_idToJSObjectMap.remove(iter->second.first);
     155        m_jsObjectToIDMap.remove(iter);
     156    }
     157}
     158
     159void NetscapePluginInstanceProxy::LocalObjectMap::clear()
     160{
     161    m_idToJSObjectMap.clear();
     162    m_jsObjectToIDMap.clear();
     163}
     164
     165bool NetscapePluginInstanceProxy::LocalObjectMap::forget(uint32_t objectID)
     166{
     167    HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> >::iterator iter = m_idToJSObjectMap.find(objectID);
     168    ASSERT(iter != m_idToJSObjectMap.end());
     169
     170    HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator rIter = m_jsObjectToIDMap.find(iter->second.get());
     171
     172    // If the object is being sent to plug-in right now, then it's not the time to forget.
     173    if (rIter->second.second != 1)
     174        return false;
     175
     176    m_jsObjectToIDMap.remove(rIter);
     177    m_idToJSObjectMap.remove(iter);
     178    return true;
     179}
     180
    103181static uint32_t pluginIDCounter;
    104182
     
    115193    , m_useSoftwareRenderer(false)
    116194    , m_waitingForReply(false)
    117     , m_objectIDCounter(0)
    118195    , m_urlCheckCounter(0)
    119196    , m_pluginFunctionCallDepth(0)
     
    186263    // Clear the object map, this will cause any outstanding JS objects that the plug-in had a reference to
    187264    // to go away when the next garbage collection takes place.
    188     m_objects.clear();
     265    m_localObjects.clear();
    189266   
    190267    if (Frame* frame = core([m_pluginView webFrame]))
     
    684761}
    685762   
    686 uint32_t NetscapePluginInstanceProxy::idForObject(JSObject* object)
    687 {
    688     uint32_t objectID = 0;
    689    
    690     // Assign an object ID.
    691     do {
    692         objectID = ++m_objectIDCounter;
    693     } while (!m_objectIDCounter || m_objectIDCounter == static_cast<uint32_t>(-1) || m_objects.contains(objectID));
    694    
    695     m_objects.set(objectID, object);
    696    
    697     return objectID;
    698 }
    699 
    700763// NPRuntime support
    701764bool NetscapePluginInstanceProxy::getWindowNPObject(uint32_t& objectID)
     
    708771        objectID = 0;
    709772    else
    710         objectID = idForObject(frame->script()->windowShell(pluginWorld())->window());
     773        objectID = m_localObjects.idForObject(frame->script()->windowShell(pluginWorld())->window());
    711774       
    712775    return true;
     
    720783   
    721784    if (JSObject* object = frame->script()->jsObjectForPluginElement([m_pluginView element]))
    722         objectID = idForObject(object);
     785        objectID = m_localObjects.idForObject(object);
    723786    else
    724787        objectID = 0;
     
    727790}
    728791
    729 void NetscapePluginInstanceProxy::releaseObject(uint32_t objectID)
    730 {
    731     m_objects.remove(objectID);
     792bool NetscapePluginInstanceProxy::forgetBrowserObjectID(uint32_t objectID)
     793{
     794    return m_localObjects.forget(objectID);
    732795}
    733796 
     
    737800    resultLength = 0;
    738801
    739     if (!m_objects.contains(objectID))
     802    if (!m_localObjects.contains(objectID))
    740803        return false;
    741804
     
    779842        return false;
    780843   
    781     JSObject* object = m_objects.get(objectID);
     844    JSObject* object = m_localObjects.get(objectID);
    782845    if (!object)
    783846        return false;
     
    813876        return false;
    814877
    815     JSObject* object = m_objects.get(objectID);
     878    JSObject* object = m_localObjects.get(objectID);
    816879    if (!object)
    817880        return false;
     
    846909        return false;
    847910
    848     JSObject* object = m_objects.get(objectID);
     911    JSObject* object = m_localObjects.get(objectID);
    849912    if (!object)
    850913        return false;
     
    880943        return false;
    881944
    882     JSObject* object = m_objects.get(objectID);
     945    JSObject* object = m_localObjects.get(objectID);
    883946    if (!object)
    884947        return false;
     
    899962bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, unsigned propertyName, data_t& resultData, mach_msg_type_number_t& resultLength)
    900963{
    901     JSObject* object = m_objects.get(objectID);
     964    JSObject* object = m_localObjects.get(objectID);
    902965    if (!object)
    903966        return false;
     
    921984        return false;
    922985
    923     JSObject* object = m_objects.get(objectID);
     986    JSObject* object = m_localObjects.get(objectID);
    924987    if (!object)
    925988        return false;
     
    9451008        return false;
    9461009
    947     JSObject* object = m_objects.get(objectID);
     1010    JSObject* object = m_localObjects.get(objectID);
    9481011    if (!object)
    9491012        return false;
     
    9681031        return false;
    9691032
    970     JSObject* object = m_objects.get(objectID);
     1033    JSObject* object = m_localObjects.get(objectID);
    9711034    if (!object)
    9721035        return false;
     
    9931056        return false;
    9941057
    995     JSObject* object = m_objects.get(objectID);
     1058    JSObject* object = m_localObjects.get(objectID);
    9961059    if (!object)
    9971060        return false;
     
    10181081        return false;
    10191082
    1020     JSObject* object = m_objects.get(objectID);
     1083    JSObject* object = m_localObjects.get(objectID);
    10211084    if (!object)
    10221085        return false;
     
    10381101        return false;
    10391102
    1040     JSObject* object = m_objects.get(objectID);
     1103    JSObject* object = m_localObjects.get(objectID);
    10411104    if (!object)
    10421105        return false;
     
    10581121        return false;
    10591122
    1060     JSObject* object = m_objects.get(objectID);
     1123    JSObject* object = m_localObjects.get(objectID);
    10611124    if (!object)
    10621125        return false;
     
    10781141        return false;
    10791142
    1080     JSObject* object = m_objects.get(objectID);
     1143    JSObject* object = m_localObjects.get(objectID);
    10811144    if (!object)
    10821145        return false;
     
    11371200        } else {
    11381201            [array addObject:[NSNumber numberWithInt:JSObjectValueType]];
    1139             [array addObject:[NSNumber numberWithInt:idForObject(object)]];
     1202            [array addObject:[NSNumber numberWithInt:m_localObjects.idForObject(object)]];
    11401203        }
    11411204    } else
     
    11991262            uint32_t objectID = [[array objectAtIndex:index++] intValue];
    12001263           
    1201             result = m_objects.get(objectID);
     1264            result = m_localObjects.get(objectID);
    12021265            ASSERT(result);
    12031266            return true;
     
    12541317    while (demarshalValueFromArray(exec, array.get(), position, value))
    12551318        result.append(value);
     1319}
     1320
     1321void NetscapePluginInstanceProxy::retainLocalObject(JSC::JSValue value)
     1322{
     1323    if (!value.isObject())
     1324        return;
     1325
     1326    JSObject* object = asObject(value);
     1327    if (object->classInfo() == &RuntimeObjectImp::s_info)
     1328        return;
     1329
     1330    m_localObjects.retain(object);
     1331}
     1332
     1333void NetscapePluginInstanceProxy::releaseLocalObject(JSC::JSValue value)
     1334{
     1335    if (!value.isObject())
     1336        return;
     1337
     1338    JSObject* object = asObject(value);
     1339    if (object->classInfo() == &RuntimeObjectImp::s_info)
     1340        return;
     1341
     1342    m_localObjects.release(object);
    12561343}
    12571344
  • trunk/WebKit/mac/Plugins/Hosted/ProxyInstance.mm

    r54504 r54783  
    138138    if (!m_instanceProxy)
    139139        return jsUndefined();
    140    
     140
    141141    RetainPtr<NSData*> arguments(m_instanceProxy->marshalValues(exec, args));
    142142
    143143    uint32_t requestID = m_instanceProxy->nextRequestID();
    144144
     145    for (unsigned i = 0; i < args.size(); i++)
     146        m_instanceProxy->retainLocalObject(args.at(i));
     147
    145148    if (_WKPHNPObjectInvoke(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), requestID, m_objectID,
    146                             type, identifier, (char*)[arguments.get() bytes], [arguments.get() length]) != KERN_SUCCESS)
    147         return jsUndefined();
     149                            type, identifier, (char*)[arguments.get() bytes], [arguments.get() length]) != KERN_SUCCESS) {
     150        for (unsigned i = 0; i < args.size(); i++)
     151            m_instanceProxy->releaseLocalObject(args.at(i));
     152        return jsUndefined();
     153    }
    148154   
    149155    auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
    150156    NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
     157
     158    for (unsigned i = 0; i < args.size(); i++)
     159        m_instanceProxy->releaseLocalObject(args.at(i));
     160
    151161    if (!reply.get() || !reply->m_returnValue)
    152162        return jsUndefined();
     
    382392
    383393    m_instanceProxy->marshalValue(exec, value, valueData, valueLength);
     394    m_instanceProxy->retainLocalObject(value);
    384395    kern_return_t kr = _WKPHNPObjectSetProperty(m_instanceProxy->hostProxy()->port(),
    385396                                                m_instanceProxy->pluginID(), requestID,
    386397                                                m_objectID, serverIdentifier, valueData, valueLength);
    387398    mig_deallocate(reinterpret_cast<vm_address_t>(valueData), valueLength);
     399    m_instanceProxy->releaseLocalObject(value);
    388400    if (kr != KERN_SUCCESS)
    389401        return;
  • trunk/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs

    r54516 r54783  
    113113                                 out objectID :uint32_t);
    114114                     
    115 routine PCReleaseObject(clientPort :mach_port_t;
     115routine PCForgetBrowserObject(clientPort :mach_port_t;
    116116                      pluginID :uint32_t;
    117117                      objectID :uint32_t);
  • trunk/WebKitTools/ChangeLog

    r54772 r54783  
     12010-02-12  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Reviewed by Kevin Decker.
     4
     5        <rdar://problem/7130641> Browser objects identity is not preserved by Safari
     6
     7        * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp:
     8        (pluginInvoke): Added methods for checking object identity (via refcount).
     9
    1102010-02-15  Robert Hogan  <robert@roberthogan.net>
    211
  • trunk/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp

    r54516 r54783  
    177177    ID_TEST_GET_BROWSER_PROPERTY,
    178178    ID_TEST_SET_BROWSER_PROPERTY,
     179    ID_REMEMBER,
     180    ID_GET_REMEMBERED_OBJECT,
     181    ID_GET_AND_FORGET_REMEMBERED_OBJECT,
     182    ID_REF_COUNT,
    179183    NUM_METHOD_IDENTIFIERS
    180184};
     
    206210    "reloadPluginsAndPages",
    207211    "testGetBrowserProperty",
    208     "testSetBrowserProperty"
     212    "testSetBrowserProperty",
     213    "remember",
     214    "getRememberedObject",
     215    "getAndForgetRememberedObject",
     216    "refCount"
    209217};
    210218
     
    747755    return false;
    748756}
     757
     758static NPObject* rememberedObject;
    749759
    750760static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
     
    808818        browser->setproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), &args[2]);
    809819        return true;
     820    } else if (name == pluginMethodIdentifiers[ID_REMEMBER]) {
     821        if (rememberedObject)
     822            browser->releaseobject(rememberedObject);
     823        rememberedObject = NPVARIANT_TO_OBJECT(args[0]);
     824        browser->retainobject(rememberedObject);
     825        VOID_TO_NPVARIANT(*result);
     826        return true;
     827    } else if (name == pluginMethodIdentifiers[ID_GET_REMEMBERED_OBJECT]) {
     828        assert(rememberedObject);
     829        browser->retainobject(rememberedObject);
     830        OBJECT_TO_NPVARIANT(rememberedObject, *result);
     831        return true;
     832    } else if (name == pluginMethodIdentifiers[ID_GET_AND_FORGET_REMEMBERED_OBJECT]) {
     833        assert(rememberedObject);
     834        OBJECT_TO_NPVARIANT(rememberedObject, *result);
     835        rememberedObject = 0;
     836        return true;
     837    } else if (name == pluginMethodIdentifiers[ID_REF_COUNT]) {
     838        uint32_t refCount = NPVARIANT_TO_OBJECT(args[0])->referenceCount;
     839        INT32_TO_NPVARIANT(refCount, *result);
     840        return true;
    810841    }
    811842   
Note: See TracChangeset for help on using the changeset viewer.