First a little background
I was tasked with creating a 'program' that would take screenshots of web pages at given times throughout the day and save the images to a folder accessible to the user. My original train of thought was to create an extension to do the job, but I soon realized that extensions don't have access to the file system, so I turned to chrome apps which can use the fileSystem API. However, chrome apps don't have access to the functions required to take a screenshot of the current page, thus I ended up creating both: the extension takes the screenshot and sends a blob of it to the app which saves it to the file system. The process is a bit convoluted but works like a charm.
Now, the app/extension communication occurs via chrome's Message Passing API. In order for communication to take place, I need to know the id of the extension or app beforehand. I've hard-coded the ids until now, but given that those ids will will change every time the extension or app is installed, I need a better approach.
Now The Question
Thus the question is: what is the recommended way to obtain the id of a chrome app from within a chrome extension and vice versa? The plan right now is to use the chrome.management API and do the following:
In Extension
var APP_NAME = "Name of My App";
var _appId;
...
function initializeAppId() {
// must declare the "management" permission in the manifest
chrome.management.getAll(function(result) {
for (var i=0; i<result.length; i++) {
if (result[i].name == APP_NAME) {
_appId = result[i].id;
}
}
});
}
Is this the way to go about it? I would still need to hard code the name of the app, but that's not nearly as tragic as hard coding its id. Also, packaged apps don't have access to the management api, so if I went this route, I would have to do it from the extension only. Once I get the app id, I can then send a message to the app and provide the extension id which can be easily obtained from within the extension code.
How does that sound? Any suggestions?
Thanks
Your approach is correct in the sense that it will work.
But chrome.management is a big hammer not particularly suited for the task.
You said that the IDs change. This only happens with unpacked versions, because they are not signed yet with a cryptographic key; Chrome has to assign something as an ID and it does it by hashing the path to the extension/app.
The solution is to either pack/sign the app once to obtain a suitable public key inside the CRX, or do the cryptography yourself as described here. When you specify the "key" property in the manifest, Chrome uses it to derive the ID and it stops changing.
After that, you can hard-code the ID.
Related
So, I am working on a project(building a chrome extension) that requires data to be stored on the local machine of the user. The size of data is quite large hence I thought of using IndexDB for this purpose.
My Question is whether is it possible to connect a chrome extension with IndexDB and query the database at the same time??
If Yes, Then how can I integrate them. In which file(popup.js or background.js or any other file) should I include the source code for creating the database.
I want the code for creating the database to run only once. After that I only want to update or delete data only.
If No, then is there any other way to achieve this?? The data is large hence I cannot store data in local storage.
Any paper, online material, advice or method from chrome developers or any other valid site would be helpful. Any example would help me alot.
Thankyou.
You can store tons of data in any HTML5 storage (including IndexedDB or localStorage) and chrome.storage.local with "unlimitedStorage" permission.
HTML5 data is stored per URL origin and each extension has its own one that looks like chrome-extension://id where id is a 32-character string that is the extension's id. In Firefox the origin looks like moz-extension://id.
Extension's own HTML5 storage:
can be accessed in any extension page (popup, options, background) just like you would do it in a web page, there are no differences.
cannot be accessed in a content script as it runs in a web page and thus can only access HTML5 storage of the web page's URL origin.
chrome.storage.local can be accessed in any extension page and in a content script.
No need for special event to create/upgrade your IndexedDB storage - it'll happen automatically if needed - simply open it as shown in the documentation whenever you need to access it and your onupgradeneeded callback will be invoked in case there was no DB or it was outdated.
Use a wrapper library for IndexedDB that provides a simplified syntax. Some are listed in the documentation, but you can probably find better ones yourself.
I am looking through the code for a chrome extension i use to see what data is reported back to devleoper/mother-ship. I see that the extension's code saves some info using 'chrome.storage.sync.set' which of course makes sense as the variables that are stored there are available to me not matter what computer I load the extension on.
My question is... does the developer have access to this data? I would guess not but wanted to make sure. I have been looking for other code that posts data or does something that could send data back to developer but this was the only thing that looked suspicious so far.
No, developer cannot access chrome.storage.sync data and no one can read this except you.
This location is access controlled by
User
Extension
Infact any other extension can not read other extension's data. You can think about this storage similar to localstorage.
Now, If I ask you a question
Does the website developer has access to different values stored in user's local storage ?
The answer is No. Developer can control what to save in this storage and the values are user specific and they remain on user's machine.
However, this comes with a catch. You have to look out for code like this in the extension:
chrome.storage.sync.get('key', function(obj) {
// Make ajax to upload the key value pair
});
But by default, developer do not have access.
While it appears that we will still be able to use google drive to host images for websites (when load speed is less of an issue than users being able to add things when they do not know any html). I have been using google apps scripts to generate JSON files that are then loaded to build webpages (This way I could have people add images to a folder, and lines on a spreadsheet and the page builds automatically). I noticed a couple of other people asking questions about this, so it is not only going to effect me. However with Google ending their 'host' feature in August, has anyone come up with a solution other than just make a small server that grabs the JSON file occasionally and hosts it in a way that allows cross domain access?
Well I found a work around inside google apps script for anyone interested. There is one large problem with it. It does not work on any safari browsers due to a known, but triaged bug. (https://code.google.com/p/google-apps-script-issues/issues/detail?id=3226) This is something I should have thought of before, as I have used it as a trick in the past:
function doGet() {
var myFile = DriveApp.getFileById('<FILE_ID>');
var str = myFile.getBlob().getDataAsString();
return ContentService.createTextOutput(str).setMimeType(ContentService.MimeType.JSON);
}
Once you have your id set up go to Publish->Deploy as Web App, set things to Execute as me, and anyone even anonymous can access. The URL https://script.google.com/macros/s//exec will allow cross domain grabs at this point.
This, I believe, will have a quota that could in theory be overwhelmed, but you can always choose to pay for more access. In my case I will just add direct access to the JSON generated by the original script so I will not hit google drive quotas, but this should work fine for any reasonably small project that does not need Safari access...
i have been going around in circles here and have totally confused myself. I need some help.
I am (trying to) writing an application for a client that in concept is simple. he want a google write document with a button. the google drive account has several folders, each shared with several people. when he drops a new file in one of the folders, he wants to be able to open this write file, this file is the template for his email. he clicks the button, the system calls the changes service in the Google Drive SDK https://developers.google.com/drive/manage-changes, gets the list of files that have been added since the last time it was checked, then pull the list of people that the file has been shared with, and use the write file as a template to send that list of people an email saying their file is ready.
SO, easy enough, right?
I started by looking at the built in functions in the Google App Script API. I found this method, https://developers.google.com/apps-script/class_docslist#find in the DocsList class. problem is the description for the query simply says "the query string". So at first i tried the Drive SDK query parameters, which are
var files = DocsList.find("modifiedDate > 2012-12-20T12:00:00-08:00.");
it didn't work. that leads me to believe it is a simple full text search on the content. Thats not good enough.
That lead me into trying to call a Drive SDK method from within an App Script application. Great, we need an OLap 2 authentication. easy enough. found the objects in the script reference and hit my wall.
Client ID and Client Secret.
you see, when i create what this really is, a service account, the olap control in apps script doesn't know how to handle the encrypted json and pass it back and forth. Then when i tried to create and use an installed applications key, i get authentication errors because the controls again, don't know what to do with the workflow. and finally, when i try to create a web app key, i can't because i don't have the site host name or redirect URI. And i can't use the application key ability because since im working with files OLap 2 is required.
i used the anonymous olap for a while, but hit the limit of anonymous calls per day in the effort of trying to figure out the code a bit, thats not going to work because the guy is going to be pushing this button constantly thru the day.
i have been pounding my head on the desk over this for 5 hours now. i need some help here, can anyone give me a direction to go?
PS, yes, i know i can use the database controls and load the entire list of files into memory and compare it to the list of files in the database. problem being, we are talking tens of thousands of files. bad idea.
I wouldn't use DocsList anymore - DriveApp is supposed to be a more reliable replacement. Some of the commands have changed, so instead of find, use searchFiles. This should work more effectively (they even use a query like yours as an example).
I would like to make a copy of a Google Spreadsheet file between users that are not on the same domain. The source file has a sharing setting of Anyone with the link can edit.
I created a Web App (with execution permissions set to User accessing the web app) that call an install function:
I was hoping the code would read the source file which is open to everybody and make a local copy to the Google Drive of the user running the Web App (of course assuming the user accept to run the script). The behavior works when it's me running it (because I am the owner of the source) but do not work if the user is from another domain.
Any suggestions on how to achieve this?
function doInstall() {
// The source file is readable by everybody with the link;
var file = DocsList.getFileById('0AlVPTKz1xoevdHc1ZTQ2OGFMXXXXXXXYYYYZZZZ');
file.makeCopy('Test Copy Spreadsheet');
}
I had a different but similar use case and problem. Like you, my source file was accessible to anyone with the link and my domain settings allowed users to share content outside my domain. It worked for me but not for them.
This might work for you, it has for me (so far):
Assuming you have your original script...
Create a separate script for 'Script as web app'.
Write a function (e.g. loadFileIds()) to store the necessary fileIds using ScriptDb. Run the loadFileIds() function.
Write another function (e.g. getFileId()) in the same project that returns your desired file Id from ScriptDb.getMyDb when called. Avoid using DocsList in this function. I originally thought that because getFileId() would 'run as me' that it would be OK but it was always the DocsList line that caused failures when other users triggered the script.
In File > Manage Versions: Save a version of the project.
Under Publish: Deploy that version of your project as a web app. Choose Execute the app as "me(me#mydomain.com)" and set Who has access to the web app to "Anyone".
In your original project go to Manage Resources and enter the Project Key of the web app, choose a version and copy the identifier.
Write a function that calls yourIdentifier.getFileId() and - hopefully - returns the fileId.
In my experience so far external users have been able to access files that they could not when DocsList methods returned null. But there is one more thing to add... You might find you have to share your web app script with your users. I haven't quite made certain that's necessary but I've encountered bugs when I don't. I untick the option to email them the link.
I learned how to do this from examples in the documentation, this video and of course StackOverflow.
As you can see, I'm still working this out myself and testing of the system has so far been just me simulating other users. So no promises. Good luck! I'll star your issue.