Accessing a local directory from a Chrome App - google-chrome

I am working on a Chrome extension called Chrome Snippets that will allow you to inject snippets of JavaScript from files but I am having trouble accessing local directories on the user's computer. Anyone have an idea of how to accomplish this?
manifest.json:
{
"name": "Chrome Snippets",
"description": "Run JavaScript on the DOM of any web page from a library of recipes stored on your computer.",
"author": "Adam Fisher",
"version": "1.0",
"manifest_version": 2,
"default_locale": "en",
"permissions": [ "tabs", "webNavigation", "*://*/*", {"fileSystem": ["write", "retainEntries", "directory"]} ],
"app": {
"background": {
"scripts": ["js/background.js"],
"persistent": false
}
},
"icons": {
"16": "img/icon16.png",
"48": "img/icon48.png",
"128": "img/icon128.png"
},
"options_page": "html/options.html",
"homepage_url": "http://adamfisher.me"
}
background.js:
/*
** file: js/background.js
** description: Main functionality of the extension. Checks if a file exists
** for the given host name and loads it.
*/
chrome.webNavigation.onCompleted.addListener(function (details) {
var recipesDirectory = localStorage['Chrome_Snippets_Recipes_Directory'];
var host = "/^(?:ht|f)tps?:\/\/([^/]+)/".exec(details.url); // Get the host part of the URL.
chrome.tabs.executeScript(details.tabId, {
file: ''
});
});

You CAN'T make what you want in a single app/extension, that's what Paweł tries to tell you.
Compare Apps APIs and Extensions APIs
Apps can't use tabs (and in general can't interact with normal browser content), extensions can't use fileSystem (and in general can't access system resources).
You need to rethink your strategy OR use both an extension and an app that talk to each other.

Replace "app" in the manifest.json file with "background":
"background": {
"scripts": ["js/background.js"],
"persistent": false
},
Reference: https://developer.chrome.com/extensions/event_pages
The "app" entry is reserved for Chrome Apps which have different set of API's and permissions.
================================================
Edit
Forgot about what you really asking for.
Chrome extensions can't access user's filesystem. This API is only available for Chrome Apps.
So if you need to do it as an extension you can't save files on local file system.

Related

Chrome extension REJECT when inline installation checked

I made custom chrome extension which loads external javascript file (file is hosted on amazon s3) using XMLHttpRequest. Code snippet which calls this XMLHttpRequest is in separate file, and included in manifest.json under content_scripts:
{
"background": {
"scripts": [ "background.js" ]
},
"content_scripts": [ {
"js": [ "content.js" ],
"matches": [ "http://*/*", "https://*/*" ]
} ],
"manifest_version": 2,
"name": "Name",
"short_name": "shortname",
"update_url": "https://clients2.google.com/service/update2/crx",
"version": "1.0"
}
If I don't check inline install, it is accepted and published in few minutes.
But when I check inline install and choose site, review process takes a long time and extension becomes rejected. Domain is secured (https). And tag containing info about extension is added to site's head tag.
<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/itemID">
So, the rejection reason is probably related to inline installation method, and there should be some trick? Anyone for help? Is there something wrong I did?

Using chrome.runtime.sendmessage to communicate from a webpage to a packaged app

I'm trying to communicate from a web page to a packaged app. The idea is to have the web page read a number from a serial device. Because I want to access the serial device, I need a packaged app and can't use an extension. This is pretty similar to Keep Chrome Packaged App running in background? and it seems that Chrome documentation says this is possible.
How can I execute the chrome.runtime.sendMessage from a regular web page? When I do so, I get *Uncaught TypeError: Cannot read property 'sendMessage' of undefined. My simple function is:
function doFunction(){
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
if (!response.success)
handleError(url);
});
}
My packaged app loads and can access the serial ports. But my suspicion is the manifest isn't "enabling" the chrome.runtime of the regular webpage. Manifest.json:
{
"name": "Hello World!",
"description": "My first Chrome App.",
"version": "0.1",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"icons": { "16": "calculator-16.png", "128": "calculator-128.png" },
"permissions": [
"serial",
"*://localhost/*"
],
"externally_connectable": {
"matches": [
"*://localhost/*"]
}
}
Maybe it's the ://localhost/ which I'm using for testing. But Chrome does not complain.
Any ideas out there? Thanks in advance.
Xan's comment did the trick.
While Chrome did not complain about *://localhost/*, it did not work. Chrome did complain about other combinations such as file://localhost/.
I added foo.com to host file and then served up my web page through a web server, and it worked! I can communicate from my web page to my packaged app.
Note that browsing to file://www.foo.com/hostpage.html did not work. But browing to http://www.foo.com:3000/hostpage.html did. (I'm using Rails, hence the 3000 port).
Morale of the story: When testing locally, you need to add an entry with a bogus second level domain to your host file.
Here's my manifest.json:
{
"name": "RFID Tag Reader",
"description": "Reads RFID Tags connected via USB reader",
"version": "0.0.0.1",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"icons": {
"16": "rfid-16.png",
"128": "rfid-128.png"
},
"permissions": [
"serial",
"*://www.foo.com/*",
"*://arealsite.net/*"
],
"externally_connectable": {
"matches": [
"*://www.foo.com/*",
"*://arealsite.net/*"
]
}
}
Adding "*://localhost/*" to externally_connectable worked for me.

