瀏覽器腳本開發(fā)的難與易

這兩天统抬,寫了一個(gè)簡單的基于有道在線翻譯的GreaseMonkey屏幕取詞腳本。

點(diǎn)我查看GreaseFork

youdaodict-1.gif

我想做這件事很久了危队,從我還不是一個(gè)前端開發(fā)者的時(shí)候聪建,就一直想做這么一個(gè)輕量的瀏覽器腳本,方便自己查看英文的文檔和文章茫陆。沒想到想了這么久金麸,真正沒做多久。

作為一個(gè)Ubuntu Linux用戶簿盅,瀏覽器取詞我有幾個(gè)選擇:

  1. 嘗試安裝有道詞典Linux版本挥下、openyoudao或者其他stardict或者goldendict這種本地詞典揍魂。但我并不覺得我需要桌面軟件。

  2. 有人做了個(gè)Google translate tooltip的GreaseMonkey腳本實(shí)現(xiàn)這個(gè)棚瘟,非常棒。但谷歌的服務(wù)在國內(nèi)的服務(wù)非常不穩(wěn)定解取,取詞功能經(jīng)常不能正常使用。

  3. 有道提供了網(wǎng)頁翻譯2.0返顺,通過書簽執(zhí)行一段代碼把取詞功能注入當(dāng)前頁面。然而慧邮,首先隨著瀏覽器安全特性的加強(qiáng),該書簽不能正常使用倡缠,其次每次都要先點(diǎn)書簽才能取詞(也許是快捷鍵)载荔。

選擇是難

很多網(wǎng)站,包括cnblog發(fā)現(xiàn)都提供了取詞版本定庵。我面臨的選擇是:

  1. 在這些已有的瀏覽器取詞腳本基礎(chǔ)上學(xué)習(xí)修改蓝仲。
  2. 憑借著自己的感覺從新設(shè)計(jì)

選擇上花了很多時(shí)間而晒。

方案一的優(yōu)點(diǎn)有:

  1. 成熟美觀诈胜。
  2. 能學(xué)習(xí)到很多東西

方案一問題在于:

  1. 源碼難理解摔笤。代碼量較大够滑,都是壓縮甚至混淆變量過的。
  2. 有些和當(dāng)前頁面的樣式或者腳本攪和在一起吕世。不易分離
  3. 被瀏覽器或網(wǎng)站安全設(shè)置廢掉彰触,未必能使用

終于,由于我的智商被有道在線翻譯那個(gè)腳本所碾壓命辖,我想還是看看功能自己設(shè)計(jì)下况毅,做個(gè)簡單版本分蓖。

想的很簡單

設(shè)計(jì)是易

想法很簡單。

  1. 鼠標(biāo)選詞
  2. 向第三方發(fā)起請求尔许,比如bing的翻譯或者有道的
  3. 讀取返回么鹤,彈出tooltip,格式化數(shù)據(jù)
  4. 其他輔助功能比如發(fā)音味廊、單詞本等等

設(shè)計(jì)是最簡單的一環(huán)蒸甜,后面你會看到時(shí)間都花到哪里了。

知易行難

通過谷歌余佛,很容易完成第一步迅皇,在腳本中得到選中的文字。

第二步就開始面臨問題衙熔。作為前信息安全專業(yè)從業(yè)者,很清楚ajax這種東西跨域是受限制的搅荞。稍微翻閱scriptish文檔發(fā)現(xiàn)GM_xmlhttpRequest可以滿足我的需求红氯。

除卻和 XMLHttpRequest這種東西并不太一樣的api造成的各種細(xì)節(jié)錯(cuò)誤,之后碰到的問題是我整個(gè)開發(fā)過程最棘手咕痛、花費(fèi)時(shí)間最長的問題痢甘。

無論onload、onerror還是onreadystate的回調(diào)中茉贡,GM_log都沒有打印出任何信息塞栅。

firebug和火狐內(nèi)置調(diào)試器也沒有顯示任何通信。這和我在網(wǎng)絡(luò)上看到的GreaseMonkey相關(guān)信息并不太相符腔丧。

