chrome.management.onEnabled Not Firing - google-chrome

I have this in my background.html:
chrome.management.onEnabled.addListener(function(ExtensionInfo info) {
alert('123');
});
which gives me an error: Uncaught SyntaxError: Unexpected identifier
If I remove info from function(ExtensionInfo info), I don't get any errors, but it's not firing the alert. Where did I go wrong?
Also, I added "management" inside permissions in manifest.json, so that's not the problem.

You won't be able to catch chrome.management.onEnabled event for your own extension.
If you are trying to execute some code on first extension installation then you would need to store some flag in a local storage.
background.html
if(!localStorage["first_run"]) {
//do something at first run here
localStorage["first_run"] = "done";
}
(for more advanced solution see this answer)
If you want to execute some code each time extension starts (browser startup) just put in into background.html.

Related

how to import a file in service_worker [chrome extension MV3] [duplicate]

I am trying to migrate my chrome extension from manifest version 2 to 3. Now that background scripts are replaced by service workers in manifest v3, I can no longer use a html file and refer js files in script tags.
Is there any way I can import my individual script files into the service_worker.js file?
I search almost everything on internet and couldn't find any solution. Even the official docs here Register background scripts were not so helpful. Any help would be appreciated.
First off, important warnings:
Warning: Chrome 92 or older doesn't show errors occurred in the service worker - it was a bug, fixed in newer Chrome, which now shows the errors in chrome://extensions page. These old versions of Chrome can't register the background script if an unhandled exception occurs during its compilation (a syntax error like an unclosed parenthesis) or initialization (e.g. accessing an undefined variable), so if you still support old Chrome you may want to wrap the code in try/catch.
Warning: Chrome 92 or older requires the worker file to be in the root path (bug).
Warning! Don't import DOM-based libraries like jQuery or axios because service workers don't have DOM so there's no document, XMLHttpRequest, and so on. Use fetch directly or find/write a library that's based on fetch and doesn't use window or document.
0. NPM packages
Use a bundler like webpack.
1. ES modules in Chrome 92 and newer
Enabled by adding "type": "module" to the declaration of background in manifest.json.
Name must start with a path and end with an extension like .js or .mjs
Static import statement can be used.
Dynamic import() is not yet implemented (crbug/1198822).
manifest.json:
"background": { "service_worker": "bg.js", "type": "module" },
"minimum_chrome_version": "92",
bg.js:
import {foo} from '/path/file.js';
import './file2.js';
As noted at the beginning of this answer, if you still target Chrome 92 or older, which don't surface the errors during registration, each imported module should also use try/catch inside where an exception is possible.
2. importScripts
This built-in function synchronously fetches and runs the scripts so their global variables and functions become available immediately.
manifest.json:
"background": { "service_worker": "bg-loader.js" },
bg-loader.js is just a try/catch wrapper for the actual code in separate files:
try {
importScripts('/path/file.js', '/path2/file2.js' /*, and so on */);
} catch (e) {
console.error(e);
}
If some file throws an error, no subsequent files will be imported. If you want to ignore such errors and continue importing, import this file separately in its own try-catch block.
Don't forget to specify a file extension, typically .js or .mjs.
2b. importScripts inside a listener
Per the specification, we must use a service worker's install event and import all the scripts that we want to be able to import in an asynchronous event later (technically speaking, anything outside of the initial task of the JS event loop). This handler is called only when the extension is installed or updated or an unpacked extension is reloaded (because it's equal to an update).
It's this convoluted in MV3 because service workers were designed for the Web, where remote scripts may be unavailable offline. Hopefully, it'll be simplified in crbug/1198822.
See also: webpack-target-webextension plugin for WebPack.
const importedScripts = [];
function tryImport(...fileNames) {
try {
const toRun = new Set(fileNames.filter(f => !importedScripts.includes(f)));
if (toRun.size) {
importedScripts.push(...toRun);
importScripts(...toRun);
}
return true;
} catch (e) {
console.error(e);
}
}
self.oninstall = () => {
// The imported script shouldn't do anything, but only declare a global function
// (someComplexScriptAsyncHandler) or use an analog of require() to register a module
tryImport('/js/some-complex-script.js');
};
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.action === 'somethingComplex') {
if (tryImport('/js/some-complex-script.js')) {
// calling a global function from some-complex-script.js
someComplexScriptAsyncHandler(msg, sender, sendResponse);
return true;
}
}
});

