Have a small doubt in how message passing works in chrome using content scrips. I modified the default example (http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/timer/) for message passing given in the chromium documentation to the one that looks below :
popup.html
function testRequest() {
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {counter: "getHTML"}, function handler(response) {
alert("Inside Client = "+response.counter2);
});
});
}
and my content script looks like this :
page.js
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
alert(request.counter);
alert("Inside server .. Req Counter = "+request.counter);
sendResponse({counter2: "5"});
});
When I execute the testRequest from popup.html, the content script is getting called as expected. I do get both the alerts i have
declared with their respective values. But my popup.html response code doesnt seem to be called .. The alert I have inside the popup.html - alert("Inside Client = "+response.counter2); is not being executed.
On the other hand, If i have a debug point inside the client, its working ! Kinda strange.. Can somebody tell me how and why this is happening ?
Thank you in advance..
your code is correct. I am mistaken what I said before.
Believe me when I say it, I was puzzled why it didn't work. It turned out to be that I am running the browser action on the chrome://extensions/ page. In Chrome Extensions, the API will not let you execute or send any requests to that page. Do it on a normal page like Google.com and you will see your popup.
You cannot show an alert dialog within popup page.
That is why you don't see: alert("Inside Client = "+response.counter2); }
If you want to see it working, you can add a console logger and view it within the Web Inspector. Replace the alert with: console.log(response.counter2);
As far as I can tell, alerts from a popup will only appear if the popup is open.
You see the alert when you're debugging the popup because the debugger keeps the popup open.
I'm pretty sure there are also no problems with creating alerts from the background page.
Related
I have the following code (I don't recommend running it):
let req = new XMLHttpRequest();
req.open('GET', 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=' + token);
req.onload = function() {
console.log('response:', req.response);
};
req.send();
What happens is this opens up a new tab, and this tab completely steals all the focus. I can't use any of the other Chrome tabs, it quickly switches back to the auth tab. And if I log-in with the auth tab, it just reloads the same auth tab, and I am back to square one.
The token is acquired via this call:
chrome.identity.getAuthToken({interactive: true}, function (token) {}):
Has anyone seen this horrible problem? I can't get Chrome to stop making an auth request to the url in the screenshot. It keeps stealing the focus, and forcing me to login over and over again.
From what I can tell, it's actually this call this brings to me to the black hole authentication tab:
chrome.identity.getAuthToken()
This didn't use to happen, but seems like it started happening after I added this to my manifest.json file:
"oauth2": {
"client_id": "5461xxx462-7gebv033e9csxxxxg5f6ggu22rju9374.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/oauth2/v1/userinfo", // added this line
"https://www.googleapis.com/oauth2/v1/userinfo.picture", // and added this line
"https://www.googleapis.com/auth/chromewebstore.readonly"
]
},
The old login screen looks like this, and this worked really nicely:
I am currently fairly certain that these two lines in the scopes array are what are causing the problem:
"https://www.googleapis.com/oauth2/v1/userinfo"
"https://www.googleapis.com/oauth2/v1/userinfo.picture"
what do I do?
I've had this problem before but it was months ago. If I recall correctly, it ended up being that the client_id was invalid. Double check your oauth client_id to make sure you're using the correct one.
I've got a Chrome Extension where the popup messages the content script - pretty straightforward. The following works consistently on macOS (Chrome 61.0.3164.100) but not on Windows 10 (Chrome 61.0.3163.100):
aSearch.js (popup)
function sendMessage(comment){
window.close(); //Close popup.
console.log("In send message: " + comment);
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {method: "insertComment", comment: comment}, function(response) {
// console.log(response.farewell);
});
});
}
Then content.js:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log('In content script after receiving request to insertcomment...');
if (request.method == 'insertComment'){
etc...
I can provide a lot more code...but the "console.log" does not fire even though background.js shows the related activity.
The aSearch.js is for an html popup that replaces the initial one...after you log in (not sure if this is important). This is accomplished in background.js:
chrome.browserAction.setPopup({ //Sets popup to last visited
popup: 'aSearch.html' // Open this html file within the popup.
});
Any guidance on what can make messaging break? Should I be taking a different approach for a constant (frequent) messaging that is used across many tabs, potentially?
Why would Chrome for Windows act differently?
Side note: I actually updated Chrome for Windows as I wrote this question...after the update suddenly messaging worked, for a little bit, then went back to dormant.
UPDATING QUESTION:
I added more code to the aSearch.js popup at the top...
I think I'm closing the popup before the message can be sent...and it's working sometimes (and on my macOS dev machine) because the computer is fast. On Windows, which is VM on my mac, not so fast...
Tomorrow I'll move the close inside the response from messaging...waiting for message to reply.
Is this plausible?
The issue here was, indeed, that you can't close a popup window before the message is successfully sent.
Duh.
The challenge, though, is that on my machines the message is sent successfully before the window closes. So I didn't discover the bug.
I have the message receiver acknowledging success and then closing the popup. Works like a charm.
My extension used to work fine. but recently it is buggy. when I pass messages between background page and content script, no matter which tabId I pass into the function, all tab's content script will get the message.
I'll just make an example.
if one time message exchange:
Background page:
chrome.tabs.sendMessage(tabId, "test");
content script:
chrome.runtime.onMessage.addListener(function (req, sender, sendResponse) {
console.log(req);
});
if I have two or more tabs running this content script, all of them will show the "test" string no matter what the passed tabId in background page is.
This also happens on long-live connections.
My chrome version is 46.0.2471.2 m and on another machine is 45.xxxx.
I am learning to create a chrome extension. To start, I am trying to just gather all links on the page and display them in the popup window of the extension when the button is clicked. I can't seem to get it right. I am able to use messages and send a message from my chrome tab to the extension. But when I try to pass the array of a tags, then it breaks.
My content script:
window.addEventListener('DOMContentLoaded', function () {
chrome.tabs.executeScript(null, {file: "content.js"});
});
My extension script:
window.addEventListener('message', function(e) {
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
console.log(event.data.links);
}
}, false);
if I dont do the links, it works fine and sends the messages. So I can't find another way to send all the links to the extension so I can process them. I have this in a github repo here https://github.com/skiftio/chrome-linkman
Your understanding of the architecture is a bit off. Please read through the Overview page, especially the Architecture part.
I'll even include a helpful picture here:
The popup is counted as "other pages" on this picture. It's an HTML page on its own domain (chrome-extension://yourextensionidhere), which is created when you open the popup and destroyed when you close it.
A content script is a script attached to a real Chrome tab; it gets access to its DOM, but is isolated from the page's own scripts. It also has very limited access to Chrome APIs.
More importantly, there are 2 ways of telling Chrome to add a content script to the page: you can declare it in the manifest so that Chrome automatically injects it upon navigation, or you can programmatically inject it from somewhere in your extension pages. You are mixing up those two.
Your manifest entry refers to scripts.js which is NOT a content script and you should not call it such. For instance, chrome.tabs.executeScript is not allowed to be called from a content script, and it will just throw an error. Since you're also injecting the script from the popup, you should just remove the section from the manifest, you don't need it.
As for messaging, you're trying to use window.postMessage, but this is not standard in Chrome extensions.
Take a look at the full Messaging docs, and I recently gave a short overview here.
In your situation, you could add a listener to chrome.runtime.onMessage to the popup and send a message with chrome.runtime.sendMessage from the content script:
/* --- Popup code (scripts.js) --- */
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
if(message.links) {
/* do work */
}
});
chrome.tabs.executeScript({file: "content.js"});
/* --- Content script code (content.js) --- */
var links = document.getElementsByTagName("a");
chrome.runtime.sendMessage({links: links});
I am trying to write a JavaScript function that will open my extension like when the extension icon is clicked. I know how to open my extension in a new tab:
var url = "chrome-extension://kelodmiboakdjlbcdfoceeiafckgojel/login.html";
window.open(url);
But I want to open a pop-up in the upper right corner of the browser, like when the extension icon is clicked.
The Chromium dev team has explicitly said they will not enable this functionality. See Feature request: open extension popup bubble programmatically :
The philosophy for browser and page action popups is that they must be triggered by user action. Our suggestion is to use the new html notifications feature...
Desktop notifications can be used progammatically to present the user with a small HTML page much like your popup. It's not a perfect substitution, but it might provide the type of functionality you need.
Chrome team did create a method to open the popup programmatically, but it's only enabled as a private API, and plans to make it generally available have stalled due to security concerns.
So, as of March 2018 as of now, you still can't do it.
Short answer is that you cannot open browserAction programmatically. But you can create a dialog with your content script which emulates your browserAction and display that isntead (programmatically). However you won't be able to access your extension's background page from this popup directly as you can from your popup.html. You will have to pass message instead to your extension.
As mentioned there is no public API for this.
One workaround I have come up with is launching the extension as an iframe inside a content script with a button click. Whereby the background script emits the extension URL to the content script to be set as the iframe's src, something like below.
background.js
browser.runtime.onMessage.addListener((request) => {
if (request.open) {
return new Promise(resolve => {
chrome.browserAction.getPopup({}, (popup) => {
return resolve(popup)
})
})
}
})
content-scipt.js
const i = document.createElement('iframe')
const b = document.createElement('button')
const p = document.getElementById('some-id')
b.innerHTML = 'Open'
b.addEventListener('click', (evt) => {
evt.preventDefault()
chrome.runtime.sendMessage({ open: true }, (response) => {
i.src = response
p.appendChild(i)
})
})
p.appendChild(b)
This opens the extension in the DOM of the page the script is running on. You will also need to add the below to the manifest.
manifest.json
....
"web_accessible_resources": [
"popup.html"
]
....
You could emulate the popup by displaying a fixed html element on the page in the same location the popup would be and style it to look like the popup.
I had the same requirement: When the user clicks on the extension icon a small popup should open. In my case, I was writing an extension which will give updates on selective stocks whenever the icon is clicked. This is how my popup looked.
If you were having the same requirement then please read the answer below.
This is how my manifest.json file looked.
All the heavy lifting was handled by manifest.json file only. There is a section browser_action inside which there is a key called default_popup, just put the name of the HTML file that you want the popup to display.
I wanted my extension to work on all the pages that's why I added the attribute matches under content_scripts. I really didn't need to put the jquery file jquery-3.2.1.js inside the js array but the extension manager was not allowing me to keep that array empty.
Hope this helps, do comment if you have any doubt regarding the answer.