經(jīng)檢查腳本元數(shù)據(jù)@grant放椰,覺得已經(jīng)授權(quán)這個(gè)跨域函數(shù)也沒什么問題。

折騰一陣愉粤,確認(rèn)API調(diào)用和細(xì)節(jié)都無法確認(rèn)問題后砾医,采取曲線調(diào)試方案。

更改請求地址到本地衣厘,確認(rèn)請求確實(shí)發(fā)出了如蚜。那么,它有返回嗎影暴?

在本地用netcat模擬返回?cái)?shù)據(jù)错邦,仍然沒有打印任何信息。我開始懷疑難道GM_xmlhttpRequest是會對返回結(jié)果做驗(yàn)證型宙?必須報(bào)頭正確撬呢?

第一天就這么過去了。

第二天我決定嘗試代理來看來往的通信是否正常妆兑。

方便起見倾芝,先用nc充當(dāng)了下代理讨勤,檢查了下相互通信,未見有什么不對的晨另。

為嚴(yán)謹(jǐn)起見潭千,用burpsuite來設(shè)置一個(gè)透明本地代理,讓瀏覽器指向那個(gè)代理借尿。經(jīng)過檢驗(yàn)刨晴,完全沒看出通信有什么問題。但onload和其他回調(diào)也不會被觸發(fā)路翻。

谷歌搜索得到一些stackoverflow狈癞、github issue和greasewiki上的信息,但問題仍不能確認(rèn)和解決茂契。

只是昨天晚上baidu時(shí)心心念念蝶桶,發(fā)現(xiàn)firefox貼吧里有人吐槽scriptish不穩(wěn)定的一些地方,今天又看到一些討論掉冶,決定換回GreaseMonkey試試真竖,事實(shí)證明這是明智的。

然而厌小,一換發(fā)現(xiàn)什么都打印不出來了恢共。后來反復(fù)嘗試,發(fā)現(xiàn)GM_log不能用璧亚,我簡直震驚了讨韭,wiki上寫著玩的么,還是有什么變化癣蟋。反正我發(fā)現(xiàn)console.log可以使用透硝,那就繼續(xù)開發(fā)下去了。

最難的部分就這么糊里糊涂過去了疯搅。

數(shù)據(jù)請求順風(fēng)順?biāo)?/h2>

一旦請求完成蹬铺,解析json數(shù)據(jù),按需展示就是水到渠成的事情秉撇。

然而甜攀,并不是那么簡單。

JS異步與回調(diào)之難

JS的異步特性帶來了這些不符合人類直觀思維方式的流程控制風(fēng)格琐馆。

按理說我應(yīng)該很習(xí)慣javascript的異步操作流程控制的種種問題规阀,但還是踩了次坑。

彈出和渲染tooltip的函數(shù)沒有讀到返回?cái)?shù)據(jù)瘦麸!

好在對javascript程序員debug這種問題比之前的問題簡單太多谁撼。一看想起來GM_xmlhttpRequest是異步過程,而不是同步,我這里卻要待異步過程返回結(jié)果再執(zhí)行下一個(gè)函數(shù)厉碟。

想想promise應(yīng)該不用喊巍,雖然firefox41肯定原生支持ES6 promise了。但箍鼓,就這點(diǎn)函數(shù)干脆崭参。。款咖。還是回調(diào)“地獄”吧何暮。

JS難中有易

說到ES6,ES6提供了很多方便javascript編程的好東西铐殃,通過let=>實(shí)現(xiàn)更好的this和作用域一致海洼,通過Template方便字符串操作等等。

很慶幸富腊,GreaseMonkey的話我只考慮firefox用戶坏逢,反正好早的時(shí)候這些ES6特性瀏覽器都支持了。

JS易中又難

JS讓人非常難過的一個(gè)地方赘被,是DOM操作和各種webAPI是整。只能說喪心病狂。你記得清楚如何獲得viewport區(qū)域大小么帘腹?知道如何獲得鼠標(biāo)相對viewport位置么?知道為啥獲取區(qū)域高度或?qū)挾炔]有獲得么许饿?看到clientWidth阳欲、offsetWidth、availWidth...有沒有想砍人陋率?