Google Chrome: DOMException: Registration failed - manifest empty or missing

I am trying to implement Push Notifications on my website (using Pushpad). Therefore I created a "manifest.json" with following content:
{
"gcm_sender_id": "my_gcm_sender_id",
"gcm_user_visible_only": true
}
of course I created a valid GCM-Account and have a sender id
I put the manifest.json into my root directory and I also added this line to my index.php:
<link rel="manifest" href="/manifest.json">
Using Firefox everything works fine and I can send and receive push notifications (so I think the manifest-include works fine), but Chrome won't work...
The console shows following error:
Uncaught (in promise) DOMException: Registration failed - manifest empty or missing
I searched Google for a long time and tried everything I found, but nothing works.
What I tried:
created the manifest.json with "Editor" and saved it as type All Types (so no hidden .txt-file) and also with UTF-8-Encoding.
restarted Chrome
cleared Chrome's cache, history, etc.
I really hope somebody can help me.
For me it was a redirect. The manifest.json must return a 200 status code (must be directly available from the server), without any redirects.
You can check the response via
wget --max-redirect=0 https://example.com/manifest.json
or
curl https://example.com/manifest.json
I faced same issue,added manifest file right after head tag . which worked for me.Cheers!
This may be an issue with your Service Worker scope. I ran into a similar problem when I rearranged my files/directories. Make sure your sw.js is on the same level as your manifest.json, otherwise the service worker won't be able to find your manifest. Try putting them both in the root of your directory. Optionally, you can specify the scope of your service worker by adding it to serviceWorker.register():
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw-test/sw.js', {scope: '/sw-test/'})
.then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}
Read more here:
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
Was wondering if your "manifest.json" is public accessible ?
If not maybe you can try to set it public accessible to see if that helps or not.
And it seems that the current chrome, when getting the "manifest.json" won't supply the cookies.
Because I didn't find an answer anywhere out there in the WWW, but managed to get it working after some time I want to provide my solution/answer for other users, who probably have the same problem:
In the file where I inlcuded the Pushpad files I wrote some PHP-Code before the <head>-Tag to include some files, e.g. for database connection. After I moved the PHP-Code below the <head>-Tag everything worked fine.
There seem to be three ways to fix this bug:
a) No redirects for "manifest.json" file.
b) Put a link to this file at the top of the tag.
c) Be sure, that there is no other manifest file before this one, cause it seems that web push script will try to import the first one and return an error due to the wrong data.
I have tried all three and finally forced Chrome to behave.
Adding the following block fixed this for me:
self.addEventListener('push', (event) => {
const title = 'Get Started With Workbox';
const options = {
body: event.data.text()
};
event.waitUntil(self.registration.showNotification(title, options));
});

Issue with Google-API-PHP Client, getting error when running the quick start script

I am facing an issue with quickstart php script here: https://developers.google.com/drive/v2/web/quickstart/php
When I run the script first time, it executes perfectly and the access token is stored in a file called: drive-php-quickstart.json
When I run the script second time, it gives me the error:
Error start:
Notice: Undefined index: expires_in in \google-api-php-client\src\Google\Client.php on line 485
Fatal error: Uncaught exception 'LogicException' with message 'refresh token must be passed in or set as part of setAccessToken' in
Error end:
My assumption is that access token been saved in the file is not in the right format.
Current format:
ya29.CODE-oN_Bearer36001/_ANOTHER-CODE-ANOTHER_ANOTHER_CODE
As you can see, it does not contain the variable "expires_in"
Any suggestions where I am going wrong ? I am running the script as it is, with no modifications.
I've debugged it.... The person who wrote it made a mistake by not calling json_encode before writing the auth result to the token.json file.
You can fix it by adding json_encode on line 45.
So...
file_put_contents($credentialsPath, $accessToken);
...should be:
file_put_contents($credentialsPath, json_encode($accessToken));
I've submitted feedback so hopefully it'll be fixed.
edit: same issue happens for the token refresh call in that same method
edit2: Here's my related comment in a Github discussion and an answer from Google: https://github.com/google/google-api-php-client/issues/263#issuecomment-186557360
I suggested something along the following lines:
if ($client->isAccessTokenExpired()) {
$refreshToken = $client->getRefreshToken();
$client->refreshToken($refreshToken);
$newAccessToken = $client->getAccessToken();
$newAccessToken['refresh_token'] = $refreshToken;
file_put_contents($credentialsPath, json_encode($newAccessToken));
}
Instead of:
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->refreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, $client->getAccessToken());
}
Google has updated their PHP Quickstart, with an improved method to handle this:
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}

