`
mmdev
  • 浏览: 12920620 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

修改浏览器使之支持WML格式页面

 
阅读更多
对于移动终端,有时候服务器返回的是WML格式的页面。 比如说中国移动的一些需要使用cmwap接入点的业务页面(DCD, 移动梦网…), 这就要求终端浏览器必须能够支持对WML格式页面的解析和显示。 Android原始代码里的webkit层虽然提供了WML相关的解析类,但是并没有很好地支持,所以在页面上无法正确显示。 我们需要做以下一些修改:
1. 打开对WML格式解析的通道
修改源码的\external\webkit\WebCore\dom\DOMImplementation.cpp
获取到服务器返回的数据中的content-type字段值后,会调用这个类里面的isXMLMIMEType()方法来判断是否按照XML格式来解析。我们看这个方法:
1
2
3
4
5
6
7
bool DOMImplementation::isXMLMIMEType(const String& mimeType) {
if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl")
return true;
static const char* const validChars = "[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]"; // per RFCs: 3023, 2045
DEFINE_STATIC_LOCAL(RegularExpression, xmlTypeRegExp, (String("^") + validChars + "+/" + validChars + "+\\+xml$", TextCaseSensitive));
return xmlTypeRegExp.match(mimeType) > -1;
}

这里只包含了text/xml, application/xml, text/xls. 我们需要把WML相应的MiMeType类型加进去
1
If(mimeType == “text/vnd.wap.wml”) return true;

修改framework/base/core/java/android/webkit/LoadListener.java, 源码如下:
1
2
3
4
5
6
7
8
9
// Does the header parsing work on the WebCore thread.
private void handleHeaders(Headers headers) {
}
else if (mMimeType.equals("text/vnd.wap.wml")) {
// As we don't support wml, render it as plain text
mMimeType = "text/plain";
}

我们可以看到, 原来是不支持wml格式的, 都当做text/plain来处理了,这样显然是不能正确显示的。 所以这一行mMimeType = "text/plain";需要注释掉,打开给外围。

2. 对WML中的超链接元素(WMLAElement和WMLAnchorElement)中href属性值里面的变量替换。
笔者发现,在一个WML的登陆页面上,填入用户名和密码后,点击登陆,附加到url后面的用户名和密码是$(username) 和$(password) ,有web开发经验的XDJM都知道,这是没有将变量替换为页面上相应值。我们看WMLAElement.cpp中处理点击事件的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void WMLAElement::defaultEventHandler(Event* event) {
if (isLink() && (event->type() == eventNames().clickEvent || (event->type() == eventNames().keydownEvent && focused()))) {
MouseEvent* e = 0;
if (event->type() == eventNames().clickEvent && event->isMouseEvent())
e = static_cast<MouseEvent*>(event);
KeyboardEvent* k = 0;
if (event->type() == eventNames().keydownEvent && event->isKeyboardEvent())
k = static_cast<KeyboardEvent*>(event);
if (e && e->button() == RightButton) {
WMLElement::defaultEventHandler(event);
return;
}
if (k) {
if (k->keyIdentifier() != "Enter") {
WMLElement::defaultEventHandler(event);
return;
}
event->setDefaultHandled();
dispatchSimulatedClick(event);
return;
}
if (!event->defaultPrevented() && document()->frame()) {
String url = document()->completeURL(deprecatedParseURL(getAttribute(HTMLNames::hrefAttr)));
/
document()->frame()->loader()->urlSelected(url, target(), event, false, false, true, SendReferrer);
}
event->setDefaultHandled();
}
}

通过打印Log发现,getAttribute(HTMLNames::hrefAttr)获取的只是href后面的字符串,包含变量$(). 我们需要对其中的变量进行转化。还好WMLVariables里面已经提供了相应的方法substituteVariableReferences,不需要我们再去写一个了。修改如下
#include "WMLVariables.h"
1
2
3
4
5
6
if (!event->defaultPrevented() && document()->frame()) {
// Substitute variables within target url attribute value. String href = getAttribute(HTMLNames::hrefAttr);
href = substituteVariableReferences(href, document(), WMLVariableEscapingEscape);
String url = document()->completeURL(deprecatedParseURL(href));
document()->frame()->loader()->urlSelected(url, target(), event, false, false, true, SendReferrer);
}

别忘了,WMLAnchorElement.cpp中相应的地方也要同样改掉。

3. 在页面上长按链接时弹出选项点击失效
这是由于点击时是从webkit层去获取这个链接的地址和标题的, 而源码中只考虑了HTML格式的页面, WML页面被忽略了。 返回的href为null.
首先要在WMLAElement.cpp中提供接口, 返回链接。
1
2
3
4
5
6
KURL WMLAElement::href() const {
// Substitute variables within target url attribute value.
String href = substituteVariableReferences(getAttribute(HTMLNames::hrefAttr),
document(), WMLVariableEscapingEscape);
return document()->completeURL(href);
}

由于WMLAnchorElement继承了WMLAElement, 就不需要再添加这个方法了。
然后修改WebViewCore.cpp, 原来获取href的方法是这样的:
1
2
3
4
WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node) {
WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
return anchor ? anchor->href() : WebCore::String();
}

在这里增加WML的支持, 修改如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**add WML anchor support. 20110224, begin**/
#if ENABLE(WML)
WebCore::WMLAnchorElement* WebViewCore::retrieveWMLAElement(WebCore::Frame* frame, WebCore::Node* node) {
if (!CacheBuilder::validNode(m_mainFrame, frame, node))
return 0;
if (!node->hasTagName(WebCore::WMLNames::aTag))
return 0;
return static_cast<WebCore::WMLAnchorElement*>(node);
}
#endif
/**add WML anchor support 20110224, end**/
WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node) {
/**retrieve WMLAnchor element. 20110224, begin**/
#if ENABLE(WML)
if (node->isWMLElement()) {
WebCore::WMLAnchorElement* anchor = retrieveWMLAElement(frame, node);
return anchor ? anchor->href() : WebCore::String();
}
#endif
/**retrieve WMLAnchor element. 20110224, end**/
WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
return anchor ? anchor->href() : WebCore::String();
}

还有获取链接标题的方法,修改如下:
1
2
3
4
5
6
7
8
9
10
11
12
WebCore::String WebViewCore::retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node) {
/**retrieve WMLAnchor element. 20110224, begin**/
#if ENABLE(WML)
if (node->isWMLElement()) {
WebCore::WMLAnchorElement* anchor = retrieveWMLAElement(frame, node);
return anchor ? anchor->title() : WebCore::String();
}
#endif
/**retrieve WMLAnchor element. 20110224, end**/
WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
return anchor ? anchor->text() : WebCore::String();
}

4. 移动梦网无法正确显示,解析出错。
移动梦网返回的数据格式为application/vnd.wap.xhtml+xml, 包含了xhtml和xml两种格式。而CMCC的数据本身又不是严格按照W3C标准来的, 导致在解析的时候出现了语法错误提示。 对于这种情况,我们显然无法去要求CMCC改变数据, 只能把这种格式当做普通的html来显示, html没有那么严格的语法检查, 可以正常显示。修改framework/base/core/java/android/webkit/LoadListener.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Does the header parsing work on the WebCore thread.
private void handleHeaders(Headers headers) {
。。。
String contentType = headers.getContentType();
if (contentType != null) {
parseContentTypeHeader(contentType);
// If we have one of "generic" MIME types, try to deduce
// the right MIME type from the file extension (if any):
if (mMimeType.equals("text/plain") ||
mMimeType.equals("application/octet-stream")) {
// for attachment, use the filename in the Content-Disposition
// to guess the mimetype
String contentDisposition = headers.getContentDisposition();
String url = null;
if (contentDisposition != null) {
url = URLUtil.parseContentDisposition(contentDisposition);
}
if (url == null) {
url = mUrl;
}
String newMimeType = guessMimeTypeFromExtension(url);
if (newMimeType != null) {
mMimeType = newMimeType;
}
} else if (mMimeType.equals("text/vnd.wap.wml")) {
// As we don't support wml, render it as plain text
// mMimeType = "text/plain";
} else {
// It seems that xhtml+xml and vnd.wap.xhtml+xml mime
// subtypes are used interchangeably. So treat them the same.
//if (mMimeType.equals("application/vnd.wap.xhtml+xml")) {
// mMimeType = "application/xhtml+xml";
//}
/* Webkit used libxml2 as the xml parser, but the CMCC's WAP sites
written in WML or XHTML do not meet W3C's specification well,
and libxml2 will throw a lot of grammatical errors when it parses
the document which has the mime type is "application/xhtml+xml" or
"application/vnd.wap.xhtml+xml". When i opened the macro named
"XHTMLMP" in config.h in webcore and tested, i found some bugs,
i believed that Google did not do detail test works for this macro.
So i could handle "XHTML" mime type as "HTML" only in order to
open CMCC's WAP sites in browser.
*/
if (mMimeType.equals("application/vnd.wap.xhtml+xml") ||
mMimeType.equals("application/xhtml+xml")) {
mMimeType = "text/html";
}
}
}
}


分享到:
评论

相关推荐

    C-Blog V2.0

    支持wml1.1标准 支持手机wap浏览和通过手机发表日志 .支持trackback引用发送和接收 网站间互通更方便 .采用smarty模版引擎,程序与模版分离,方便修改,用户可自定义界面 .采用目前相对最安全的数据库防下载技术 ...

    3G 手机建站系统 最强大的手机建站系统 手机B2C移动购物,智能软件下载功能模块,高级论坛

    三、 3G版另外的一个特点是 实现PC普通浏览器也可以登录手机网站(即平台通用性),不仅打破电脑无需安装任何特殊浏览器(例如 OPERA等手机网站常用浏览器)即可及时访问手机网站,并且实现了PC与手机内容同步,通过...

    3G 手机建站系统 最强大的手机建站系统智能软件下载功能模块,高级论坛

    三、 3G版另外的一个特点是 实现PC普通浏览器也可以登录手机网站(即平台通用性),不仅打破电脑无需安装任何特殊浏览器(例如 OPERA等手机网站常用浏览器)即可及时访问手机网站,并且实现了PC与手机内容同步,通过...

    动易内容管理系统WAP2.0适配程序

    QuickWAP的开发集成了微软的ASP、VB、ActiveX、Windows2003(2007)、IIS6.0(5.0)、Access、MSSQL2000(2005)、SQL和WAP的WML、XHTML MP语言,以及ASPJPEG、JMail组件、CSS语言等技术于一体,其中以微软的各种技术为核心...

    动易SiteWeaver内容管理系统WAP2.0适配程序 V1.0.rar

    QuickWAP的开发集成了微软的ASP、VB、ActiveX、Windows2003(2007)、IIS6.0(5.0)、Access、MSSQL2000(2005)、SQL和WAP的WML、XHTML MP语言,以及ASPJPEG、JMail组件、CSS语言等技术于一体,其中以微软的各种技术为核心...

    酷睿股票私募网站管理系统 V2010 SP2

    继续ASP开源之路,稳定、安全、强大的核心程序,对于有网站设计知识和程序爱好者可以随心所欲进行修改,方便建立具有自已特色的站点。  酷睿股票私募网站管理系统,最大的优势不仅在于有全国首创的WAP手机访问系统...

    柯林net9.0最新破解版

    --[优先级2]移动网关提供有UA情况下,有些浏览器不支持wap1.0/2.0,只支持电脑访问如苹果的Safari浏览器,有以下UA关键字进入电脑版--&gt; |iPhone" /&gt; &lt;!--[优先级3]移动网关提供有UA情况下,当网站进入不同版本...

    XML高级编程pdf

    7.7.1 MSXML对命名空间和模式的支持 7.7.2 数据类型 7.8 图书目录中的变化 7.8.1 为什么烦恼 7.8.2 重铸DTD 7.8.3 模式协调 7.9 小结 第8章 链接和查询 8.1 XML 信息集合 8.1.1 信息类型 8.1.2 信息集合的...

    XML高级编程 (Extensible Markup Language)

    7.7.1 MSXML对命名空间和模式的支持 7.7.2 数据类型 7.8 图书目录中的变化 7.8.1 为什么烦恼 7.8.2 重铸DTD 7.8.3 模式协调 7.9 小结 第8章 链接和查询 8.1 XML 信息集合 8.1.1 信息类型 8.1.2 信息集合的...

    XML 高级编程(高清版)

    7.7.1 MSXML对命名空间和模式的支持 7.7.2 数据类型 7.8 图书目录中的变化 7.8.1 为什么烦恼 7.8.2 重铸DTD 7.8.3 模式协调 7.9 小结 第8章 链接和查询 8.1 XML 信息集合 8.1.1 信息类型 8.1.2 信息集合的...

    XML高级编程

    7.7.1 MSXML对命名空间和模式的支持 228 7.7.2 数据类型 229 7.8 图书目录中的变化 230 7.8.1 为什么烦恼 230 7.8.2 重铸DTD 231 7.8.3 模式协调 236 7.9 小结 240 第8章 链接和查询 241 8.1 XML 信息集合 241 8.1.1...

    asp.net技术内幕(1)

    &lt;br&gt;7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...

    asp.net技术内幕(2)

    &lt;br&gt;7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...

    asp.net技术内幕(5)

    &lt;br&gt;7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...

    asp.net技术内幕(4)

    &lt;br&gt;7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...

    asp.net技术内幕(3)

    &lt;br&gt;7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...

    ASP.net技术内幕

    behind文件派生多个页面 6.3.4 编译完整的ASP.NET页面 6.4 小结 &lt;br/&gt;第7章 用可移动控件为可移动设备服务 &lt;br/&gt;7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 ...

Global site tag (gtag.js) - Google Analytics