<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>随.心.所.记 &#187; Firefox</title>
	<atom:link href="http://www.realdodo.com/tag/firefox/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.realdodo.com</link>
	<description>享受生活的乐趣与烦恼</description>
	<lastBuildDate>Fri, 25 Jun 2010 18:49:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Firefox插件（plugins）开发实用指南</title>
		<link>http://www.realdodo.com/2010/02/11/595/</link>
		<comments>http://www.realdodo.com/2010/02/11/595/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 11:21:20 +0000</pubDate>
		<dc:creator>realdodo</dc:creator>
				<category><![CDATA[技术文章]]></category>
		<category><![CDATA[FAQ]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[插件]]></category>
		<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://www.realdodo.com/?p=595</guid>
		<description><![CDATA[Firefox插件可实现强大功能，但其中麻烦事情不少。写这个实用指南首先是为了方便自己记忆，免得以后再次栽倒一些坑里面，如果能帮助其他人，则是更好。这个指南不是为了手把手教读者开发插件，而是作为一个FAQ，解决各种诡异问题。
Firefox拥有众多的扩展（Extension），开发扩展也非常容易，不过有一些事情还是无法用扩展解决，需要访问操作系统的底层功能，这就需要写插件（plugins）。例如flash就是一个插件而不是扩展。
Mozilla提供了一系列的教程和文档，虽然很不详尽，众多重要的API语焉不详，但至少是一个好的开始。
最需要阅读的是plugins API和使用入门。这是一个相当长的文档，如果看完所有的内容会花费大量的时间而且还会很晕，这里列一些重点供参考。

plugins基础概念
写第一个插件（只需要关注Writing Plug-ins这一节所谈到的内容）
获得一份firefox的源码，比如firefox 3.6。plugins的例子可以在源码里找到（modules/plugin/sdk/samples），如果出了问题还可以自己编译一个debug版的firefox来调试。
了解浏览器能提供什么功能
制作插件的安装程序，推荐用扩展的方式安装插件，有无数的好处

完成以上这些内容以后差不多就已经可以实现自己的插件了，一般而言，参照着例子来做开发不会有什么问题，只是有不少细节需要留意。
Firefox plugins开发的众多奇怪的约定（假设plugins已经被正确安装）
有些约定非常奇怪，不要问我为什么，天晓得开发firefox的牛人们怎么想的。
在Windows下，plugins必须满足以下条件才能被firefox检测到：

插件的名字必须是np*.dll，也就是必须以np开头，.dll结尾
插件dll资源的语言必须为LANG_ENGLISH，code page必须为1252。在rc文件里是这么写的：

LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)

插件dll的VERSION_INFO里面必须包含以下值：
VALUE "MIMEType", "application/x-your-mimetype"

这个MIME就是&#60;object&#62;标签引用插件的唯一凭证。

在Linux下，plugins必须满足以下条件才能被检测到：

插件的名字必须是lib*plugin.so，即以lib开头，plugin.so结尾
插件必须实现NP_GetMIMEDescription和NP_GetPluginVersion，并返回合适MIME字符串。注意，这个字符串并不是普通的MIME，是有特殊规则的，详见前面这个链接的内容。
插件so不要静态链接gtk、opensll、pthread、z等系统库，这会在不同linux平台上因为符号表的问题遇到各种运行时错误

特别需要说明的是，NP_GetPluginVersion、NP_GetEntryPoints等关键函数没有任何官方文档介绍它们，只能根据例子来猜，反正没事就别改它们的实现，copy例子中的代码就好。
firefox插件开发注意事项
写firefox插件的一个基本习惯是，经常编译代码并运行它，保证你的插件还能工作。只要firefox无法加载dll/so，或者加载出现任何错误，都会悄无声息的忽略这个插件。时常关注一下about:plugins，看看插件是不是还在这个列表里。
firefox插件从窗口模式上可分为windowless和windowed两种。其中，windowless模式的文档较多较全，是firefox比较推荐的模式，坑比较少，这里就不多说了。windowed模式则相反，需要好好说说。
无论在Windows还是Linux上，windowed的插件都拥有独立于浏览器页面的窗口。firefox会通过插件的NPP_SetWindow来告诉插件当前窗口的情况。
关于windowed插件有两个诡异问题需要注意：

Windows平台下，插件窗口默认会响应WM_CTLCOLOREDIT、WM_CTLCOLORLISTBOX、WM_CTLCOLORBTN、WM_CTLCOLORSTATIC消息，并设置一个默认的背景色。这本来没问题，但在Windows XP下，这个颜色居然永远是黑色，而不是默认系统背景色（通常是白色）。最好subclass这个窗口并且拦截这些消息，不要让firefox去处理它们。对于插件来说，firefox处理这些消息只是帮倒忙而已。至于firefox还帮了哪些倒忙，可以去源码widget/src/windows/nsWindows.cpp的nsWindow::ProcessMessage()去围观。
Linux平台下，NPP_SetWindow传入的NPWindow指针中虽然有一个ws_info成员，这个成员里面也确实有一个display变量指向X Window的Display结构，但绝对不要真正使用它，否则可能会导致firefox直接退出，据说这可能是firefox的一个bug。

测试firefox插件小技巧，测试方面的高手可以无视
测试插件前建议先在firefox里面创建一个新的profile（帐号）。这样可以创造一个最干净的开发环境，避免被其他扩展/插件干扰。
默认的profile名叫default，在命令行里输入firefox -p default就可以使用这个profile。如果只是输入firefox -p，会弹出一个对话框用于选择profile。这个命令在Windows和Linux下都可使用。
无论是哪个平台，调试插件的方法都很类似。
Windows下可以用VC以调试方式启动firefox，载入插件时调试器会自动载入对应的符号，捕捉发生的异常或者设断点都很方便。
Linux下直接用gdb就好，细节应该不用多说。有一点需要注意，系统默认安装的firefox命令（默认放在/usr/bin/firefox）是一个shell脚本，真正的可执行文件名字需要打开这个脚本自行查找。
实现firefox插件的基本功能
firefox为插件提供的接口十分原始，很多功能默认没有实现，下面提供了一些思路和方法。

让插件接受焦点：默认情况下，&#60;object&#62;标签不能获得焦点，必须指定tabindex。
在插件中使用tab键跳到下一个element：没有好办法，必须自己手动将焦点还给浏览器窗口（Linux下不必如此），然后自己用NPN_*系列函数找到应该获得focus的DOM element，然后调用这个element的focus()方法。
隐藏和显示插件：直接设置&#60;object&#62;标签的style.display = &#8220;none&#8221;即可，但这里有个严重的副作用，firefox会调用插件的NS_PluginShutdown，销毁这个插件。如果不期望造成这种效果，要么别用这种方式隐藏插件，要么把插件状态保存在js里，再次显示的时候把状态设回去。
触发DOM事件：firefox没有提供任何便利的方法触发DOM事件，要在插件中做到这点，必须自己模拟js触发DOM事件的过程。例如，对于HTML事件，假设self是DOM element，js会这么做。

evt = document.createEvent("KeyboardEvent");
evt.initKeyEvent(
"blur",      //  in DOMString typeArg,
false,       //  in boolean canBubbleArg,
false);      //  in boolean cancelableArg,
self.dispatchEvent(evt);

对应的C代码就是


void FireHTMLEvent(NPP npp, [...]]]></description>
			<content:encoded><![CDATA[<p>Firefox插件可实现强大功能，但其中麻烦事情不少。写这个实用指南首先是为了方便自己记忆，免得以后再次栽倒一些坑里面，如果能帮助其他人，则是更好。这个指南不是为了手把手教读者开发插件，而是<strong>作为一个FAQ，解决各种诡异问题</strong>。</p>
<p>Firefox拥有众多的扩展（Extension），开发扩展也非常容易，不过有一些事情还是无法用扩展解决，需要访问操作系统的底层功能，这就需要写插件（plugins）。例如flash就是一个插件而不是扩展。</p>
<p>Mozilla提供了一系列的教程和文档，虽然很不详尽，众多重要的API语焉不详，但至少是一个好的开始。</p>
<p>最需要阅读的是<a href="https://developer.mozilla.org/en/Gecko_Plugin_API_Reference">plugins API和使用入门</a>。这是一个相当长的文档，如果看完所有的内容会花费大量的时间而且还会很晕，这里列一些重点供参考。</p>
<ul>
<li><a href="https://developer.mozilla.org/en/Gecko_Plugin_API_Reference:Plug-in_Basics">plugins基础概念</a></li>
<li><a href="https://developer.mozilla.org/en/Gecko_Plugin_API_Reference:Plug-in_Development_Overview#Writing%20Plug-ins">写第一个插件</a>（只需要关注Writing Plug-ins这一节所谈到的内容）</li>
<li><a href="https://developer.mozilla.org/En/Developer_Guide/Source_Code/Mercurial#mozilla-1.9.2_%28Firefox_3.6%29">获得一份firefox的源码</a>，比如firefox 3.6。plugins的例子可以在源码里找到（modules/plugin/sdk/samples），如果出了问题还可以自己编译一个debug版的firefox来调试。</li>
<li><a href="https://developer.mozilla.org/en/Gecko_Plugin_API_Reference:Browser_Side_Plug-in_API">了解浏览器能提供什么功能</a></li>
<li>制作插件的安装程序，推荐用<a href="https://developer.mozilla.org/en/Bundles">扩展的方式安装插件</a>，有无数的好处</li>
</ul>
<p>完成以上这些内容以后差不多就已经可以实现自己的插件了，一般而言，参照着例子来做开发不会有什么问题，只是有不少细节需要留意。</p>
<p><strong>Firefox plugins开发的众多奇怪的约定（假设plugins已经被正确安装）</strong></p>
<p>有些约定非常奇怪，不要问我为什么，天晓得开发firefox的牛人们怎么想的。</p>
<p>在Windows下，plugins必须满足以下条件才能被firefox检测到：</p>
<ul>
<li>插件的名字必须是np*.dll，也就是必须以np开头，.dll结尾</li>
<li>插件dll资源的语言必须为LANG_ENGLISH，code page必须为1252。在rc文件里是这么写的：<br />
<code><br />
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US<br />
#pragma code_page(1252)<br />
</code></li>
<li>插件dll的VERSION_INFO里面必须包含以下值：<code>
<p>VALUE "MIMEType", "application/x-your-mimetype"<br />
</code><br />
这个MIME就是&lt;object&gt;标签引用插件的唯一凭证。</li>
</ul>
<p>在Linux下，plugins必须满足以下条件才能被检测到：</p>
<ul>
<li>插件的名字必须是lib*plugin.so，即以lib开头，plugin.so结尾</li>
<li>插件必须实现<a href="https://developer.mozilla.org/En/NP_GetMIMEDescription">NP_GetMIMEDescription</a>和NP_GetPluginVersion，并返回合适MIME字符串。注意，这个字符串并不是普通的MIME，是有特殊规则的，详见前面这个链接的内容。</li>
<li>插件so不要静态链接gtk、opensll、pthread、z等系统库，这会在不同linux平台上因为符号表的问题遇到各种运行时错误</li>
</ul>
<p>特别需要说明的是，NP_GetPluginVersion、NP_GetEntryPoints等关键函数没有任何官方文档介绍它们，只能根据例子来猜，反正没事就别改它们的实现，copy例子中的代码就好。</p>
<p><strong>firefox插件开发注意事项</strong></p>
<p>写firefox插件的一个基本习惯是，经常编译代码并运行它，保证你的插件还能工作。只要firefox无法加载dll/so，或者加载出现任何错误，都会悄无声息的忽略这个插件。时常关注一下<a href="about:plugins">about:plugins</a>，看看插件是不是还在这个列表里。</p>
<p>firefox插件从窗口模式上可分为<a href="https://developer.mozilla.org/en/Gecko_Plugin_API_Reference:Drawing_and_Event_Handling#Windowless_Plug-ins">windowless</a>和<a href="https://developer.mozilla.org/en/Gecko_Plugin_API_Reference:Drawing_and_Event_Handling#Windowed_Plug-ins">windowed</a>两种。其中，windowless模式的文档较多较全，是firefox比较推荐的模式，坑比较少，这里就不多说了。windowed模式则相反，需要好好说说。</p>
<p>无论在Windows还是Linux上，windowed的插件都拥有独立于浏览器页面的窗口。firefox会通过插件的<a href="https://developer.mozilla.org/en/NPP_SetWindow">NPP_SetWindow</a>来告诉插件当前窗口的情况。</p>
<p>关于windowed插件有两个诡异问题需要注意：</p>
<ul>
<li>Windows平台下，插件窗口默认会响应WM_CTLCOLOREDIT、WM_CTLCOLORLISTBOX、WM_CTLCOLORBTN、WM_CTLCOLORSTATIC消息，并设置一个默认的背景色。这本来没问题，但在Windows XP下，这个颜色居然永远是黑色，而不是默认系统背景色（通常是白色）。最好subclass这个窗口并且拦截这些消息，不要让firefox去处理它们。对于插件来说，firefox处理这些消息只是帮倒忙而已。至于firefox还帮了哪些倒忙，可以去源码widget/src/windows/nsWindows.cpp的nsWindow::ProcessMessage()去围观。</li>
<li>Linux平台下，NPP_SetWindow传入的NPWindow指针中虽然有一个ws_info成员，这个成员里面也确实有一个display变量指向X Window的Display结构，但绝对不要真正使用它，否则可能会导致firefox直接退出，<a href="http://www.mail-archive.com/xorg@lists.freedesktop.org/msg04770.html">据说</a>这可能是firefox的一个bug。</li>
</ul>
<p><strong>测试firefox插件小技巧，测试方面的高手可以无视</strong></p>
<p>测试插件前建议先在firefox里面<a href="https://developer.mozilla.org/en/Setting_up_extension_development_environment">创建一个新的profile（帐号）</a>。这样可以创造一个最干净的开发环境，避免被其他扩展/插件干扰。</p>
<p>默认的profile名叫default，在命令行里输入<code>firefox -p default</code>就可以使用这个profile。如果只是输入<code>firefox -p</code>，会弹出一个对话框用于选择profile。这个命令在Windows和Linux下都可使用。</p>
<p>无论是哪个平台，调试插件的方法都很类似。</p>
<p>Windows下可以用VC以调试方式启动firefox，载入插件时调试器会自动载入对应的符号，捕捉发生的异常或者设断点都很方便。</p>
<p>Linux下直接用gdb就好，细节应该不用多说。有一点需要注意，系统默认安装的firefox命令（默认放在/usr/bin/firefox）是一个shell脚本，真正的可执行文件名字需要打开这个脚本自行查找。</p>
<p><strong>实现firefox插件的基本功能</strong></p>
<p>firefox为插件提供的接口十分原始，很多功能默认没有实现，下面提供了一些思路和方法。</p>
<ul>
<li>让插件接受焦点：默认情况下，&lt;object&gt;标签不能获得焦点，必须指定tabindex。</li>
<li>在插件中使用tab键跳到下一个element：没有好办法，必须自己手动将焦点还给浏览器窗口（Linux下不必如此），然后自己用NPN_*系列函数找到应该获得focus的DOM element，然后调用这个element的focus()方法。</li>
<li>隐藏和显示插件：直接设置&lt;object&gt;标签的style.display = &#8220;none&#8221;即可，但这里有个严重的副作用，firefox会调用插件的NS_PluginShutdown，销毁这个插件。如果不期望造成这种效果，要么别用这种方式隐藏插件，要么把插件状态保存在js里，再次显示的时候把状态设回去。</li>
<li>触发DOM事件：firefox没有提供任何便利的方法触发DOM事件，要在插件中做到这点，必须自己模拟js触发DOM事件的过程。例如，对于HTML事件，假设self是DOM element，js会这么做。<br />
<code><br />
evt = document.createEvent("KeyboardEvent");<br />
evt.initKeyEvent(<br />
"blur",      //  in DOMString typeArg,<br />
false,       //  in boolean canBubbleArg,<br />
false);      //  in boolean cancelableArg,<br />
self.dispatchEvent(evt);<br />
</code><br />
对应的C代码就是</li>
</ul>
<pre name="code" class="cpp">
void FireHTMLEvent(NPP npp, const string &#038; name)
{
    NPVariant result;
    NPObject *window;
    NPVariant vDoc;

    NPN_GetValue(npp, NPNVWindowNPObject, &#038;window);

    // 也许页面已经跳转了……
    if (!window) {
        return;
    }

    NPIdentifier sDocument = NPN_GetStringIdentifier("document");
    NPN_GetProperty(npp, window, sDocument, &#038;vDoc);
    NPN_ReleaseObject(window);

    // evt = document.createEvent("KeyboardEvent");
    NPVariant evt;
    NPObject* npDoc = NPVARIANT_TO_OBJECT(vDoc);
    NPIdentifier createEvent = NPN_GetStringIdentifier("createEvent");
    NPVariant eventArgs[1];
    STRINGZ_TO_NPVARIANT("HTMLEvents", eventArgs[0]);
    NPN_Invoke(npp, npDoc, createEvent, eventArgs, 1, &#038;evt);
    NPN_ReleaseObject(npDoc);

    // evt.initKeyEvent(
    //    "blur",      //  in DOMString typeArg,
    //    false,            //  in boolean canBubbleArg,
    //    false);            //  in boolean cancelableArg,
    NPObject * npEvt = NPVARIANT_TO_OBJECT(evt);
    NPIdentifier initKeyEvent = NPN_GetStringIdentifier("initEvent");
    NPVariant initArgs[3];
    STRINGZ_TO_NPVARIANT(name.c_str(), initArgs[0]);
    BOOLEAN_TO_NPVARIANT(false, initArgs[1]);
    BOOLEAN_TO_NPVARIANT(false, initArgs[2]);
    NPN_Invoke(npp, npEvt, initKeyEvent, initArgs, 3, &#038;result);
    NPN_ReleaseVariantValue(&#038;result);

    // this.dispatchEvent(evt);
    NPObject * self;
    NPN_GetValue(npp, NPNVPluginElementNPObject, &#038;self);
    NPIdentifier dispatchEvent = NPN_GetStringIdentifier("dispatchEvent");
    NPVariant dispatchArgs[1];
    dispatchArgs[0] = evt;
    NPN_Invoke(npp, self, dispatchEvent, dispatchArgs, 1, &#038;result);
    NPN_ReleaseVariantValue(&#038;result);
    NPN_ReleaseObject(npEvt);

    NPN_ReleaseObject(self);
}
</pre>
<p>暂时先写到这里，如果还有什么疑难杂症，欢迎评论，我继续添加。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.realdodo.com/2010/02/11/595/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IE的未来在何方</title>
		<link>http://www.realdodo.com/2009/03/07/262/</link>
		<comments>http://www.realdodo.com/2009/03/07/262/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 08:56:03 +0000</pubDate>
		<dc:creator>realdodo</dc:creator>
				<category><![CDATA[技术文章]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[浏览器]]></category>

		<guid isPermaLink="false">http://www.realdodo.com/?p=262</guid>
		<description><![CDATA[IE8即将发布已经不是新闻，很多评论家以及那些讨厌IE的开发者们都对这个亲近标准的IE抱有一丝好感，这也不是新闻。
IE8中最显著的改变莫过于对CSS 2.1的全面支持。正因为现在亲近标准而以前疏离标准，IE8引入了兼容模式这种复杂的新功能，来兼容以前那些不标准的网页。在外界看来，IE8这么痛苦的在标准支持和兼容性方面抉择，简直就是搬起石头砸自己的脚——早知现在，何必当初呢。
我曾经问过负责CSS 2.1标准支持的IE PM，为什么现在才开始做标准支持而以前不做，为什么不做DOM而选择CSS。他对此也感觉有心无力，毕竟无论是支持什么新标准，对IE来说都是一次大手术。IE是在标准产生之前确定的架构，现在能做到如此强大的功能还能支持那么多标准已经很不容易。就比如说对CSS 2.1的支持，IE重写了很多核心代码，花了大量的时间去保证正确性、性能和兼容性，已经有点精力不够。相比而言，还是开发WebSlice和 Accelerator更加省心省力。
现在的IE已经很有点像当年的NetScape。有谁能想到，当IE 5全面打败NetScape时，IE是世界上最标准的浏览器，它全面支持HTML 4和CSS 1，而且它还十分的小巧，比NetScape小一个数量级。IE的胜利绝对不仅仅因为它与Windows绑定，而是因为它实在比NetScape好太多了。NetScape当年拖着沉重的历史包袱，每一个升级都不敢做太大的变动，生怕那些使用了自己独有特性的网站出问题，至于标准，当然是抛在脑后。这何其像现在的IE。
时过境迁，多年之后，Firefox从当年NetScape的残骸之中诞生，Firefox成了当年的IE，IE成了当年的NetScape。当 Firefox一身轻松快速开发新版本的时候，IE还要考虑兼容IE6这样古董的浏览器。当Firefox毫无忌惮的通过自动更新强制用户更新浏览器版本的时候，IE还要修IE6的bug、还要发布IT工具方便众多公司阻止IE升级版本。唉，开发IE真累啊。
有很多人希望有朝一日Firefox能打败IE，解放现在身处“水深火热”之中的Web前端开发者。可是我觉得，这绝对不是未来的趋势，Firefox或者说Mozilla基金会绝不愿意这么做。浏览器世界的盟主不是那么好当的，站在风口浪尖，不但赚不到钱，还要花力气赔名声，得不偿失。
就拿修浏览器漏洞这件事情来说，Vista下的IE7已经做得非常安全，比Firefox好上无数倍，基本上对缓冲区溢出和DEP免疫了，可是大家还是会觉得Firefox更安全，根本原因是舆论导向。IE造好了一座坚固的城池，如果依然能将它攻破，对于攻击者来说，自然很有成就感。同时，新闻也总关注 IE的安全，毕竟它一出问题，全世界大部分电脑都处于危险之中，这绝对是大新闻。一来二去，IE不安全的口碑也就建立。至于Firefox究竟有多安全，那还真不见得。用XPCOM做的Firefox插件真的比ActiveX安全？还真不见得。从技术上来讲，做Firefox版的流氓插件不存在任何技术问题。
从我和IE PM聊天中得到的信息，IE现在最关注的领域是企业级应用和RIA。这两方面，恰好是Firefox最弱的地方。而在这个领域，IE真正的对手是 Google Chrome，所以下一个版本的IE会针对Google Chrome的特性采取很多动作。也许还要再经历3个版本，IE才能够脱胎换骨，不过那时，其他竞争者早不知道发展到什么程度了。对IE来说，是时候考虑学习一下Firefox，来个凤凰涅磐了。我猜，五年之后必有大变，我会拭目以待。
]]></description>
			<content:encoded><![CDATA[<p>IE8即将发布已经不是新闻，很多评论家以及那些讨厌IE的开发者们都对这个亲近标准的IE抱有一丝好感，这也不是新闻。</p>
<p>IE8中最显著的改变莫过于对CSS 2.1的全面支持。正因为现在亲近标准而以前疏离标准，IE8引入了兼容模式这种复杂的新功能，来兼容以前那些不标准的网页。在外界看来，IE8这么痛苦的在标准支持和兼容性方面抉择，简直就是搬起石头砸自己的脚——早知现在，何必当初呢。</p>
<p>我曾经问过负责CSS 2.1标准支持的IE PM，为什么现在才开始做标准支持而以前不做，为什么不做DOM而选择CSS。他对此也感觉有心无力，毕竟无论是支持什么新标准，对IE来说都是一次大手术。IE是在标准产生之前确定的架构，现在能做到如此强大的功能还能支持那么多标准已经很不容易。就比如说对CSS 2.1的支持，IE重写了很多核心代码，花了大量的时间去保证正确性、性能和兼容性，已经有点精力不够。相比而言，还是开发WebSlice和 Accelerator更加省心省力。</p>
<p>现在的IE已经很有点像当年的NetScape。有谁能想到，当IE 5全面打败NetScape时，IE是世界上最标准的浏览器，它全面支持HTML 4和CSS 1，而且它还十分的小巧，比NetScape小一个数量级。IE的胜利绝对不仅仅因为它与Windows绑定，而是因为它实在比NetScape好太多了。NetScape当年拖着沉重的历史包袱，每一个升级都不敢做太大的变动，生怕那些使用了自己独有特性的网站出问题，至于标准，当然是抛在脑后。这何其像现在的IE。</p>
<p>时过境迁，多年之后，Firefox从当年NetScape的残骸之中诞生，Firefox成了当年的IE，IE成了当年的NetScape。当 Firefox一身轻松快速开发新版本的时候，IE还要考虑兼容IE6这样古董的浏览器。当Firefox毫无忌惮的通过自动更新强制用户更新浏览器版本的时候，IE还要修IE6的bug、还要发布IT工具方便众多公司阻止IE升级版本。唉，开发IE真累啊。</p>
<p>有很多人希望有朝一日Firefox能打败IE，解放现在身处“水深火热”之中的Web前端开发者。可是我觉得，这绝对不是未来的趋势，Firefox或者说Mozilla基金会绝不愿意这么做。浏览器世界的盟主不是那么好当的，站在风口浪尖，不但赚不到钱，还要花力气赔名声，得不偿失。</p>
<p>就拿修浏览器漏洞这件事情来说，Vista下的IE7已经做得非常安全，比Firefox好上无数倍，基本上对缓冲区溢出和DEP免疫了，可是大家还是会觉得Firefox更安全，根本原因是舆论导向。IE造好了一座坚固的城池，如果依然能将它攻破，对于攻击者来说，自然很有成就感。同时，新闻也总关注 IE的安全，毕竟它一出问题，全世界大部分电脑都处于危险之中，这绝对是大新闻。一来二去，IE不安全的口碑也就建立。至于Firefox究竟有多安全，那还真不见得。用XPCOM做的Firefox插件真的比ActiveX安全？还真不见得。从技术上来讲，做Firefox版的流氓插件不存在任何技术问题。</p>
<p>从我和IE PM聊天中得到的信息，IE现在最关注的领域是企业级应用和RIA。这两方面，恰好是Firefox最弱的地方。而在这个领域，IE真正的对手是 Google Chrome，所以下一个版本的IE会针对Google Chrome的特性采取很多动作。也许还要再经历3个版本，IE才能够脱胎换骨，不过那时，其他竞争者早不知道发展到什么程度了。对IE来说，是时候考虑学习一下Firefox，来个凤凰涅磐了。我猜，五年之后必有大变，我会拭目以待。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.realdodo.com/2009/03/07/262/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
	</channel>
</rss>
