2013年12月29日日曜日

Mac版 Qt 5.2のWebViewはPlugin機能が無効になっていた件

未だに年賀状が倒せていない隠者です。年の瀬も近づいて来ていますが、皆様進捗どうですか?

さて、先週の土曜日に、Qt勉強会 #6 @Tokyoに参加して来ました。Qt 5.2も出たことなので、艦メモをビルドしようとがんばったのですが、なぜかFlashがインストールされていません扱いでした。Mac Book Proではソースからビルドしていたのですが、MBAでは横着して5.2の正式版はパッケージから入れており、Beta版のソースコードも削除した直後で、ビルドのできないSrc(インストーラからinstallできるけど、configureなどは入っていない)はあるものの、デバッグまではできませんでした。

一応、勉強会では時間いっぱい粘って、WebKitのおおよそのソースコード構成は把握してまして、年末休みに突入してから、こちらでもない、あっちでもないとあれこれ彷徨いましたが、何の事はないそもそもPluginが有効になってない事がわかりました。

WebKitは、様々なアーキテクチャや下回り用に、コードの一部をMakefileで切り替えて使うように構成されています。今回問題になったのは、PluginPackageの下回りの切り替え部分でした。

通常、Mac版では

qtwebkit/Source/WebCore/plugins/mac/PluginPackageMac.cpp

が使われるべき所が、

qtwebkit/Source/WebCore/plugins/PluginPackageNone.cpp

のコードが使われていました。このコードは、プラグイン未使用環境用で処理の実装はなく、失敗を返すように実装されています。これでビルドされている限り、Pluginは利用できなくなります。


qtwebkit/Source/WebCore/Target.pri を読むと


 enable?(NETSCAPE_PLUGIN_API) {
    SOURCES += plugins/npapi.cpp
    unix {
        mac {
            SOURCES += \
                plugins/mac/PluginPackageMac.cpp
            OBJECTIVE_SOURCES += \
                platform/text/mac/StringImplMac.mm \
                platform/mac/WebCoreNSStringExtras.mm \
                plugins/mac/PluginViewMac.mm
        } else {
            SOURCES += \
                plugins/qt/PluginPackageQt.cpp \
                plugins/qt/PluginViewQt.cpp
        }
    }
      :
 } else {
     SOURCES += \
         plugins/PluginPackageNone.cpp \
         plugins/PluginViewNone.cpp
 }


となっています。つまり、NETSCAPE_PLUGIN_APIが有効になっていないわけです。
ごそごそっと検索かけると、この辺の定義は以下で行われていました。
qtwebkit/Tools/qmake/mkspecs/features/features.prf


    # Nescape plugins support (NPAPI)
    xlibAvailable() {
        WEBKIT_CONFIG += \
            netscape_plugin_api \
            use_plugin_backend_xlib
        # WebKit2
        WEBKIT_CONFIG += \
            plugin_architecture_x11 \
            plugin_process
    } else: unix|win32-*:!embedded:!wince* {
        WEBKIT_CONFIG += netscape_plugin_api
        # WebKit2
        WEBKIT_CONFIG += plugin_architecture_unsupported
    } else {
        WEBKIT_CONFIG += plugin_architecture_unsupported
    }

Macの場合、xlib扱いにはなっておらず、その次のunix:!embedded:!wince* に引っかかるはずなのですが、ここに入らずにelseに入っていました。

!embedded {
    message("!!!!! embedded? !!!!")
}

というのを追加してビルドするとメッセージが出力されるじゃないですか。どうやら、誰かがembeddedを立てているようです。そのせいで、netscape_plugin_apiがWEBKIT_CONFIGに追加されない状態でビルドされていました。

本来はembeddedを落とすのが正しい対処なのですが、誰が立ててるのか見当たらないというか、grepすると多く出過ぎるので、とりあえず暫定的に以下を追加しました。

} else : mac {
    WEBKIT_CONFIG += netscape_plugin_api
    WEBKIT_CONFIG += plugin_architecture_unsupported
}

そうすると今度は、Source/WebCore/platform/qt/FileSystemQt.cpp がビルドエラーじゃないですか・・・・なんと言う嫌がらせ。

調べてみたら、原因はこれでした。

  • Q_WS_MAC is no longer defined in Qt 5.
そう、no longer definedとされていた、Q_WS_MACが定義されなくなってます。

でも、ソースコードでは、未だに数カ所使われていました。そのうち以下の場所でエラーに成ってくれました。エラーでなかったら気がつかないだろう、それ。



 bool unloadModule(PlatformModule module)
 {
 #if defined(Q_WS_MAC)
     CFRelease(module);
     return true;
 #elif defined(Q_OS_WIN)
     return ::FreeLibrary(module);
 #else

 #ifndef QT_NO_LIBRARY
     if (module->unload()) {
         delete module;
         return true;
     }
 #endif
     return false;
 #endif
 }


というわけで、複数ある、Q_WS_MACをQ_OS_MACに置き換える必要がありました。
変更箇所は多いので、diffで上げておきます。


