2011-12-12 79 views
0

在我的Greasemonkey腳本中,我想重寫一個仍然存在於網頁中的函數。如何在沒有「unsafeWindow」的情況下編程?

所以我用這個JavaScript代碼:

var oldDoWork = DoWork; 

unsafeWindow.DoWork = function() 
{ 
    // Do some new work 
    ... 

    oldDoWork(); // Call the old function 
} 

它的工作原理。

但有兩個問題與方法:

  1. unsafeWindow的特點是安全性問題,從Greasemonkey的說。
  2. 在這個新功能中,我們不能使用GM_getValueGM_setValue。使用計時器的解決方法會導致異步作業的其他一些問題。

如何在不使用unsafeWindow的情況下管理上述代碼?

+0

'使用定時器的變通辦法導致其他一些異步作業問題。「 有什麼問題? –

回答

1

爲了避免unsafeWindow,你可以使用:

location.assign("javascript:YOUR_CODE_GOES_HERE"); 

但是,這不會讓你使用GM_ *功能無論是。

而使用GM_ *「超出GM範圍」的唯一方法是使用定時器。

所以基本上,你的問題的答案是:你是在正確的方式,你不能做太多的事情。

如果你的函數不返回任何東西,那麼我會建議你使用location.assign

+0

看起來你是對的:在unsafewindow中不可能使用GM_getValue。唯一的解決方法是使用setTimeout和0 ms。 – WolveFred

0

如果你想避免unsafeWindow,代碼注入 - 這與頁面的交互JS - 進入頁面。見下面的addJS_Node()

從這類事件中觸發GM_功能,您應該能夠通過互動:

  • 寫作節點和聽DOMSubtreeModified(在W3C規範不建議使用)。但是,a bug in FF/GM prevents this for now

  • 發送自定義事件。再次,GM/FF bugs and features prevent that for now
    請注意,例如,當用戶物理地點擊時,例如,click事件可以調用使用GM_函數的代碼。但是,以編程方式生成相同的點擊事件,並且出現"Greasemonkey access violation: unsafeWindow cannot call..."錯誤。

所以,就目前而言,解決辦法仍然是用一個定時器,你能避免unsafeWindow,如果你想:

//--- Put everything that goes into the main page, inside myJS(). 
function myJS() { 

    window.oldDoWork = DoWork; 

    window.DoWork = function() { 
     // Do some new work 

     callGM_setValue ("From target page", "some value"); 

     window.oldDoWork(); // Call the old function 
    } 

    function callGM_setValue (varName, varValue) { 

     //--- Generate and dispatch a synthetic event. 
     var zEvent = document.createEvent ("CustomEvent"); 
     zEvent.initCustomEvent (
      "messageToGM_setvalue", true, false, 
      {Name: varName, Value: varValue} 
     ); 

     document.body.dispatchEvent (zEvent); 
    } 
} 

document.body.addEventListener (
    "messageToGM_setvalue", fireGM_setValue, false 
); 

function fireGM_setValue (zEvent) { 

    /*--- setTimeout remains one of the few things that can cleanse 
     the calling tree of it's "unsafe" origins. 
    */ 
    setTimeout (function() { 
     GM_setValue (zEvent.detail.Name, zEvent.detail.Value); 
    }, 0); 
} 

addJS_Node (null, null, myJS); 

function addJS_Node (text, s_URL, funcToRun) { 
    var D   = document; 
    var scriptNode = D.createElement ('script'); 
    scriptNode.type = "text/javascript"; 
    if (text)  scriptNode.textContent = text; 
    if (s_URL)  scriptNode.src   = s_URL; 
    if (funcToRun) scriptNode.textContent = '(' 
              + funcToRun.toString() 
              + ')()'; 

    var targ = D.getElementsByTagName('head')[0] 
       || D.body 
       || D.documentElement; 
    targ.appendChild (scriptNode); 
} 
相關問題