命令處理器的執行方法通過查找“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事件。