Q: "chrome.permissions is not available" when requesting optional permissions for my extension I am building an extension that requires access to history to provide one of the features.
After publishing a version which contained the permission as mandatory and consequently losing a part of my users because they got scared away by the big alert saying that the extension might be able to snoop into their history (I really didn't plan on doing that), I decided to publish a version with the offending part removed and the permission disabled as a temporary fix.
I'd like to implement this feature back using optional permissions.
First of all, I added the new optional permission to my manifest file:
...

"permissions": [
  "https://news.ycombinator.com/",
  "http://news.ycombinator.com/"
],

"optional_permissions": [ "history" ],

...

Then, I built a function to request permissions into the script which handles the extension's settings:
Settings.prototype.applyPermissions = function (permissions, map) {
  Object.keys(permissions).forEach(function (key) {
    if (map[key]) {
      var checkbox = map[key].getElementsByTagName("input")[0];
      checkbox.addEventListener("change", function (e) {
        if (this.checked) {
          chrome.permissions.request(permissions[key], function(granted) {
            if (granted) {
              // Permission has been granted
            } else {
              // Not granted
            }
          });
        }
      });
    }
  });
};

The key part here is this:
checkbox.addEventListener("change", function (e) {
  if (this.checked) {
    chrome.permissions.request(permissions[key], function(granted) {
      if (granted) {
        // Permission has been granted
      } else {
        // Not granted
      }
    });
  }
});

I perform the request on an event caused by user interaction (the guide states that it won't work otherwise), and pass permissions[key], an object specified in my extension's settings which looks like this:
"permissions": {
    "mark_as_read": {
        "permissions": ["history"]
    }
}

When accessing it as permissions[key], I get this part:
{
    "permissions": ["history"]
}

Which is basically the format that the documentation shows for this kind of requests.

If I run this code and toggle the checkbox that should enable the feature, and look at the error log, I see this error:

chrome.permissions is not available: You do not have permission to
  access this API. Ensure that the required permission or manifest
  property is included in your manifest.json.

I also tried accessing this API from a background page, where it was actually available but I was not allowed to use because Chrome requires that you access it from a user interaction, and such interaction is lost if you send a message to the background page from your content script to request activation.
Am I missing something obvious here? Maybe I need to add something to the manifest, but I can't find any explicit documentation about it.

A: I assume you're trying to do this from a content script. You can't access most chrome.* APIs from content scripts, including chrome.permissions. However, you've correctly pointed out that a background page is also unsuitable, because you a permission change requires a direct user action.
Luckily, we have hardly exhausted our options. You could set the permission in:


*

*The extension's options page

*A browser action popup

*A page action popup

*Any page in your extension served through the chrome-extension:// scheme, provided you include the page and necessary sub-resources as web_accessible_resources in your manifest


In the last case, get the URL using chrome.extension.getURL. You could possibly use an iframe to inject it directly into the page, if you don't want the permission-requesting interface to be separate from the current page.
So, in fact, content scripts and background pages are the only two extension contexts where you can't use chrome.permissions.