run console.log commands through protractor

after some research I've found that can I make some assertions using 'console.log' (in Chrome) when testing a three.js page.
for example:
console.log(scene)
console.log(camera)
when running those commands I'm getting a JSON array and can check the parameters.
my question is - can I do this through protractor? meaning running the commands and check the response?
EDIT:
I know that I can use console.log for logging the test. but - I can for example going to browser console (chrome for example) and enter:
console.log(window)
when doing that, I get:
{top: Window, window: Window, location: Location, external: Object, chrome: Object…}Infinity: Infinity$: function (a,b){return new e.fn.init(a,b,h)}AnalyserNode: ...
and so on.
I can also enter
console.log(document.URL)
and get
http://stackoverflow.com/posts/28690960/edit
when trying to put the same line in protractor:
console.log(window);
I'm getting this error:
ReferenceError: window is not defined
thanks!
If your question is whether you can use console.log in protractor to log simple objects/variables, then yes, protractor is just javascript.
If your question is how to use console.log properly for promises (i.e. element(by.xyz).getText(), just keep in mind that everything protractor returns are promises, so you'll need to resolve the promise before doing console.log (see Protractor console log)
EDIT: okay, so you want to log objects from your browser. Protractors runs in a different process from your browser, so you would need to retrieve it first before doing console.log
browser.driver.executeScript(function() {
return window;
}).then(function(result) {
console.log('result is: ', result);
});

How to get appWindow from Chrome.app.window.create

I am trying to write a chrome.app that is able to open and close chrome.app windows on both displays of a system that is configured with two monitors. When launched, the chrome application establishes a socket connection with a native application running on the same computer, I also open a hidden window via chrome.app.window.create to keep the chrome application up and running. The native application then reads a configuration file and then sends a series of ‘openBrowser’ commands to the chrome application via the socket.
When the chrome application receives an ‘openBrowser’ command, the chrome application makes a call to the chrome API method chrome.app.window.create, passing the create parameters AND a callback function. A code snippet is below:
NPMBrowserManager.prototype.openBrowser = function (browserId,htmlFile,browserBounds,hidden,grabFocus)
{
var browserManager = this;
var createParameters = {};
createParameters.bounds = browserBounds;
createParameters.hidden = hidden;
chrome.app.window.create(htmlFile,createParameters,function(appWindow)
{
// Check to see if I got a non-undefined appWindow.
if(appWindow !== null)
{
browserManager.browsers.push({"browserId":browserId,"window":appWindow});
console.info("NPMBrowserManager.openBrowser: Added browser, id =" + browserId + ", count =" + browserManager.browsers.length);
}
});
}
Unfortunately, the ‘appWindow’, parameter passed in the create callback is always undefined. I suspect it has something to do with the fact that the method openBrowser is itself being called by another method that processes commands received from the native application. However, the window opens exactly here and when I want to to, I just can’t seem to cache away any information about the new window that can be used later to close or move the window.
I want to be able to cache away the appWindow so that I can close or modify the created window later on in the workflow.
As a side note, I’ve noticed that appWindow is NOT undefined if I call the openBrowser method from within the callback that is associated with the chrome.app.runtime.onLaunched event. I suspect it has something to do with the current script context. I was not able to find any chrome.app documentation that goes into any detail about the chrome app architecture.
I would GREATLY appreciate it if anyone out there can explain to me how I can get the appWindow of the window that is created in the chrome.app.window.create method. By the way, I have also tried calling chrome.app.window.current to no avail… Very frustrating!!!
I’d also be interested in any documentation that might exist. I am aware of developer.chrome.com, but could not find much documentation other than reference documentation.
Thanks for the help!
Jim