Bug 45145

Summary: [Qt] V8 port for QT platform: v8 binding changes
Product: WebKit Reporter: Vlad <vladbph>
Component: New BugsAssignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: antonm, christian.webkit, hausmann, japhet, webkit.review.bot
Priority: P3    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Bug Depends on:    
Bug Blocks: 45136    
Attachments:
Description Flags
v8 binding changes
none
v8 binding changes
hausmann: review-
Moved most of scriptcontroller changes to PlatformBridge: pluginScriptableObject(), pluginScriptableObjectInstance(), popupsAllowed()
none
Included plugins changes b/c of dependency abarth: review-

Description Vlad 2010-09-02 16:03:01 PDT
V8 binding changes for QT
Comment 1 Vlad 2010-09-02 17:25:47 PDT
Created attachment 66437 [details]
v8 binding changes
Comment 2 Vlad 2010-09-02 17:29:53 PDT
Created attachment 66438 [details]
v8 binding changes
Comment 3 Simon Hausmann 2010-09-02 23:38:32 PDT
Comment on attachment 66438 [details]
v8 binding changes

View in context: https://bugs.webkit.org/attachment.cgi?id=66438&action=prettypatch

> WebCore/bindings/v8/npruntime_internal.h:30
> -#include "npapi.h"
> +#if PLATFORM(QT)
> +#include <bridge/npapi.h>
> +#endif
Why is this PLATFORM(QT) guard added here? (the ChangeLog doesn't explain)

Won't the missing inclusion break the Chromium build?

> WebCore/bindings/v8/NPV8Object.cpp:254
> +#if PLATFORM(QT)
> +    bool popupsAllowed = false;
> +#else
It looks like this is at least missing a FIXME.

Then again, maybe it's not too difficult to fix. What about this?

PluginView* view = pluginViewForInstance(npp);
bool popupsAllowed = view ? view->arePopupsAllowed() : false;

> WebCore/bindings/v8/ScriptCachedFrameData.h:54
> +#elif PLATFORM(ANDROID) || PLATFORM(QT)
Any explanation why this is needed for the Qt port but not for Chromium for example? (I'm just curious :)

> WebCore/bindings/v8/V8Binding.cpp:75
> +#if !PLATFORM(QT)
>          : m_plainString(string)
>          , m_atomicString(string)
> +#endif
>      {
>  #ifndef NDEBUG
>          m_threadId = WTF::currentThread();
>  #endif
> +#if PLATFORM(QT)
> +        m_plainString = string;
> +        m_atomicString = string;
> +#endif
Why is the initialization done different for the Qt port?

Or is this not actually Qt specific but specific to rvct?

> WebCore/config.h:190
> +#if PLATFORM(QT)
> +#include <bridge/npruntime_internal.h>
> +#endif
What compile errors did you encounter?

I'm going to say r- because I think some of the #ifdefs are not correct (such as the string init one) and there's a little bit of context missing for some of the changes.

In general it looks good though.
Comment 4 Vlad 2010-09-03 11:39:13 PDT
(In reply to comment #3)
> (From update of attachment 66438 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=66438&action=prettypatch
This should be fixed by changing inclusion order. At the time of the port it was a problem.
> 
> > WebCore/bindings/v8/npruntime_internal.h:30
> > -#include "npapi.h"
> > +#if PLATFORM(QT)
> > +#include <bridge/npapi.h>
> > +#endif
> Why is this PLATFORM(QT) guard added here? (the ChangeLog doesn't explain)
> 
OK
> Won't the missing inclusion break the Chromium build?
> 
> > WebCore/bindings/v8/NPV8Object.cpp:254
> > +#if PLATFORM(QT)
> > +    bool popupsAllowed = false;
> > +#else
> It looks like this is at least missing a FIXME.
> 
> Then again, maybe it's not too difficult to fix. What about this?
> 
> PluginView* view = pluginViewForInstance(npp);
> bool popupsAllowed = view ? view->arePopupsAllowed() : false;

Comment from Chromium says: // We don't use WebKit's page caching, so this implementation is just a stub.
I chose to use caching :)
> 
> > WebCore/bindings/v8/ScriptCachedFrameData.h:54
> > +#elif PLATFORM(ANDROID) || PLATFORM(QT)
> Any explanation why this is needed for the Qt port but not for Chromium for example? (I'm just curious :)

Original code crashes at runtime. Most likely wrong constructor is called. This is again may be related to CString.h inclusion. Will check it if #ifdef can be removed now.
> 
> > WebCore/bindings/v8/V8Binding.cpp:75
> > +#if !PLATFORM(QT)
> >          : m_plainString(string)
> >          , m_atomicString(string)
> > +#endif
> >      {
> >  #ifndef NDEBUG
> >          m_threadId = WTF::currentThread();
> >  #endif
> > +#if PLATFORM(QT)
> > +        m_plainString = string;
> > +        m_atomicString = string;
> > +#endif
> Why is the initialization done different for the Qt port?
> 
> Or is this not actually Qt specific but specific to rvct?

Compilation errors appear on maemo. Will double check this.
> 
> > WebCore/config.h:190
> > +#if PLATFORM(QT)
> > +#include <bridge/npruntime_internal.h>
> > +#endif
> What compile errors did you encounter?
> 
> I'm going to say r- because I think some of the #ifdefs are not correct (such as the string init one) and there's a little bit of context missing for some of the changes.
> 
> In general it looks good though.
Comment 5 Vlad 2010-09-03 12:20:53 PDT
Just checked removing #if !PLATFORM(QT). It has to be 
    explicit WebCoreStringResource(const AtomicString& string)
        : m_plainString(reinterpret_cast<const WTF::String &>(string))
        , m_atomicString(reinterpret_cast<const WTF::String &>(string))
to specify which to use
"WTF::String::String(const QString &) or
"WTF::String::String(const WTF::String &)
Comment 6 Nate Chapin 2010-09-03 16:11:14 PDT
Comment on attachment 66438 [details]
v8 binding changes


> +#if PLATFORM(QT)
> +    if (widget->isPluginView()) {
> +        PluginView* pluginView = static_cast<PluginView*>(widget);
> +        // Create script inscance (v8 object)
> +        PassScriptInstance instance = pluginView->bindingInstance();
> +        if (!instance)
> +            return 0;
> +        // Get npobject
> +        NPObject* npObject = static_cast<NPObject*>(instance->instance()->GetPointerFromInternalField(v8DOMWrapperObjectIndex));

I'm confused by this. It looks like you're accessing an NPObject that is stored on a PassScriptInstance and creating a new PassScriptInstance for it? Why wouldn't we just want the original PassScriptInstance?

I think I'm probably missing some subtlety :)

> +        // Track the plugin object. We've been given a reference to the object.
> +        m_pluginObjects.set(widget, npObject);
> +        return instance;
> +    }
>  
> +    QWidget* platformWidget = widget->platformWidget();
> +    if (!platformWidget)
> +        return 0;
> +
> +    Frame* activeFrame = V8Proxy::retrieveFrameForEnteredContext();
> +    if (!activeFrame)
> +        return 0;
> +
> +    V8Proxy* activeProxy = activeFrame->script()->proxy();
> +    v8::HandleScope handleScope;
> +    v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(activeFrame);
> +    if (v8Context.IsEmpty())
> +        return 0;
> +
> +    v8::Context::Scope scope(v8Context);
> +    v8::Handle<v8::Object> result = 
> +        V8::Bindings::QtInstance::getQtInstance(platformWidget, v8Context, "", QScriptEngine::QtOwnership)->getV8Object();
> +    return V8ScriptInstance::create(result);
> +

Would it be possible to put the QT-specific code in a WebCore/platform/qt/PlatformBridge.h and make use of the PlatformBridge::pluginScriptableObject() call that Android and Chromium use?
Comment 7 Vlad 2010-09-03 16:30:52 PDT
I'm trying as we speak :) Complication is that QT has QT plugins.
if (widget->isPluginView())() is for qt plugins and pluginView->bindingInstance() returns v8 object already and then returns:)
Comment 8 Vlad 2010-09-03 16:40:11 PDT
I'm trying to make it look like this

PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widget)
{
...
#if PLATFORM(QT)
    // Create v8 object for QT plugins first
    PassScriptInstance instance = PlatformBridge::pluginScriptableObjectInstance(widget);
    if (instance)
        return instance;
#endif
    if (widget->isFrameView())
        return 0;
    NPObject* npObject = PlatformBridge::pluginScriptableObject(widget);
    if (!npObject)
        return 0;
...
Comment 9 Vlad 2010-09-03 17:03:40 PDT
Confusing part for me is that JSC implementation does:
_NPN_ReleaseObject() in PassScriptInstance PluginView::bindingInstance() after npobject retrieved from PluginView. 
V8 implementation in 
PassScriptInstance ScriptController::createScriptInstanceForWidget() 
doesnt do that... Does this mean that Chromium PlatformBridge::pluginScriptableObject(widget) already has ref counter decreased for this npobject?
Comment 10 Vlad 2010-09-03 17:27:05 PDT
Created attachment 66571 [details]
Moved most of scriptcontroller changes to PlatformBridge: pluginScriptableObject(), pluginScriptableObjectInstance(), popupsAllowed()
Comment 11 WebKit Review Bot 2010-09-03 17:29:07 PDT
Attachment 66571 [details] did not pass style-queue:

Failed to run "['WebKitTools/Scripts/check-webkit-style']" exit_code: 1
WebCore/platform/qt/platformBridge.cpp:23:  Found other header before a header this file implements. Should be: config.h, primary header, blank line, and then alphabetically sorted.  [build/include_order] [4]
WebCore/platform/qt/platformBridge.cpp:25:  Alphabetical sorting problem.  [build/include_order] [4]
WebCore/platform/qt/PlatformBridge.h:31:  Alphabetical sorting problem.  [build/include_order] [4]
WebCore/platform/qt/PlatformBridge.h:77:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
WebCore/platform/qt/PlatformBridge.h:78:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 5 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 12 Vlad 2010-09-03 18:01:50 PDT
Created attachment 66574 [details]
Included plugins changes b/c of dependency
Comment 13 Adam Barth 2010-09-05 23:28:49 PDT
Comment on attachment 66574 [details]
Included plugins changes b/c of dependency 

View in context: https://bugs.webkit.org/attachment.cgi?id=66574&action=prettypatch

> WebCore/bindings/v8/ScriptController.cpp:74
> +#if PLATFORM(QT)
> +PassRefPtr<DOMWrapperWorld> ScriptController::createWorld()
> +{
> +    return DOMWrapperWorld::create();
> +}
> +#endif
This can't be right.  It's not Qt-specific.  We need to integrate V8 with DOMWrapperWorld in genera.

> WebCore/bindings/v8/V8Binding.cpp:54
> -        : m_plainString(string)
> +        : m_plainString(reinterpret_cast<const WTF::String &>(string))
I don't understand this code.  Does Qt use different string types than other ports?  reinterpret_cast is almost always wrong.

> WebCore/plugins/win/PluginViewWin.cpp:661
> +#if USE(JSC)
>      JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
> +#endif
This ifdefs point to a missing abstraction.  Perhaps a ScriptLock object?
Comment 14 anton muhin 2010-09-07 08:50:45 PDT
(In reply to comment #9)
> Confusing part for me is that JSC implementation does:
> _NPN_ReleaseObject() in PassScriptInstance PluginView::bindingInstance() after npobject retrieved from PluginView. 
> V8 implementation in 
> PassScriptInstance ScriptController::createScriptInstanceForWidget() 
> doesnt do that... Does this mean that Chromium PlatformBridge::pluginScriptableObject(widget) already has ref counter decreased for this npobject?

I cannot say for JSC, but V8 bindings introduce a weak reference to a wrapper which owns the NPObject and would deref NPObject when it gets unreachable via V8.
Comment 15 anton muhin 2010-09-07 08:51:01 PDT
(In reply to comment #14)
> (In reply to comment #9)
> > Confusing part for me is that JSC implementation does:
> > _NPN_ReleaseObject() in PassScriptInstance PluginView::bindingInstance() after npobject retrieved from PluginView. 
> > V8 implementation in 
> > PassScriptInstance ScriptController::createScriptInstanceForWidget() 
> > doesnt do that... Does this mean that Chromium PlatformBridge::pluginScriptableObject(widget) already has ref counter decreased for this npobject?
> 
> I cannot say for JSC, but V8 bindings introduce a weak reference to a wrapper which owns the NPObject and would deref NPObject when it gets unreachable via V8.

Forgotten URL: http://www.google.com/codesearch/p?hl=en#OAMlx_jo-ck/src/third_party/WebKit/WebCore/bindings/v8/V8NPObject.cpp&q=createV8ObjectForNPObject&sa=N&cd=1&ct=rc
Comment 16 anton muhin 2010-09-07 08:54:58 PDT
Comment on attachment 66574 [details]
Included plugins changes b/c of dependency 

View in context: https://bugs.webkit.org/attachment.cgi?id=66574&action=prettypatch

> WebCore/platform/qt/PlatformBridge.cpp:67
> +        V8::Bindings::QtInstance::getQtInstance(platformWidget, v8Context, "", QScriptEngine::QtOwnership)->getV8Object();
can returned result by empty (on some failure path?)  Or V8ScriptInstance will take care of this?
Comment 17 Vlad 2010-09-17 12:43:51 PDT
(In reply to comment #13)
> (From update of attachment 66574 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=66574&action=prettypatch
> 
> > WebCore/bindings/v8/ScriptController.cpp:74
> > +#if PLATFORM(QT)
> > +PassRefPtr<DOMWrapperWorld> ScriptController::createWorld()
> > +{
> > +    return DOMWrapperWorld::create();
> > +}
> > +#endif
> This can't be right.  It's not Qt-specific.  We need to integrate V8 with DOMWrapperWorld in genera.
It is not Qt specific code and ifdef should be removed. I was trying to isolate Qt+v8 related changes.

> 
> > WebCore/bindings/v8/V8Binding.cpp:54
> > -        : m_plainString(string)
> > +        : m_plainString(reinterpret_cast<const WTF::String &>(string))
> I don't understand this code.  Does Qt use different string types than other ports?  reinterpret_cast is almost always wrong.

As I said earlier without explicit cast compiler gives an error b/c of confusion b/n
"WTF::String::String(const QString &) or
"WTF::String::String(const WTF::String &)

> 
> > WebCore/plugins/win/PluginViewWin.cpp:661
> > +#if USE(JSC)
> >      JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
> > +#endif
> This ifdefs point to a missing abstraction.  Perhaps a ScriptLock object?
Comment 18 Simon Hausmann 2010-09-20 02:48:10 PDT
(In reply to comment #17)
> > > WebCore/bindings/v8/V8Binding.cpp:54
> > > -        : m_plainString(string)
> > > +        : m_plainString(reinterpret_cast<const WTF::String &>(string))
> > I don't understand this code.  Does Qt use different string types than other ports?  reinterpret_cast is almost always wrong.
> 
> As I said earlier without explicit cast compiler gives an error b/c of confusion b/n
> "WTF::String::String(const QString &) or
> "WTF::String::String(const WTF::String &)

We have solved this one differently now:

http://trac.webkit.org/changeset/67326
Comment 19 Simon Hausmann 2010-09-20 02:48:45 PDT
These changes are not needed anymore, after Andreas and I separated them in the trunk.