開啓宏定義
Android的代碼中本身已經對WML做了一定的支持了,但是默認情況下並沒有開啓,這些支持都在一個ENABLE_WML的宏定義中括起來了,可以grep下源代碼看下有很多ENABLE(WML)括起來的代碼。
代碼中需要的宏
這個ENABLE的宏定義我查的在Source/JavaScriptCore/wtf/Platform.h中被定義的,不知道爲什麼在這個目錄下。#defineENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE && ENABLE_##WTF_FEATURE)
由以上ENABLE(WML)對應的宏定義就是ENABLE_WML。
注意這裏的##是C語言宏的連接符,即把ENABLE_與WTF_FEATURE(傳入的是WML)的內容連接起來,這樣就連接成了ENABLE_WML。
這樣#if ENABLE(WML) 會被預處理成 #if (defined ENABLE_WML && ENABLE_WML)
由此可見,我們首先要做的就是開啓這個ENABLE_WML宏定義。
編譯環境中變量定義
在external/webkit/Android.mk中加入下面代碼開啓宏的設置,我們需要讓他的值爲true,這裏的含義是,如果ENABLE_WML環境值沒有被定義過,則我們定義它爲true。
ifeq ($(ENABLE_WML), )
ENABLE_WML := true
endif
在編譯腳本中定義代碼中的宏
但是經過上述的內容,只是定義了編譯環境裏的變量,代碼中的宏定義還沒有被定義的,那麼需要主動來設置下宏定義了,通過下面的方式
ifeq ($(ENABLE_WML), true)
LOCAL_CFLAGS += -DENABLE_WML=1
endif
這裏的-D編譯選項是用來定義代碼中的宏的,即設置c/c++中的DENABLE_WML宏的值爲1。就相當於代碼中的#define ENABLE_WML 1
通過上述兩步,c/c++的宏被成功的定義了。
另外說下Source/JavaScriptCore/wtf/Platform.h這裏有很多#defineENABLE_XXX的宏,這裏可以修改一些宏的值來修改配置。
總結下上述的過程。有一個編譯的環境變量叫ENABLE_WML,(你也可以命名爲其他的名字),在判斷這個環境變量如果沒有被定義的話,那麼在該腳本中定義它的值爲true。
然後在腳本的後面,判斷該環境變量值是否爲true,如果爲true那麼就在編譯配置LOCAL_CFLAGS中加入c/c++中的宏定義DENABLE_WML=1,(這裏的宏定義命名必須是DENABLE_WML了。)
經過以上的配置,然後編譯發現會有錯誤的。編譯不過。
頭文件的包含
剛纔編譯不過的原因是很多頭文件和源文件並沒有被編譯,那麼find下wml的文件在哪裏。可以發現他們在./Source/WebCore/wml這個目錄下,在./Source/WebCore/下還有html的目錄,那麼這裏我們就模仿下html在Android.mk中的包含的方式。
在Android.mk中加入如下:
ifeq ($(ENABLE_WML), true)
LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
$(WEBCORE_PATH)/wml
endif
ifeq ($(ENABLE_WML), true)
LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
$(WEBCORE_INTERMEDIATES_PATH)/wml
endif
這裏看下$(WEBCORE_PATH),這個路徑就是external/webkit/Source/WebCore
而$(WEBCORE_INTERMEDIATES_PATH)則對應out/target/product/XXX/obj/STATIC_LIBRARIES/libwebcore_intermediates/Source/WebCore
源文件的包含
經過以上的加入還不夠,以上只是加入了頭文件。看下./Source/WebCore,發現這裏還有個Android.mk。看看該文件發現裏面有對源文件的包含,那麼繼續模仿html的方式加入wml的支持吧。
ifeq ($(ENABLE_WML), true)
LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
wml/WMLAccessElement.cpp \
.......(這裏把wml目錄下所有的源文件都寫上)
wml/WMLVariables.cpp
endif
添加wml的style sheets
在./Source/WebCore/css/下有XXX.css文件,這些貌似定義了不少的css,對css我也不怎麼懂,但是看下是有html.css的。
另外需要看一個重要的文件,./Source/WebCore/DerivedSource.mk中有如下的語句
ifeq ($(findstring ENABLE_WML,$(FEATURE_DEFINES)),ENABLE_WML)
USER_AGENT_STYLE_SHEETS := $(USER_AGENT_STYLE_SHEETS)$(WebCore)/css/wml.css
endif
即它告訴我們如果我們需要使能WML那麼需要添加對這個的支持,這個就是用於環境變量USER_AGENT_STYLE_SHEETS上。
而在./Source/WebCore/Android.derived.mk中有對html.css的包含。那麼繼續效仿添加對wml.css的支持。
ifeq ($(ENABLE_WML), true)
style_sheets := $(style_sheets)$(LOCAL_PATH)/css/wml.css
endif
添加生成WMLName.cpp(.h)和WMLElementFactory.cpp(.h)的支持
經過以上的包含後執行編譯發現還是編譯不過。提示沒有WMLNames.h這個文件。
查看網上的內容,發現WMLName.h這個並不是源碼本身提供的,在./Source/WebCore/wml/下有WMLTagName.in和WMLAttributeNames.in。但是並沒有WMLNames.h和WMLNames.cpp,這兩個文件時生成的並且生成在out/target/product/XXX/obj/STATIC_LIBRARIES/libwebcore_intermediates/Source/WebCore/wml下
再看下./Source/WebCore/DerivedSource.mk文件,這裏還有對這兩個的描述並且也有對WMLNames的描述。
# --------
# WML tag and attribute names, and elementfactory
ifeq ($(findstringENABLE_WML,$(FEATURE_DEFINES)), ENABLE_WML)
WMLElementFactory.cpp WMLNames.cpp :dom/make_names.pl wml/WMLTagNames.in wml/WMLAttributeNames.in
perl -I $(WebCore)/bindings/scripts $< --tags$(WebCore)/wml/WMLTagNames.in --attrs $(WebCore)/wml/WMLAttributeNames.in--factory --wrapperFactory
else
WMLElementFactory.cpp :
echo > $@
WMLNames.cpp :
echo > $@
endif
# --------
不清楚這段描述是什麼意思,但是可以看到WMLNames.cpp和WMLElementFactory.cpp應該是生成出來的,並且會利用到wml/WMLTagNames.in wml/WMLAttributeNames.in。另外在./Source/WebCore/CodeGenerators.pri中也有一些對WMLNames的描述可以做參考。
參照網上對這塊的支持方法,是在./Source/WebCore/Android.derived.mk中添加如下:
參考XMLNames.cpp的生成方式,生成wml對應的WMLNames.cpp .h等
ifeq ($(ENABLE_WML), true)
GEN:= $(intermediates)/WMLNames.cpp $(intermediates)/WMLNames.h$(intermediates)/WMLElementFactory.cpp $(intermediates)/WMLElementFactory.h
$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
$(GEN): PRIVATE_CUSTOM_TOOL = perl -I $(PRIVATE_PATH)/bindings/scripts $<--tags $(wml_tag) --attrs $(wml_attrs) --factory --wrapperFactory --output$(dir $@)
$(GEN): wml_tag := $(LOCAL_PATH)/wml/WMLTagNames.in
$(GEN): wml_attrs := $(LOCAL_PATH)/wml/WMLAttributeNames.in
$(GEN): $(LOCAL_PATH)/dom/make_names.pl $(wml_tag) $(wml_attrs)
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
endif
對WML的MimeType的支持
獲取到服務器返回的數據中的content-type字段值後,會調用DOMImplementation::isXMLMIMEType(constString& mimeType)方法來判斷是否按照XML格式來解析。
Wml頁面的MimeType是”text/vnd.wap.wml”,在這個函數裏並沒有對這個MimeType進行判斷,那麼我們需要加上
#ifENABLE(WML)
if (mimeType =="text/vnd.wap.wml")
return true;
#endif
經過以上的這些操作,終於可以編譯通過並且可以打開一個wml的頁面了,但是android上對wml的支持並不完善還有不少的bug需要解,這裏就不討論了。