命令处理器的执行方法通过查找“name”来决定调用哪个方法,然后做什么。第一个参数是一个“响应”对象(这么叫是因为初只是用于将响应发回给用户),它封装的不只是可能发送的值;还有一个方法,使要调度的响应返回给用户以及可以找出有关DOM的实现机制。第二个参数是上面参数对象的值(在这里是Id和name)。这个方案的优点是每个函数都有一个统一的接口,反映了在客户端上使用的结构,这意味着用来思考每一端的代码的心理模式是相似的。这是getAttribute的底层实现,在之前也看到过:
FirefoxDriver.prototype.getElementAttribute = function(respond, parameters) {
var element = Utils.getElementAt(parameters.id,
respond.session.getDocument());
var attributeName = parameters.name;
respond.value = webdriver.element.getAttribute(element, attributeName);
respond.send();
};
为了使元素引用一致,第一行是在缓存中通过不透明的ID查找被引用的元素。在Firefox driver中,那个ID是一个通用识别码,cache是一个map。这个getElementAt方法还检查元素是否已知并且附加到DOM上,如果检查失败,ID则从缓存中移除并抛异常返回给用户。
第二行之前讨论过的是利用浏览器自动化原子,这时候编译为一个单个脚本并加载为扩展的一部分。后一行调用了send方法,做了个简单的检查,确保在调用执行方法的回调前一次只发一个响应。该响应是以JSON字符串装到对象里的形式发回给用户(假设getAttribute返回7,意思是没有发现元素)。
{
'value': '7',
'status': 0,
'sessionId': 'XXX'
}
然后Java客户端检查状态的值,如果该值非零,把数字状态码转换成正确类型的异常抛出来,使用“value”字段设置发送给用户的消息,如果状态为零“value”字段的值直接返回给用户。
大部分能行的通,但是有一位聪明的读者提出个问题:在调用执行方法之前为什么调度器把对象转换成一个字符串?
这样做的原因是Firefox driver还支持纯javascript编写的测试脚本。通常情况下,这是件非常难以实现的事情:测试都是在浏览器的Javascript安全沙盒中运行,因此可能不会做一系列对测试有用的事情,如在不同域之间切换或上传文件等。但是,Webdriver的Firefox扩展提供了一个解决办法,属性添加到文档元素上以证明它的存在。Webdriver的Javascript API使用它作为一项指标,它可以添加JSON序列化的命令对象作为文档元素的命令属性的值,触发一个自定义的webdriverCommand事件,然后在被通知响应已确定的相同元素上监听webdriverResponse事件。
这表明在一个装有Webdriver扩展的firefox版本里浏览网页是一个坏点子,因为它使其他人远程控制浏览器变得更容易。
在后台有一个DOM消息器,等待webdriverCommand读取序列化的JSON对象并调用命令处理器的执行方法。这次,回调是在文档元素上设置了响应属性,然后触发预期的webdriverResponse事件。