Omar Siddiqui
Omar Siddiqui

Reputation: 1655

chrome.tabs.onUpdated changeInfo.status === 'complete' fires too quickly

First time creating a Chrome extension, finding it a bit overwhelming.

I'm trying to create a plugin to extract review data from a website and store it in a text file. I want to be able to click the plugin button to start the downloads, and then the plugin should navigate to each review on the website using the Next Review button provided on the page, until it reaches the last review.

Each page takes some time to load, so I need to wait for the page to load before I can call the function that extracts the info and causes the page to move forward.

I originally tried using timers, but that obviously gives inconsistent behavior across systems, so I am now trying to use the chrome.webNavigation/chrome.tabs APIs.

Here's where I'm facing an issue. Neither chrome.webNavigation.onDOMContentLoaded nor chrome.webNavigation.onCompleted get fired if I'm using a link within the page to navigate to another page. They are only getting triggered if I navigate to a page by manually entering the url, or if I reload the page.

So I tried using the chrome.tabs.onUpdated event. This successfully recognizes that I have clicked on a link, but it gets triggered the instant I click the button. It does not wait for the DOM content to load. I need a way to delay this (without using timers) so that it fires after the page content loads

Here's an excerpt of my background script:

chrome.webNavigation.onDOMContentLoaded.addListener((tab) => {
  if (tab.frameId === 0)
    console.log("webNavigation DOMContentLoaded")
})
chrome.webNavigation.onCompleted.addListener((tab) => {
  if (tab.frameId === 0)
    console.log("webNavigation Content Loaded")
    
})


chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  let msg = {
    txt : "ContentLoaded"
  }

  if (changeInfo.status == 'complete' && tab.status == 'complete') {
    console.log('tabs ContentLoaded')
    chrome.tabs.sendMessage(tab.id, msg)
  }
})

I may be interpreting this incorrectly, but I was under the impression that the TabStatus (changeInfo.status) would show 'complete' when the page finishes loading (sort of like the 'load' event). Obviously, that isn't happening. If someone could also explain how it actually works, that'd be brilliant.

So, to summarize: I need a way for the Chrome plugin to realize that I've navigated to another page using a link, and it should fire an event only when the page content finishes loading.

Upvotes: 4

Views: 1841

Answers (1)

Graham Billington
Graham Billington

Reputation: 129

I struggled with this issue as well - I was using chrome.tabs.onUpdated to listen for the completed state of the tab. Then I would send a message to the content script (that wasn't loaded yet), and an error would be thrown.

To get around this, I used the scripting API to load in a JS file that ran my code. This only worked because the code I wanted to run at the onUpdated event didn't require any context from the original content scripts. Heres an example:

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {

    if (changeInfo.status == "complete" && tab.url) {
        // other checks for my use case here, then: 
        chrome.scripting.executeScript({ 
            target: { tabId: tab.id },
            files: ['js/scripts/listenForSubscription.js']
         })
    }
});

Again I'd like to reiterate that this only works because all listenForSubscription.js does is bind an event listener to an element on the DOM, so it doesn't need to interface with any objects or variables in the original content script. But this was a nice workaround to get rid of those annoying message-passing errors. Hope this helps

Upvotes: -1

Related Questions