Chrome extension with no icon?

I am trying to create a simple Google Chrome extension. I don't want it to have an icon next to the omnibar. Is this possible? What do I need to put in my manifest.json?
Yes, this is possible. To do it, just don't declare browser_action in your manifest. Remember, though, to get it to work, you'll need to do something to run the script. contextMenus are a great way to do that.
Here's a manifest that has no browser action line, so it will not display an icon:
manifest.json
{
"manifest_version": 2,
"description": "Example",
"name":"Example",
"icons": {
"16": "img16.png" }, // Needed for the context menu
"background": {
"scripts":["background.js"] },
"permissions":[ "tabs", "contextMenus" ], // contextMenus permission allows you to create the action
"version": "1.0"
}

Accessing the Cast API from within an extension page

I was working on a chromecast app, and I wanted to incorporate it into a chrome extension. I'm also using knockout.js in order to help with some of the UI. I have two pages, one is unsandboxed (http://jsfiddle.net/AuJaX/3/), and the other is sandboxed (http://jsfiddle.net/V2dJc/1/). None of the console.log's ever get called. My manifest is below:
{
"manifest_version": 2,
"name": "__MSG_app_title__",
"description": "__MSG_app_description__",
"version": "0.1",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/content/content.js"]
}
],
"background": {
"scripts": ["js/back/background.js"],
"persistent": false
},
"permissions": [
"tabs",
"contextMenus"
],
"page_action": {
"default_title": "__MSG_app_title__",
"default_icon": {
"19": "images/icon-19.png"
}
},
"sandbox": {
"pages": ["sandboxed.html"]
},
"icons": { "48": "images/icon.png" },
"default_locale": "en"
}
Is there anything that I'm doing wrong, or is this something that's not supported (yet??)?
Did you whitelist the domain you are trying to use the extension on? Currently to have the Cast API injected into the page you need two things:
<html data-cast-api-enabled="true">
and you need to follow the steps at the bottom of this page (whitelisting in the extension, not the same as the Google Cast device whitelisting):
https://developers.google.com/cast/whitelisting#whitelist-chrome
That said, I doubt this is going to work. The instructions are for getting the Cast API injected into a regular web page. However, if I'm not mistaken you want the API injected into your Chrome extension page. I don't know if it will be made available there, since I don't think two different extensions are allowed to interact.

Getting error: "This webpage is not available" for my chrome app's options page

My CRX had the proper html page options.html in it, the manifest declares it properly (it shows up as a link on the chrome://extensions page) but when I click that link, Chrome gives the error:
This webpage is not available
The webpage at chrome-extension://invalid/ might be temporarily down or it may have moved permanently to a new web address.
It says "invalid" but the app runs perfectly well (all the content scripts run, the background created a database and saved to it). Why would it show as invalid? Why doesn't it have the extensions' id?
Here's the manifest:
{
"manifest_version": 2,
"name": "MyAPP",
"description": "My App",
"version": "0.0.0.32",
"minimum_chrome_version": "27",
"offline_enabled": true,
"options_page": "options.html",
"icons":
{
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
},
"app":
{
"background":
{
"scripts":
[
"scripts/background.js"
]
}
},
"permissions":
[
"unlimitedStorage",
"fullscreen",
{
"fileSystem":
[
"write"
]
},
"background",
"<all_urls>",
"tabs"
]
}
Does it need to be declared in "web_accessible_resources"? Any idea what's wrong?
Update
Adding to "web_accessible_resources" does not fix the issue. I added everything on that page too.
update 2
It looks like it might be a Chrome bug for packaged apps. When I remove the "app" section in the manifest, it works! This is a bug since the Chrome app documentation states that apps can have options pages: https://developer.chrome.com/apps/options.html
Options pages are only supported for extensions, you have indeed discovered a documentation bug (I've filed issue 255079).