diff --git a/Source/WebCore/page/qt/EventHandlerQt.cpp b/Source/WebCore/page/qt/EventHandlerQt.cpp
index f45f81d..885fcde 100644
--- a/Source/WebCore/page/qt/EventHandlerQt.cpp
+++ b/Source/WebCore/page/qt/EventHandlerQt.cpp
@@ -52,7 +52,7 @@
 namespace WebCore {
-#if defined(Q_WS_MAC)
+#if defined(Q_OS_MAC)
 const double EventHandler::TextDragDelay = 0.15;
 #else
 const double EventHandler::TextDragDelay = 0.0;

diff --git a/Source/WebCore/platform/FileSystem.h b/Source/WebCore/platform/FileSystem.h
index e1d5b7e..b5fcfa6 100644
--- a/Source/WebCore/platform/FileSystem.h
+++ b/Source/WebCore/platform/FileSystem.h
@@ -48,7 +48,7 @@
 #endif
 #endif
-#if USE(CF) || (PLATFORM(QT) && defined(Q_WS_MAC))
+#if USE(CF) || (PLATFORM(QT) && defined(Q_OS_MAC))
 typedef struct __CFBundle* CFBundleRef;
 typedef const struct __CFData* CFDataRef;
 #endif
@@ -80,7 +80,7 @@ typedef GModule* PlatformModule;
 #elif PLATFORM(EFL)
 typedef Eina_Module* PlatformModule;
 #elif PLATFORM(QT)
-#if defined(Q_WS_MAC)
+#if defined(Q_OS_MAC)
 typedef CFBundleRef PlatformModule;
 #elif !defined(QT_NO_LIBRARY)
 typedef QLibrary* PlatformModule;

diff --git a/Source/WebCore/platform/qt/FileSystemQt.cpp b/Source/WebCore/platform/qt/FileSystemQt.cpp
index b5d0096..1cd8e2c 100644
--- a/Source/WebCore/platform/qt/FileSystemQt.cpp
+++ b/Source/WebCore/platform/qt/FileSystemQt.cpp
@@ -242,7 +242,7 @@ int writeToFile(PlatformFileHandle handle, const char* data, int length)
 bool unloadModule(PlatformModule module)
 {
-#if defined(Q_WS_MAC)
+#if defined(Q_OS_MAC)
     CFRelease(module);
     return true;

diff --git a/Source/WebCore/platform/qt/RenderThemeQStyle.cpp b/Source/WebCore/platform/qt/RenderThemeQStyle.cpp
index f85a75b..81f9278 100644
--- a/Source/WebCore/platform/qt/RenderThemeQStyle.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQStyle.cpp
@@ -117,7 +117,7 @@ RenderThemeQStyle::RenderThemeQStyle(Page* page)
 {
     int buttonPixelSize = 0;
     m_qStyle->getButtonMetrics(&m_buttonFontFamily, &buttonPixelSize);
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     m_buttonFontPixelSize = buttonPixelSize;
 #endif
 }
@@ -228,7 +228,7 @@ void RenderThemeQStyle::adjustButtonStyle(StyleResolver* styleResolver, RenderSt
     // Ditch the border.
     style->resetBorder();
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     if (style->appearance() == PushButtonPart) {
         // The Mac ports ignore the specified height for <input type="button"> elements
         // unless a border and/or background CSS property is also specified.
@@ -239,7 +239,7 @@ void RenderThemeQStyle::adjustButtonStyle(StyleResolver* styleResolver, RenderSt
     FontDescription fontDescription = style->fontDescription();
     fontDescription.setIsAbsoluteSize(true);
-#ifdef Q_WS_MAC // Use fixed font size and family on Mac (like Safari does)
+#ifdef Q_OS_MAC // Use fixed font size and family on Mac (like Safari does)
     fontDescription.setSpecifiedSize(m_buttonFontPixelSize);
     fontDescription.setComputedSize(m_buttonFontPixelSize);
 #else

まぁ、これでも実はビルドエラーが残っていまして、PluginPackageMac.cppで、他にもエラーが出ました。どうやら、WTF::RetainPtrが一部変更になっているようですが、ヘッダを帰ると影響が読めないので、PluginPackageMac.cppの方を一部修正しました。



diff --git a/Source/WebCore/plugins/mac/PluginPackageMac.cpp b/Source/WebCore/plugins/mac/PluginPackageMac.cpp
index 6b6c417..b40f0d4 100644
--- a/Source/WebCore/plugins/mac/PluginPackageMac.cpp
+++ b/Source/WebCore/plugins/mac/PluginPackageMac.cpp
@@ -138,7 +138,7 @@ bool PluginPackage::fetchInfo()
     if (mimeTypesFileName && CFGetTypeID(mimeTypesFileName.get()) == CFStringGetTypeID()) {
         WTF::RetainPtr<CFStringRef> fileName = (CFStringRef)mimeTypesFileName.get();
-        WTF::RetainPtr<CFStringRef> homeDir = adoptCF(homeDirectoryPath().createCFString());
+        WTF::RetainPtr<CFStringRef> homeDir = homeDirectoryPath().createCFString();
         WTF::RetainPtr<CFStringRef> path = adoptCF(CFStringCreateWithFormat(0, 0, CFSTR("%@/Library/Preferences/%@"), homeDir.get(), fileName.get()));
         WTF::RetainPtr<CFDictionaryRef> plist = readPListFile(path.get(), /*createFile*/ false, m_module);
@@ -255,7 +255,7 @@ bool PluginPackage::load()
         return true;
     }
-    WTF::RetainPtr<CFStringRef> path = adoptCF(m_path.createCFString());
+    WTF::RetainPtr<CFStringRef> path = m_path.createCFString();
     WTF::RetainPtr<CFURLRef> url = adoptCF(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(),
                                                                         kCFURLPOSIXPathStyle, false));


これ、自動テストにプラグインの登録、PluginViewの利用が入っていないのでしょうねぇ。
入っていれば、さすがにこんな大きなデグレード、しかもビルドも通されていない等というお粗末な状態をRelease版として出さないのでしょうけど・・・。

一応、このQt5.2でビルドした艦メモさんは無事に起動して、利用できました。



まぁ、timerでこけるという変な現象は出ましたが、とりあえずはゲームできて、画像付きでつぶやけたから、良しとしましょう。あとは、誰がembeddedを立ててるか調べないとなぁ・・・というあたりで、今日はここまでで、ゲームに戻ってろ号任務をクリアしてきます。