為了讓腳本能正確在屏幕邊緣讓tooltip出現(xiàn)在viewport內(nèi)球化,在各種邊界條件數(shù)學(xué)計(jì)算題這里又糾結(jié)了好久。

GreaseMonkey相比Scriptish少了一個(gè)比較方便的特性: @css瓦糟。雖然可以在head標(biāo)簽中通過GM_addStyle()來注入樣式筒愚,我總覺得會不合時(shí)宜的覆蓋不該覆蓋的東西,我對Google Translate Tooltip在阮一峰大大的網(wǎng)站上奇葩的樣式表現(xiàn)印象深刻菩浙。所以巢掺,還是選擇在DOM中注入的樣式。

這是體力活劲蜻,你說體力活難不難呢陆淀?

最難的部分

安全是最難以面對的一個(gè)問題。之所以先嬉,很多標(biāo)簽轧苫、腳本在頁面上失效,都是由于近年來瀏覽器越來越嚴(yán)格的安全策略疫蔓。我在開發(fā)這個(gè)腳本時(shí)碰到了兩點(diǎn):

  1. 在https網(wǎng)站頁面中無法加載http的資源含懊。在調(diào)試工具中可以看到mixed content的字樣身冬。
  2. 如果網(wǎng)站報(bào)頭中有CSP限制。調(diào)試工具中也能看到提示岔乔。

問題一酥筝,可以通過GM_xmlhttpRequest方法實(shí)現(xiàn)混合協(xié)議內(nèi)容,如果外部資源也支持https請求也行重罪。當(dāng)我開發(fā)發(fā)音功能時(shí)就發(fā)現(xiàn)有道的語音api可以用https訪問樱哼。

問題二,只能通過各種CORS技術(shù)實(shí)現(xiàn)(參見附錄)剿配。我還沒開始做搅幅。但看到Stackoverflow上有個(gè)示例

你確定要通過打開about:config禁用firefox對CSP的支持嗎?

不:襞摺茄唐!

通過GM_xmlhttpRequest完成異步請求,將數(shù)據(jù)用瀏覽器播放出來實(shí)現(xiàn)跨域資源引用蝇更。這樣沪编,在一定程度上并不降低瀏覽器安全性,卻能夠?qū)崿F(xiàn)需求年扩,完成功能蚁廓。

Cheers!

附錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厨幻,一起剝皮案震驚了整個(gè)濱河市相嵌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌况脆,老刑警劉巖饭宾,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異格了,居然都是意外死亡看铆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門盛末,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弹惦,“玉大人,你說我怎么就攤上這事悄但》羝担” “怎么了算墨?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵宵荒,是天一觀的道長。 經(jīng)常有香客問我,道長报咳,這世上最難降的妖魔是什么侠讯? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮暑刃,結(jié)果婚禮上厢漩,老公的妹妹穿的比我還像新娘。我一直安慰自己岩臣,他們只是感情好溜嗜,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著架谎,像睡著了一般炸宵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谷扣,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天土全,我揣著相機(jī)與錄音,去河邊找鬼会涎。 笑死裹匙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的末秃。 我是一名探鬼主播概页,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼练慕!你這毒婦竟也來了惰匙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤贺待,失蹤者是張志新(化名)和其女友劉穎徽曲,沒想到半個(gè)月后零截,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體麸塞,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年涧衙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哪工。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弧哎,死狀恐怖雁比,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撤嫩,我是刑警寧澤偎捎,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響茴她,放射性物質(zhì)發(fā)生泄漏寻拂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一丈牢、第九天 我趴在偏房一處隱蔽的房頂上張望祭钉。 院中可真熱鬧,春花似錦己沛、人聲如沸慌核。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垮卓。三九已至,卻和暖如春晶姊,著一層夾襖步出監(jiān)牢的瞬間扒接,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工们衙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钾怔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓蒙挑,卻偏偏與公主長得像宗侦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子忆蚀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容