2

This is my first time creating a Google Chrome Extension, and i can't find a way to reliably get the content script to run once when clicking a suggested video, or any video for that matter, on YouTube. I've tried setting "all_frames" to true, but that calls the script to many times. Is there a simple way to run a content script only once per video when browsing YouTube videos?

PS: I'm using YouTube as my main example but this issue exists on other websites. what causes it and how can I fix it?

{//manifest.json
  "name": "Test",
  "version": "0.0.1",
  "content_scripts": [{
      "matches": ["<all_urls>"],
      "js": ["run.js"],
    }],
  "permissions": ["activeTab"],
  "manifest_version": 3
}

-

//run.js
console.log('running');
glacial
  • 23
  • 1
  • 4
  • 1
    Youtube is an AJAX-driven site that updates the page dynamically on navigation. See [Is there a JavaScript/jQuery DOM change listener?](//stackoverflow.com/a/39508954) and [How to detect page navigation on Youtube and modify HTML before page is rendered?](//stackoverflow.com/a/34100952) – wOxxOm Apr 05 '18 at 05:53

1 Answers1

8

The problem is that Youtube updates the page dynamically, so the content script wasn't always being run after page content is changed. You need to detect if page url has been changed.

There is two ways for detect content changing.

Solution

  1. Use chrome.webNavigation.onHistoryStateUpdated event to detect that the content is changed.

You need to set permissions for webNavigation in manifest.json:

"permissions": [
    *"tabs", "webNavigation"*
  ]

background.js

    chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) {
//Send message to content Script -> Page was changed
//or execute parser from here 
// chrome.tabs.executeScript
});

content.js // do pars your content

  1. Use Mutation Observers: at your content script.

The MutationObserver interface provides the ability to watch for changes being made to the DOM tree.

// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');

// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true, subtree: true };

// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
    for(var mutation of mutationsList) {
        if (mutation.type == 'childList') {
            // do something with content 
        }
        else if (mutation.type == 'subtree') {
           // do something with content 
        }
    }
};

// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

// Later, you can stop observing
observer.disconnect();
Max Sherbakov
  • 1,817
  • 16
  • 21