setTimeout не работает в скрипте пользователя Greasemonkey, когда JS отключен в браузере - PullRequest
7 голосов
/ 28 июля 2010

Я работаю над проектом, который требует, чтобы мой пользовательский скрипт запускался на страницах, поскольку они отображаются без выполнения какого-либо JavaScript-кода страницы.То есть нам нужно просматривать с отключенным JavaScript.

Я столкнулся с проблемой, когда пытался отложить выполнение функции в моем скрипте.Всякий раз, когда я звоню window.setTimeout, функция, которую я передаю, никогда не выполняется.

Я думаю, что эта функция на самом деле вызывается unsafeWindow вместо окна.Есть ли обходной путь для этого?

Я должен отметить, что вызовы setTimeout работают нормально, когда включен JavaScript, а все остальное в моем скрипте работает нормально без включения JavaScript.

Спасибо за вашу помощь!

Ответы [ 3 ]

4 голосов
/ 29 июля 2010

Несмотря на то, что Greasemonkey JavaScript работает с повышенными привилегиями, как сказал Пойнти, функции setTimeout добавляются к пространству JavaScript страницы - по мере необходимости заключаются в замыкание. (При нормальной работе экземпляр Greasemonkey часто исчезает к тому времени, когда таймеры запускаются.)

Таким образом, если основной JavaScript-код страницы отключен, таймер никогда не будет работать.

Возможные обходные пути:

  • Используйте GM_xmlhttpRequest как грубую задержку. Вы можете настроить страницу, которая намеренно вытягивает свой ответ. Так что код вроде:

    GM_xmlhttpRequest
    (
        {
            method: "GET",
            url:    "http://YourTestServer.com/DelayService.php?Seconds=2",
            onload: function (response) {YourDelayedFunctionHere (); }
        }
    );
    

    Вызовет служебную страницу, которую вы настроили, чтобы сделать задержку для вас.

  • Используйте NoScript, чтобы отключить весь JavaScript-код страницы, кроме главной страницы. Например, для страницы YourSite.com / testpage.htm , которая включает в себя сценарии, скажем, * SpamGenerator.net ... Разрешить сценарии от YourSite.com но заблокируйте их от SpamGenerator.net .

2 голосов
/ 28 июля 2010

Ссылка window по-прежнему window страницы, только что завернутая в оболочку песочницы. Когда вы звоните по номеру setTimeout, вы все равно настраиваете что-то, что будет запускаться страницей. Я предполагаю, что это должен быть случай, когда браузер вообще не будет запускать эти события тайм-аута (или просто будет игнорировать события), когда Javascript отключен.

0 голосов
/ 17 мая 2011

это может быть исправлено следующим образом:

Вы можете сказать НЕТ NoScript + setTimeout = ошибка

В greasemonkey.js: найти [injectScripts]: функцию ..... добавить нашGM-api .....

Добавить этот код:

sandbox.setTimeOut = function (callback, timeout, p1,p2,p3/*....*/){
    var args = Array.prototype.slice.call(arguments,2);
    return  sandbox.window.setTimeout(function(){
        return callback.apply(sandbox, args);
    } ,timeout);
}

или

sandbox.setInterval = function (callback, timeout, p1,p2,p3/*....*/){
    var args = Array.prototype.slice.call(arguments,2);
    return sandbox.window.setInterval(function(){
        return callback.apply(sandbox, args);
    } ,timeout);
}

Этот код работает нормально, я использовал его с мая 2010 года.

В user.js вы можете проверить это следующим образом:

setTimeout(alert,1000, 'i am happy');
var loopid = setInterval(alert, 1000, 'I am happy again');
setTimeout(clearInterval, 5000, loopid);

var j=300;
for(;~j;j--){ //running perfectly!
    setTimeout(alert, 1000+20*j, 'I am happy' )
}

Решение 2

sandbox.kk_setTimeout = function (func, timeout, repeat_type, p1,p2,p3/*....*/){
    var callback = { k100: sandbox };
    var args = Array.slice.call(arguments,3);

    // repeat_type:  0=once  1=repeatng, after fired stopped    2=always repeat
    if(repeat_type!=2){
        callback.notify = function (timer){ func.apply(this.k100,args); }
        var timerCC = Components.Constructor("@mozilla.org/timer;1", "nsITimer", 'initWithCallback');
        var R = repeat_type?1:0;
    } else {
        callback.observe = function (subject, topic, data) { func.call(this.k100); };
        var timerCC = Components.Constructor("@mozilla.org/timer;1", "nsITimer", 'init'); 
        var R = 2; 
    }
    return new timerCC(callback, timeout, R);
}

// now have to test it:

var test100 = kk_setTimeout(alert, 1000, 0, 'i am timer');  //running = setTimeout
var test100 = kk_setTimeout(alert, 1000, 2, 'i am timer');  //running = setInterval
test100.cancal() ;   //clear it by cancel() method

kk_setTimeout(alert, 1000+20*j, 2, 'i am happy' );
var j=300;
for(;~j;j--){
    kk_setTimeout(alert, 1000+20*j, 0, 'i am happy 2' );
}

//bug:
//this solution 2 running after about 3-8 times differently stop, why bug ? i don't know.
// you will fail to use many times(over 3-8 time) kk_timeout(); or using repeat_type = 2 after fired 3-8 times timeout
//or running total time max about 20-30 seconds stop 
//--- this maybe stop by option in about:config -- about [max javascript run time]

исправлено china-kkmove


изменить, чтобы добавить…

Извините всех,

Есть еще несколько исправлений для кода, который я забыл написать:

sandbox.window = sandbox._proto_; // add this line also to the solution 1#

Эта ошибка мне пришла в голову сегодня утром.

...