简体   繁体   中英

I'm getting an error "Tabs cannot be edited right now (user may be dragging a tab)" on tab update/activate/focus event in chrome 91

After the recent Chrome update my extension started to fire "Unchecked runtime.lastError: Tabs cannot be edited right now (user may be dragging a tab)" when I attempt to use chrome.tabs API. There is not much info on this issue yet, but I believe this is a browser bug. In the meantime my extension causes the chrome tabs to switch noticeably slower, that it used to be. It now takes a couple of seconds to change the tab. So I'm looking for a workaround.

Any ideas how to fix this?

The only solution that I have found so far is to put my handlers in a timeout like this:

chrome.tabs.onActivated.addListener((activeInfo) => {
        setTimeout(() => {
           // The old listener handler moves here
        }, 100);
    });

But there must be a better way, right?

You will still get errors but at least it will work

chrome.tabs.onActivated.addListener(function(activeInfo) {getActivatedTab();});
function getActivatedTab(){
    chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
        try{
            if(tabs[0]!=undefined){
            
                console.log(tabs[0].url);   
            }
        }
        catch(err){
            setTimeout(function() {
            getActivatedTab();
            },100);
        }
    })
}

create separate function outside of chrome.tabs.onActivated.addListener. this way work for me.

function insertScript(tab) {
  chrome.tabs.get(tab.tabId, function (info) {
    console.log(info);
   });
}
chrome.tabs.onActivated.addListener(function (tab) {
   setTimeout(function () {
     insertScript(tab);
    }, 500);
});

This is a bug in Chrome91, as pointed by @wOxxOm.

This patch is suggested if you are making a lot of calls to eg xchrome.tabs.query

const ChromeWrapper = {
  chromeTabsQuery: function (params, callback) {
    chrome.tabs.query(params, tabs => {
      if (chrome.runtime.lastError) {
        setTimeout(function () {
          //console.warn("Patch for xchrome.tabs.query (Chrome 91).");
          ChromeWrapper.chromeTabsQuery(params, callback)
        }, 100); // arbitrary delay
      } else {
        callback(tabs)
      }
    })
  }
}

And then, just replace the instances of

xchrome.tabs.query(...

with:

ChromeWrapper.chromeTabsQuery(...

...Alright, I don't have an really better solution other than setTimeout, as I don't really see where are the message/event posted after the tab done, so what I do is also add a setTimeout to do some "trial and error".

But how I do it is to override the original chrome.tabs.get so that we can have the same experience as we use it as expected way. (And easily to delete this snippet when they finally fix it some day)

Here is my code, cheers

    chrome.tabs.get = function () {
        const orig_get = chrome.tabs.get.bind(chrome.tabs);
        return async function (tabId) {
            return new Promise(
                resolve => {
                    var tryGet = () => {
                        orig_get(tabId)
                        .then(resolve)
                        .catch(() => {
                            // console.log("retry get");
                            setTimeout(() => {
                                tryGet(tabId);
                            }, 50);
                        })
                    };
                    tryGet();
                }
            )
        }
    }();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM