Reputation: 2755
I want to make a small extension that injects a simple html into a YouTube page right under the video. It works fine if I simple visiting a youtube url. However if I choose a video from youtube offers then my html code is injected twice but removed. I can see that it to appear and then disappear almost immediately.
My code is:
background.js
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if ( changeInfo.status == 'complete' && tab.status == 'complete' && tab.url != undefined ) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {method: "reDraw"}, function(response) {
console.log("Injection ready!");
});
});
}
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.method == "reDraw") {
$.get(chrome.extension.getURL('/mytest.html'), function(data) {
$(data).insertAfter('#placeholder-player');
});
}
}
);
Upvotes: 3
Views: 7382
Reputation: 4215
Here is a way to only fire one time using chrome.webNavigation.onHistoryStateUpdated
// background.js
'use strict';
console.log('QboAudit Background Script');
chrome.runtime.onInstalled.addListener(details => {
console.log('QboAudit previousVersion', details.previousVersion);
})
chrome.webNavigation.onHistoryStateUpdated.addListener( (details) => {
console.log('QboAudit Page uses History API and we heard a pushSate/replaceState.')
if(typeof chrome._LAST_RUN === 'undefined' || notRunWithinTheLastSecond(details.timeStamp)){
chrome._LAST_RUN = details.timeStamp
chrome.tabs.getSelected(null, function (tab) {
if(tab.url.match(/.*\/app\/auditlog$/)){
chrome.tabs.sendRequest(tab.id, 'runQboAuditLog')
}
})
}
})
const notRunWithinTheLastSecond = (dt) => {
const diff = dt - chrome._LAST_RUN
if (diff < 1000){
return false
} else {
return true
}
}
In short you make a global var chrome._LAST_RUN
to track if this event has already fired less than a second ago.
// contentscript.js
chrome.extension.onRequest.addListener((request, sender, sendResponse) => {
//console.log('request', request)
if (request == 'runQboAuditLog')
new QboAuditLog()
});
Upvotes: 2
Reputation: 10897
chrome.tabs.onUpdated
will also fire for iframes, and for youtube, there are many iframes will trigger this event, besides that, youtube doesn't reload the page when you go from one video to another. For more details about youtube issue, you could take a look at these threads:
So my recommendation would be using chrome.webNavigation
api, and combining webNavigation.onCompleted
with webNavigation.onHistoryStateUpdated
, sample code would look like the following
Considering you are detecting youtube video page, I would suggest you used chrome.webNavigation.onHistoryStateUpdated
// To handle youtube video page
chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) {
if(details.frameId === 0) {
// Fires only when details.url === currentTab.url
chrome.tabs.get(details.tabId, function(tab) {
if(tab.url === details.url) {
console.log("onHistoryStateUpdated");
}
});
}
});
Upvotes: 14
Reputation: 198
I guess youTube is using Ajax calls on some pages to load things, so your code is being replaced with the Ajax response.
Use a setTimeout() function to check after a few seconds if your code is on the page, if it's not, add it again.
Upvotes: 0