summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions
diff options
context:
space:
mode:
authorjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-27 14:36:49 +0000
committerjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-27 14:36:49 +0000
commit38383b194bc471ebba4de124cbf391b00114923a (patch)
treef7a027d2ea9f88f28216a29d0b9a0368e03ae502 /chrome/common/extensions
parent4d48dccadf757b39157537331a3becd13a5f7d9f (diff)
downloadchromium_src-38383b194bc471ebba4de124cbf391b00114923a.zip
chromium_src-38383b194bc471ebba4de124cbf391b00114923a.tar.gz
chromium_src-38383b194bc471ebba4de124cbf391b00114923a.tar.bz2
Add an experimental permissions API for extensions.
The permissions API lets extensions specify optional permissions in their manifest that they can request at run-time. It currently supports API permissions through a white-list. Host permissions will come later. BUG=48119, 70466, 84507 TEST=*Extension* Review URL: http://codereview.chromium.org/7432006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94288 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/extensions')
-rw-r--r--chrome/common/extensions/api/extension_api.json137
-rw-r--r--chrome/common/extensions/docs/experimental.html1
-rw-r--r--chrome/common/extensions/docs/experimental.permissions.html1784
-rw-r--r--chrome/common/extensions/docs/samples.json6
-rw-r--r--chrome/common/extensions/extension.cc345
-rw-r--r--chrome/common/extensions/extension.h94
-rw-r--r--chrome/common/extensions/extension_constants.cc1
-rw-r--r--chrome/common/extensions/extension_constants.h1
-rw-r--r--chrome/common/extensions/extension_messages.cc52
-rw-r--r--chrome/common/extensions/extension_messages.h28
-rw-r--r--chrome/common/extensions/extension_permission_set.cc87
-rw-r--r--chrome/common/extensions/extension_permission_set.h24
-rw-r--r--chrome/common/extensions/extension_permission_set_unittest.cc337
-rw-r--r--chrome/common/extensions/extension_unittest.cc4
-rw-r--r--chrome/common/extensions/url_pattern_set.cc28
-rw-r--r--chrome/common/extensions/url_pattern_set.h14
-rw-r--r--chrome/common/extensions/url_pattern_set_unittest.cc211
17 files changed, 2861 insertions, 293 deletions
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index f3f8559..3e032aa 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -1060,6 +1060,143 @@
]
},
{
+ "namespace": "experimental.permissions",
+ "types": [
+ {
+ "id": "Permissions",
+ "type": "object",
+ "properties": {
+ "permissions": {
+ "type": "array",
+ "items": {"type": "string"},
+ "optional": true,
+ "description": "List of named permissions (does not include hosts or origins)."
+ }
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "onAdded",
+ "type": "function",
+ "unprivileged": true,
+ "description": "Fired when the extension acquires new permissions.",
+ "parameters": [
+ {
+ "$ref": "Permissions",
+ "name": "permissions",
+ "description": "The newly acquired permissions."
+ }
+ ]
+ },
+ {
+ "name": "onRemoved",
+ "type": "function",
+ "unprivileged": true,
+ "description": "Fired when access to permissions has been removed from the extension.",
+ "parameters": [
+ {
+ "$ref": "Permissions",
+ "name": "permissions",
+ "description": "The permissions that have been removed."
+ }
+ ]
+ }
+ ],
+ "functions": [
+ {
+ "name": "getAll",
+ "type": "function",
+ "unprivileged": true,
+ "description": "Gets the extension's current set of permissions.",
+ "parameters": [
+ {
+ "name": "callback",
+ "type": "function",
+ "parameters": [
+ {
+ "name": "permissions",
+ "$ref": "Permissions",
+ "description": "The extension's active permissions."
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "contains",
+ "type": "function",
+ "unprivileged": true,
+ "description": "Checks if the extension has the specified permissions.",
+ "parameters": [
+ {
+ "name": "permissions",
+ "$ref": "Permissions"
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "parameters": [
+ {
+ "name": "result",
+ "type": "boolean",
+ "description": "True if the extension has the specified permissions."
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "request",
+ "type": "function",
+ "unprivileged": true,
+ "description": "Requests access to the specified permissions. These permissions must be defined in the optional_permissions field of the manifest.",
+ "parameters": [
+ {
+ "name": "permissions",
+ "$ref": "Permissions"
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": true,
+ "parameters": [
+ {
+ "name": "granted",
+ "type": "boolean",
+ "description": "True if the user granted the specified permissions."
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "remove",
+ "type": "function",
+ "unprivileged": true,
+ "description": "Removes access to the specified permissions.",
+ "parameters": [
+ {
+ "name": "permissions",
+ "$ref": "Permissions"
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": true,
+ "parameters": [
+ {
+ "name": "removed",
+ "type": "boolean",
+ "description": "True if the permissions were removed."
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
"namespace": "tabs",
"types": [
{
diff --git a/chrome/common/extensions/docs/experimental.html b/chrome/common/extensions/docs/experimental.html
index 49aa374..8c62aec 100644
--- a/chrome/common/extensions/docs/experimental.html
+++ b/chrome/common/extensions/docs/experimental.html
@@ -328,6 +328,7 @@ on the following experimental APIs:
<a href="experimental.devtools.panels.html">experimental.devtools.panels</a></li><li>
<a href="experimental.devtools.resources.html">experimental.devtools.resources</a></li><li>
<a href="experimental.infobars.html">experimental.infobars</a></li><li>
+ <a href="experimental.permissions.html">experimental.permissions</a></li><li>
<a href="experimental.processes.html">experimental.processes</a></li><li>
<a href="experimental.sidebar.html">experimental.sidebar</a></li><li>
<a href="experimental.webNavigation.html">experimental.webNavigation</a></li><li>
diff --git a/chrome/common/extensions/docs/experimental.permissions.html b/chrome/common/extensions/docs/experimental.permissions.html
new file mode 100644
index 0000000..b167ee9
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.permissions.html
@@ -0,0 +1,1784 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+ 1) The <head> information in this page is significant, should be uniform
+ across api docs and should be edited only with knowledge of the
+ templating mechanism.
+ 3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+ browser, it will be re-generated from the template, json schema and
+ authored overview content.
+ 4) The <body>.innerHTML is also generated by an offline step so that this
+ page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+ <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+ <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+ </script>
+ <script type="text/javascript" src="js/api_page_generator.js"></script>
+ <script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
+ <title>chrome.experimental.permissions - Google Chrome Extensions - Google Code</title></head>
+ <body> <div id="gc-container" class="labs">
+ <div id="devModeWarning">
+ You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+ </div>
+ <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+ <!-- In particular, sub-templates that recurse, must be used by allowing
+ jstemplate to make a copy of the template in this section which
+ are not operated on by way of the jsskip="true" -->
+ <div style="display:none">
+
+ <!-- VALUE -->
+ <div id="valueTemplate">
+ <dt>
+ <var>paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a> Type</a>
+ </span>
+ <span>
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd>
+ Description of this parameter from the json schema.
+ </dd>
+ <dd>
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd>
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd>
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd>
+ <div></div>
+ </dd>
+
+ </div> <!-- /VALUE -->
+
+ <div id="functionParametersTemplate">
+ <h5>Parameters</h5>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div> <!-- /SUBTEMPLATES -->
+
+ <a id="top"></a>
+ <div id="skipto">
+ <a href="#gc-pagecontent">Skip to page content</a>
+ <a href="#gc-toc">Skip to main navigation</a>
+ </div>
+ <!-- API HEADER -->
+ <table id="header" width="100%" cellspacing="0" border="0">
+ <tbody><tr>
+ <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+ <td valign="middle" width="100%" style="padding-left:0.6em;">
+ <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+ <div id="gsc-search-box">
+ <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+ <input type="hidden" name="ie" value="UTF-8">
+ <input type="text" name="q" value="" size="55">
+ <input class="gsc-search-button" type="submit" name="sa" value="Search">
+ <br>
+ <span class="greytext">e.g. "page action" or "tabs"</span>
+ </div>
+ </form>
+
+ <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+ <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+ </td>
+ </tr>
+ </tbody></table>
+
+ <div id="codesiteContent" class="">
+
+ <a id="gc-topnav-anchor"></a>
+ <div id="gc-topnav">
+ <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+ <ul id="home" class="gc-topnav-tabs">
+ <li id="home_link">
+ <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+ </li>
+ <li id="docs_link">
+ <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+ </li>
+ <li id="faq_link">
+ <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+ </li>
+ <li id="samples_link">
+ <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+ </li>
+ <li id="group_link">
+ <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+ </li>
+ </ul>
+ </div> <!-- end gc-topnav -->
+
+ <div class="g-section g-tpl-170">
+ <!-- SIDENAV -->
+ <div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li><a href="getstarted.html">Getting Started</a></li>
+ <li><a href="overview.html">Overview</a></li>
+ <li><a href="whats_new.html">What's New?</a></li>
+ <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+ <ul>
+ <li>Browser UI
+ <ul>
+ <li><a href="browserAction.html">Browser Actions</a></li>
+ <li><a href="contextMenus.html">Context Menus</a></li>
+ <li><a href="notifications.html">Desktop Notifications</a></li>
+ <li><a href="omnibox.html">Omnibox</a></li>
+ <li><a href="options.html">Options Pages</a></li>
+ <li><a href="override.html">Override Pages</a></li>
+ <li><a href="pageAction.html">Page Actions</a></li>
+ </ul>
+ </li>
+ <li>Browser Interaction
+ <ul>
+ <li><a href="bookmarks.html">Bookmarks</a></li>
+ <li><a href="cookies.html">Cookies</a></li>
+ <li><a href="events.html">Events</a></li>
+ <li><a href="history.html">History</a></li>
+ <li><a href="management.html">Management</a></li>
+ <li><a href="tabs.html">Tabs</a></li>
+ <li><a href="windows.html">Windows</a></li>
+ </ul>
+ </li>
+ <li>Implementation
+ <ul>
+ <li><a href="a11y.html">Accessibility</a></li>
+ <li><a href="background_pages.html">Background Pages</a></li>
+ <li><a href="content_scripts.html">Content Scripts</a></li>
+ <li><a href="xhr.html">Cross-Origin XHR</a></li>
+ <li><a href="idle.html">Idle</a></li>
+ <li><a href="i18n.html">Internationalization</a></li>
+ <li><a href="messaging.html">Message Passing</a></li>
+ <li><a href="npapi.html">NPAPI Plugins</a></li>
+ </ul>
+ </li>
+ <li>Finishing
+ <ul>
+ <li><a href="hosting.html">Hosting</a></li>
+ <li><a href="external_extensions.html">Other Deployment Options</a></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
+ <li><h2><a href="tutorials.html">Tutorials</a></h2>
+ <ul>
+ <li><a href="tut_debugging.html">Debugging</a></li>
+ <li><a href="tut_analytics.html">Google Analytics</a></li>
+ <li><a href="tut_oauth.html">OAuth</a></li>
+ </ul>
+ </li>
+ <li><h2>Reference</h2>
+ <ul>
+ <li>Formats
+ <ul>
+ <li><a href="manifest.html">Manifest Files</a></li>
+ <li><a href="match_patterns.html">Match Patterns</a></li>
+ </ul>
+ </li>
+ <li><a href="permission_warnings.html">Permission Warnings</a></li>
+ <li><a href="api_index.html">chrome.* APIs</a></li>
+ <li><a href="api_other.html">Other APIs</a></li>
+ </ul>
+ </li>
+ <li><h2><a href="samples.html">Samples</a></h2></li>
+ <div class="line"> </div>
+ <li><h2>More</h2>
+ <ul>
+ <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
+ <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
+ <li><a href="themes.html">Themes</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <script>
+ initToggles();
+ </script>
+
+ <div class="g-unit" id="gc-pagecontent">
+ <div id="pageTitle">
+ <h1 class="page_title">chrome.experimental.permissions</h1>
+ </div>
+ <!-- TABLE OF CONTENTS -->
+ <div id="toc">
+ <h2>Contents</h2>
+ <ol>
+ <li style="display: none; ">
+ <a>h2Name</a>
+ <ol>
+ <li>
+ <a>h3Name</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#apiReference">API reference: chrome.experimental.permissions</a>
+ <ol>
+ <li style="display: none; ">
+ <a href="#properties">Properties</a>
+ <ol>
+ <li>
+ <a href="#property-anchor">propertyName</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#global-methods">Methods</a>
+ <ol>
+ <li>
+ <a href="#method-contains">contains</a>
+ </li><li>
+ <a href="#method-getAll">getAll</a>
+ </li><li>
+ <a href="#method-remove">remove</a>
+ </li><li>
+ <a href="#method-request">request</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#global-events">Events</a>
+ <ol>
+ <li>
+ <a href="#event-onAdded">onAdded</a>
+ </li><li>
+ <a href="#event-onRemoved">onRemoved</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#types">Types</a>
+ <ol>
+ <li>
+ <a href="#type-Permissions">Permissions</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </div>
+ <!-- /TABLE OF CONTENTS -->
+
+ <!-- Standard content lead-in for experimental API pages -->
+ <p id="classSummary">
+ For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+ </p>
+
+ <!-- STATIC CONTENT PLACEHOLDER -->
+ <div id="static"></div>
+
+ <!-- API PAGE -->
+ <div class="apiPage">
+ <a name="apiReference"></a>
+ <h2>API reference: chrome.experimental.permissions</h2>
+
+ <!-- PROPERTIES -->
+ <div class="apiGroup" style="display: none; ">
+ <a name="properties"></a>
+ <h3 id="properties">Properties</h3>
+
+ <div>
+ <a></a>
+ <h4>getLastError</h4>
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.extension</span><span>lastError</span>
+ </div>
+ <div>
+ </div>
+ </div>
+
+ </div> <!-- /apiGroup -->
+
+ <!-- METHODS -->
+ <div id="methodsTemplate" class="apiGroup">
+ <a name="global-methods"></a>
+ <h3>Methods</h3>
+
+ <!-- iterates over all functions -->
+ <div class="apiItem">
+ <a name="method-contains"></a> <!-- method-anchor -->
+ <h4>contains</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.permissions.contains</span>(<span class="null"><span style="display: none; ">, </span><span>Permissions</span>
+ <var><span>permissions</span></var></span><span class="null"><span>, </span><span>function</span>
+ <var><span>callback</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Checks if the extension has the specified permissions.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>permissions</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.permissions.html#type-Permissions">Permissions</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p style="display: none; ">
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>boolean result</span>) <span class="subdued">{...}</span>;</pre>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>result</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>True if the extension has the specified permissions.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-getAll"></a> <!-- method-anchor -->
+ <h4>getAll</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.permissions.getAll</span>(<span class="null"><span style="display: none; ">, </span><span>function</span>
+ <var><span>callback</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Gets the extension's current set of permissions.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p style="display: none; ">
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Permissions permissions</span>) <span class="subdued">{...}</span>;</pre>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>permissions</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.permissions.html#type-Permissions">Permissions</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The extension's active permissions.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-remove"></a> <!-- method-anchor -->
+ <h4>remove</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.permissions.remove</span>(<span class="null"><span style="display: none; ">, </span><span>Permissions</span>
+ <var><span>permissions</span></var></span><span class="optional"><span>, </span><span>function</span>
+ <var><span>callback</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Removes access to the specified permissions.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>permissions</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.permissions.html#type-Permissions">Permissions</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p style="display: none; ">
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>boolean removed</span>) <span class="subdued">{...}</span>;</pre>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>removed</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>True if the permissions were removed.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-request"></a> <!-- method-anchor -->
+ <h4>request</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.permissions.request</span>(<span class="null"><span style="display: none; ">, </span><span>Permissions</span>
+ <var><span>permissions</span></var></span><span class="optional"><span>, </span><span>function</span>
+ <var><span>callback</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Requests access to the specified permissions. These permissions must be defined in the optional_permissions field of the manifest.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>permissions</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.permissions.html#type-Permissions">Permissions</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p style="display: none; ">
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>boolean granted</span>) <span class="subdued">{...}</span>;</pre>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>granted</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>True if the user granted the specified permissions.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- EVENTS -->
+ <div id="eventsTemplate" class="apiGroup">
+ <a name="global-events"></a>
+ <h3>Events</h3>
+ <!-- iterates over all events -->
+ <div class="apiItem">
+ <a name="event-onAdded"></a>
+ <h4>onAdded</h4>
+
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span class="subdued">chrome.experimental.permissions.</span><span>onAdded</span><span class="subdued">.addListener</span>(function(<span>Permissions permissions</span>) <span class="subdued">{...}</span><span></span>));
+ </div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Fired when the extension acquires new permissions.</p>
+
+ <!-- LISTENER PARAMETERS -->
+ <div>
+ <h4>Listener parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>permissions</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.permissions.html#type-Permissions">Permissions</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The newly acquired permissions.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- EXTRA PARAMETERS -->
+ <div style="display: none; ">
+ <h4>Extra parameters to addListener</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- LISTENER RETURN VALUE -->
+ <h4 style="display: none; ">Listener returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /description -->
+ </div><div class="apiItem">
+ <a name="event-onRemoved"></a>
+ <h4>onRemoved</h4>
+
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span class="subdued">chrome.experimental.permissions.</span><span>onRemoved</span><span class="subdued">.addListener</span>(function(<span>Permissions permissions</span>) <span class="subdued">{...}</span><span></span>));
+ </div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Fired when access to permissions has been removed from the extension.</p>
+
+ <!-- LISTENER PARAMETERS -->
+ <div>
+ <h4>Listener parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>permissions</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.permissions.html#type-Permissions">Permissions</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The permissions that have been removed.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- EXTRA PARAMETERS -->
+ <div style="display: none; ">
+ <h4>Extra parameters to addListener</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+
+ <!-- LISTENER RETURN VALUE -->
+ <h4 style="display: none; ">Listener returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /description -->
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- TYPES -->
+ <div class="apiGroup">
+ <a name="types"></a>
+ <h3 id="types">Types</h3>
+
+ <!-- iterates over all types -->
+ <div class="apiItem">
+ <a name="type-Permissions"></a>
+ <h4>Permissions</h4>
+
+ <div>
+ <dt>
+ <var style="display: none; ">paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>permissions</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span>
+ array of <span><span>
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span></span>
+ </span>
+ <span style="display: none; ">paramType</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>List of named permissions (does not include hosts or origins).</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ </div> <!-- /apiPage -->
+ </div> <!-- /gc-pagecontent -->
+ </div> <!-- /g-section -->
+ </div> <!-- /codesiteContent -->
+ <div id="gc-footer" --="">
+ <div class="text">
+ <p>
+ Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+ the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+ Attribution 3.0 License</a>, and code samples are licensed under the
+ <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+ </p>
+ <p>
+ ©2011 Google
+ </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+ // chrome doc tracking
+ try {
+ var engdocs = _gat._getTracker("YT-10763712-2");
+ engdocs._trackPageview();
+ } catch(err) {}
+
+ // code.google.com site-wide tracking
+ try {
+ _uacct="UA-18071-1";
+ _uanchor=1;
+ _uff=0;
+ urchinTracker();
+ }
+ catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+ </div>
+ </div> <!-- /gc-footer -->
+ </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/docs/samples.json b/chrome/common/extensions/docs/samples.json
index 862059d..56dbf21 100644
--- a/chrome/common/extensions/docs/samples.json
+++ b/chrome/common/extensions/docs/samples.json
@@ -51,6 +51,12 @@
"chrome.experimental.devtools.resources.onFinished": "experimental.devtools.resources.html#event-onFinished",
"chrome.experimental.devtools.resources.onNavigation": "experimental.devtools.resources.html#event-onNavigation",
"chrome.experimental.infobars.show": "experimental.infobars.html#method-show",
+ "chrome.experimental.permissions.contains": "experimental.permissions.html#method-contains",
+ "chrome.experimental.permissions.getAll": "experimental.permissions.html#method-getAll",
+ "chrome.experimental.permissions.onAdded": "experimental.permissions.html#event-onAdded",
+ "chrome.experimental.permissions.onRemoved": "experimental.permissions.html#event-onRemoved",
+ "chrome.experimental.permissions.remove": "experimental.permissions.html#method-remove",
+ "chrome.experimental.permissions.request": "experimental.permissions.html#method-request",
"chrome.experimental.processes.getProcessIdForTab": "experimental.processes.html#method-getProcessIdForTab",
"chrome.experimental.processes.onUpdated": "experimental.processes.html#event-onUpdated",
"chrome.experimental.sidebar.collapse": "experimental.sidebar.html#method-collapse",
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 111ed76..5488349 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -286,20 +286,6 @@ Extension::Location Extension::GetHigherPriorityLocation(
return (loc1_rank > loc2_rank ? loc1 : loc2 );
}
-ExtensionPermissionMessages Extension::GetPermissionMessages() const {
- if (IsTrustedId(id_))
- return ExtensionPermissionMessages();
- else
- return permission_set_->GetPermissionMessages();
-}
-
-std::vector<string16> Extension::GetPermissionMessageStrings() const {
- if (IsTrustedId(id_))
- return std::vector<string16>();
- else
- return permission_set_->GetWarningMessages();
-}
-
void Extension::OverrideLaunchUrl(const GURL& override_url) {
GURL new_url(override_url);
if (!new_url.is_valid()) {
@@ -1202,6 +1188,7 @@ bool Extension::EnsureNotHybridApp(const DictionaryValue* manifest,
if (!IsBaseCrxKey(*key) &&
*key != keys::kApp &&
*key != keys::kPermissions &&
+ *key != keys::kOptionalPermissions &&
*key != keys::kOptionsPage &&
*key != keys::kBackground) {
*error = ExtensionErrorUtils::FormatErrorMessage(
@@ -1385,13 +1372,16 @@ GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) {
bool Extension::InitFromValue(const DictionaryValue& source, int flags,
std::string* error) {
+ base::AutoLock auto_lock(runtime_data_lock_);
// When strict error checks are enabled, make URL pattern parsing strict.
URLPattern::ParseOption parse_strictness =
(flags & STRICT_ERROR_CHECKS ? URLPattern::ERROR_ON_PORTS
: URLPattern::IGNORE_PORTS);
// Initialize permissions with an empty, default permission set.
- permission_set_.reset(new ExtensionPermissionSet());
+ runtime_data_.SetActivePermissions(new ExtensionPermissionSet());
+ optional_permission_set_ = new ExtensionPermissionSet();
+ required_permission_set_ = new ExtensionPermissionSet();
if (source.HasKey(keys::kPublicKey)) {
std::string public_key_bytes;
@@ -1911,104 +1901,30 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags,
}
}
+ // Initialize the permissions (optional).
ExtensionAPIPermissionSet api_permissions;
URLPatternSet host_permissions;
+ if (!ParsePermissions(&source,
+ keys::kPermissions,
+ flags,
+ error,
+ &api_permissions,
+ &host_permissions)) {
+ return false;
+ }
- // Initialize the permissions (optional).
- if (source.HasKey(keys::kPermissions)) {
- ListValue* permissions = NULL;
- if (!source.GetList(keys::kPermissions, &permissions)) {
- *error = ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidPermissions, "");
- return false;
- }
-
- for (size_t i = 0; i < permissions->GetSize(); ++i) {
- std::string permission_str;
- if (!permissions->GetString(i, &permission_str)) {
- *error = ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidPermission, base::IntToString(i));
- return false;
- }
-
- ExtensionAPIPermission* permission =
- ExtensionPermissionsInfo::GetInstance()->GetByName(permission_str);
-
- // Only COMPONENT extensions can use private APIs.
- // TODO(asargent) - We want a more general purpose mechanism for this,
- // and better error messages. (http://crbug.com/54013)
- if (!IsComponentOnlyPermission(permission)
-#ifndef NDEBUG
- && !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kExposePrivateExtensionApi)
-#endif
- ) {
- continue;
- }
-
- if (web_extent().is_empty() || location() == Extension::COMPONENT) {
- // Check if it's a module permission. If so, enable that permission.
- if (permission != NULL) {
- // Only allow the experimental API permission if the command line
- // flag is present, or if the extension is a component of Chrome.
- if (IsDisallowedExperimentalPermission(permission->id()) &&
- location() != Extension::COMPONENT) {
- *error = errors::kExperimentalFlagRequired;
- return false;
- }
- api_permissions.insert(permission->id());
- continue;
- }
- } else {
- // Hosted apps only get access to a subset of the valid permissions.
- if (permission != NULL && permission->is_hosted_app()) {
- if (IsDisallowedExperimentalPermission(permission->id())) {
- *error = errors::kExperimentalFlagRequired;
- return false;
- }
- api_permissions.insert(permission->id());
- continue;
- }
- }
-
- // Check if it's a host pattern permission.
- URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ?
- URLPattern::SCHEME_ALL : kValidHostPermissionSchemes);
-
- URLPattern::ParseResult parse_result = pattern.Parse(permission_str,
- parse_strictness);
- if (parse_result == URLPattern::PARSE_SUCCESS) {
- if (!CanSpecifyHostPermission(pattern)) {
- *error = ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidPermissionScheme, base::IntToString(i));
- return false;
- }
-
- // The path component is not used for host permissions, so we force it
- // to match all paths.
- pattern.SetPath("/*");
-
- if (pattern.MatchesScheme(chrome::kFileScheme) &&
- !CanExecuteScriptEverywhere()) {
- wants_file_access_ = true;
- if (!(flags & ALLOW_FILE_ACCESS))
- pattern.SetValidSchemes(
- pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
- }
-
- host_permissions.AddPattern(pattern);
- }
-
- // If it's not a host permission, then it's probably an unknown API
- // permission. Do not throw an error so extensions can retain
- // backwards compatability (http://crbug.com/42742).
- // TODO(jstritar): We can improve error messages by adding better
- // validation of API permissions here.
- // TODO(skerner): Consider showing the reason |permission_str| is not
- // a valid URL pattern if it is almost valid. For example, if it has
- // a valid scheme, and failed to parse because it has a port, show an
- // error.
- }
+ // Initialize the optional permissions (optional).
+ ExtensionAPIPermissionSet optional_api_permissions;
+ URLPatternSet optional_host_permissions;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalExtensionApis) &&
+ !ParsePermissions(&source,
+ keys::kOptionalPermissions,
+ flags,
+ error,
+ &optional_api_permissions,
+ &optional_host_permissions)) {
+ return false;
}
// Initialize background url (optional).
@@ -2394,8 +2310,12 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags,
return false;
}
- permission_set_.reset(
- new ExtensionPermissionSet(this, api_permissions, host_permissions));
+ runtime_data_.SetActivePermissions(new ExtensionPermissionSet(
+ this, api_permissions, host_permissions));
+ required_permission_set_ = new ExtensionPermissionSet(
+ this, api_permissions, host_permissions);
+ optional_permission_set_ = new ExtensionPermissionSet(
+ optional_api_permissions, optional_host_permissions, URLPatternSet());
// Although |source| is passed in as a const, it's still possible to modify
// it. This is dangerous since the utility process re-uses |source| after
@@ -2573,6 +2493,118 @@ GURL Extension::GetIconURL(int size,
return GetResourceURL(path);
}
+bool Extension::ParsePermissions(const DictionaryValue* source,
+ const char* key,
+ int flags,
+ std::string* error,
+ ExtensionAPIPermissionSet* api_permissions,
+ URLPatternSet* host_permissions) {
+ if (source->HasKey(key)) {
+ // When strict error checks are enabled, make URL pattern parsing strict.
+ URLPattern::ParseOption parse_strictness =
+ (flags & STRICT_ERROR_CHECKS ? URLPattern::ERROR_ON_PORTS
+ : URLPattern::IGNORE_PORTS);
+ ListValue* permissions = NULL;
+ if (!source->GetList(key, &permissions)) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidPermissions, "");
+ return false;
+ }
+
+ for (size_t i = 0; i < permissions->GetSize(); ++i) {
+ std::string permission_str;
+ if (!permissions->GetString(i, &permission_str)) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidPermission, base::IntToString(i));
+ return false;
+ }
+
+ ExtensionAPIPermission* permission =
+ ExtensionPermissionsInfo::GetInstance()->GetByName(permission_str);
+
+ // Only COMPONENT extensions can use private APIs.
+ // TODO(asargent) - We want a more general purpose mechanism for this,
+ // and better error messages. (http://crbug.com/54013)
+ if (!IsComponentOnlyPermission(permission)
+#ifndef NDEBUG
+ && !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kExposePrivateExtensionApi)
+#endif
+ ) {
+ continue;
+ }
+
+ if (web_extent().is_empty() || location() == Extension::COMPONENT) {
+ // Check if it's a module permission. If so, enable that permission.
+ if (permission != NULL) {
+ // Only allow the experimental API permission if the command line
+ // flag is present, or if the extension is a component of Chrome.
+ if (IsDisallowedExperimentalPermission(permission->id()) &&
+ location() != Extension::COMPONENT) {
+ *error = errors::kExperimentalFlagRequired;
+ return false;
+ }
+ api_permissions->insert(permission->id());
+ continue;
+ }
+ } else {
+ // Hosted apps only get access to a subset of the valid permissions.
+ if (permission != NULL && permission->is_hosted_app()) {
+ if (IsDisallowedExperimentalPermission(permission->id())) {
+ *error = errors::kExperimentalFlagRequired;
+ return false;
+ }
+ api_permissions->insert(permission->id());
+ continue;
+ }
+ }
+
+ // Check if it's a host pattern permission.
+ URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ?
+ URLPattern::SCHEME_ALL : kValidHostPermissionSchemes);
+
+ URLPattern::ParseResult parse_result = pattern.Parse(permission_str,
+ parse_strictness);
+ if (parse_result == URLPattern::PARSE_SUCCESS) {
+ if (!CanSpecifyHostPermission(pattern)) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidPermissionScheme, base::IntToString(i));
+ return false;
+ }
+
+ // The path component is not used for host permissions, so we force it
+ // to match all paths.
+ pattern.SetPath("/*");
+
+ if (pattern.MatchesScheme(chrome::kFileScheme) &&
+ !CanExecuteScriptEverywhere()) {
+ wants_file_access_ = true;
+ if (!(flags & ALLOW_FILE_ACCESS))
+ pattern.SetValidSchemes(
+ pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
+ }
+
+ host_permissions->AddPattern(pattern);
+ }
+
+ // If it's not a host permission, then it's probably an unknown API
+ // permission. Do not throw an error so extensions can retain
+ // backwards compatability (http://crbug.com/42742).
+ // TODO(jstritar): We can improve error messages by adding better
+ // validation of API permissions here.
+ // TODO(skerner): Consider showing the reason |permission_str| is not
+ // a valid URL pattern if it is almost valid. For example, if it has
+ // a valid scheme, and failed to parse because it has a port, show an
+ // error.
+ }
+ }
+ return true;
+}
+
+bool Extension::CanSilentlyIncreasePermissions() const {
+ return location() != INTERNAL;
+}
+
bool Extension::CanSpecifyHostPermission(const URLPattern& pattern) const {
if (!pattern.match_all_urls() &&
pattern.MatchesScheme(chrome::kChromeUIScheme)) {
@@ -2588,24 +2620,68 @@ bool Extension::CanSpecifyHostPermission(const URLPattern& pattern) const {
bool Extension::HasAPIPermission(
ExtensionAPIPermission::ID permission) const {
- return permission_set()->HasAPIPermission(permission);
+ base::AutoLock auto_lock(runtime_data_lock_);
+ return runtime_data_.GetActivePermissions()->HasAPIPermission(permission);
}
bool Extension::HasAPIPermission(
const std::string& function_name) const {
- return permission_set()->HasAccessToFunction(function_name);
+ base::AutoLock auto_lock(runtime_data_lock_);
+ return runtime_data_.GetActivePermissions()->
+ HasAccessToFunction(function_name);
}
const URLPatternSet& Extension::GetEffectiveHostPermissions() const {
- return permission_set()->effective_hosts();
+ base::AutoLock auto_lock(runtime_data_lock_);
+ return runtime_data_.GetActivePermissions()->effective_hosts();
}
bool Extension::HasHostPermission(const GURL& url) const {
+ base::AutoLock auto_lock(runtime_data_lock_);
if (url.SchemeIs(chrome::kChromeUIScheme) &&
url.host() != chrome::kChromeUIFaviconHost &&
location() != Extension::COMPONENT)
return false;
- return permission_set()->HasExplicitAccessToOrigin(url);
+ return runtime_data_.GetActivePermissions()->
+ HasExplicitAccessToOrigin(url);
+}
+
+bool Extension::HasEffectiveAccessToAllHosts() const {
+ base::AutoLock auto_lock(runtime_data_lock_);
+ return runtime_data_.GetActivePermissions()->HasEffectiveAccessToAllHosts();
+}
+
+bool Extension::HasFullPermissions() const {
+ base::AutoLock auto_lock(runtime_data_lock_);
+ return runtime_data_.GetActivePermissions()->HasEffectiveFullAccess();
+}
+
+ExtensionPermissionMessages Extension::GetPermissionMessages() const {
+ base::AutoLock auto_lock(runtime_data_lock_);
+ if (IsTrustedId(id_))
+ return ExtensionPermissionMessages();
+ else
+ return runtime_data_.GetActivePermissions()->GetPermissionMessages();
+}
+
+std::vector<string16> Extension::GetPermissionMessageStrings() const {
+ base::AutoLock auto_lock(runtime_data_lock_);
+ if (IsTrustedId(id_))
+ return std::vector<string16>();
+ else
+ return runtime_data_.GetActivePermissions()->GetWarningMessages();
+}
+
+void Extension::SetActivePermissions(
+ const ExtensionPermissionSet* permissions) const {
+ base::AutoLock auto_lock(runtime_data_lock_);
+ runtime_data_.SetActivePermissions(permissions);
+}
+
+scoped_refptr<const ExtensionPermissionSet>
+ Extension::GetActivePermissions() const {
+ base::AutoLock auto_lock(runtime_data_lock_);
+ return runtime_data_.GetActivePermissions();
}
bool Extension::IsComponentOnlyPermission(
@@ -2637,6 +2713,7 @@ bool Extension::HasMultipleUISurfaces() const {
bool Extension::CanExecuteScriptOnPage(const GURL& page_url,
const UserScript* script,
std::string* error) const {
+ base::AutoLock auto_lock(runtime_data_lock_);
// The gallery is special-cased as a restricted URL for scripting to prevent
// access to special JS bindings we expose to the gallery (and avoid things
// like extensions removing the "report abuse" link).
@@ -2661,7 +2738,8 @@ bool Extension::CanExecuteScriptOnPage(const GURL& page_url,
// Otherwise, see if this extension has permission to execute script
// programmatically on pages.
- if (permission_set()->HasExplicitAccessToOrigin(page_url))
+ if (runtime_data_.GetActivePermissions()->HasExplicitAccessToOrigin(
+ page_url))
return true;
if (error) {
@@ -2672,14 +2750,6 @@ bool Extension::CanExecuteScriptOnPage(const GURL& page_url,
return false;
}
-bool Extension::HasEffectiveAccessToAllHosts() const {
- return permission_set_->HasEffectiveAccessToAllHosts();
-}
-
-bool Extension::HasFullPermissions() const {
- return permission_set_->HasEffectiveFullAccess();
-}
-
bool Extension::ShowConfigureContextMenus() const {
// Don't show context menu for component extensions. We might want to show
// options for component extension button but now there is no component
@@ -2767,11 +2837,26 @@ ExtensionInfo::ExtensionInfo(const DictionaryValue* manifest,
ExtensionInfo::~ExtensionInfo() {}
+Extension::RuntimeData::RuntimeData() {}
+Extension::RuntimeData::RuntimeData(const ExtensionPermissionSet* active)
+ : active_permissions_(active) {}
+Extension::RuntimeData::~RuntimeData() {}
+
+scoped_refptr<const ExtensionPermissionSet>
+ Extension::RuntimeData::GetActivePermissions() const {
+ return active_permissions_;
+}
+
+void Extension::RuntimeData::SetActivePermissions(
+ const ExtensionPermissionSet* active) {
+ active_permissions_ = active;
+}
+
UninstalledExtensionInfo::UninstalledExtensionInfo(
const Extension& extension)
: extension_id(extension.id()),
extension_api_permissions(
- extension.permission_set()->GetAPIsAsStrings()),
+ extension.GetActivePermissions()->GetAPIsAsStrings()),
extension_type(extension.GetType()),
update_url(extension.update_url()) {}
@@ -2784,3 +2869,11 @@ UnloadedExtensionInfo::UnloadedExtensionInfo(
: reason(reason),
already_disabled(false),
extension(extension) {}
+
+UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo(
+ const Extension* extension,
+ const ExtensionPermissionSet* permissions,
+ Reason reason)
+ : reason(reason),
+ extension(extension),
+ permissions(permissions) {}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index a2ee0e7..e46cba1 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -16,6 +16,7 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/extension_permission_set.h"
@@ -209,15 +210,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// its install source should be set to GetHigherPriorityLocation(A, B).
static Location GetHigherPriorityLocation(Location loc1, Location loc2);
- // Returns the full list of permission messages that this extension
- // should display at install time.
- ExtensionPermissionMessages GetPermissionMessages() const;
-
- // Returns the full list of permission messages that this extension
- // should display at install time. The messages are returned as strings
- // for convenience.
- std::vector<string16> GetPermissionMessageStrings() const;
-
// Icon sizes used by the extension system.
static const int kIconSizes[];
@@ -375,11 +367,25 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
static void SetScriptingWhitelist(const ScriptingWhitelist& whitelist);
static const ScriptingWhitelist* GetScriptingWhitelist();
+ // Parses the host and api permissions from the specified permission |key|
+ // in the manifest |source|.
+ bool ParsePermissions(const base::DictionaryValue* source,
+ const char* key,
+ int flags,
+ std::string* error,
+ ExtensionAPIPermissionSet* api_permissions,
+ URLPatternSet* host_permissions);
+
bool HasAPIPermission(ExtensionAPIPermission::ID permission) const;
bool HasAPIPermission(const std::string& function_name) const;
const URLPatternSet& GetEffectiveHostPermissions() const;
+ // Returns true if the extension can silently increase its permission level.
+ // Extensions that can silently increase permissions are installed through
+ // mechanisms that are implicitly trusted.
+ bool CanSilentlyIncreasePermissions() const;
+
// Whether or not the extension is allowed permission for a URL pattern from
// the manifest. http, https, and chrome://favicon/ is allowed for all
// extensions, while component extensions are allowed access to
@@ -400,6 +406,21 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// having an NPAPI plugin).
bool HasFullPermissions() const;
+ // Returns the full list of permission messages that this extension
+ // should display at install time.
+ ExtensionPermissionMessages GetPermissionMessages() const;
+
+ // Returns the full list of permission messages that this extension
+ // should display at install time. The messages are returned as strings
+ // for convenience.
+ std::vector<string16> GetPermissionMessageStrings() const;
+
+ // Sets the active |permissions|.
+ void SetActivePermissions(const ExtensionPermissionSet* permissions) const;
+
+ // Gets the extension's active permission set.
+ scoped_refptr<const ExtensionPermissionSet> GetActivePermissions() const;
+
// Whether context menu should be shown for page and browser actions.
bool ShowConfigureContextMenus() const;
@@ -494,8 +515,11 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
const GURL& options_url() const { return options_url_; }
const GURL& devtools_url() const { return devtools_url_; }
const std::vector<GURL>& toolstrips() const { return toolstrips_; }
- const ExtensionPermissionSet* permission_set() const {
- return permission_set_.get();
+ const ExtensionPermissionSet* optional_permission_set() const {
+ return optional_permission_set_.get();
+ }
+ const ExtensionPermissionSet* required_permission_set() const {
+ return required_permission_set_.get();
}
const GURL& update_url() const { return update_url_; }
const ExtensionIconSet& icons() const { return icons_; }
@@ -551,6 +575,20 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
typedef std::pair<FilePath, std::string> ImageCacheKey;
typedef std::map<ImageCacheKey, SkBitmap> ImageCache;
+ class RuntimeData {
+ public:
+ RuntimeData();
+ explicit RuntimeData(const ExtensionPermissionSet* active);
+ ~RuntimeData();
+
+ void SetActivePermissions(const ExtensionPermissionSet* active);
+ scoped_refptr<const ExtensionPermissionSet> GetActivePermissions() const;
+
+ private:
+ friend class base::RefCountedThreadSafe<RuntimeData>;
+ scoped_refptr<const ExtensionPermissionSet> active_permissions_;
+ };
+
// Normalize the path for use by the extension. On Windows, this will make
// sure the drive letter is uppercase.
static FilePath MaybeNormalizePath(const FilePath& path);
@@ -673,8 +711,15 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// Defines the set of URLs in the extension's web content.
URLPatternSet extent_;
- // The set of permissions that the extension effectively has access to.
- scoped_ptr<ExtensionPermissionSet> permission_set_;
+ // The extension runtime data.
+ mutable base::Lock runtime_data_lock_;
+ mutable RuntimeData runtime_data_;
+
+ // The set of permissions the extension can request at runtime.
+ scoped_refptr<const ExtensionPermissionSet> optional_permission_set_;
+
+ // The extension's required / default set of permissions.
+ scoped_refptr<const ExtensionPermissionSet> required_permission_set_;
// The icons for the extension.
ExtensionIconSet icons_;
@@ -870,4 +915,27 @@ struct UnloadedExtensionInfo {
UnloadedExtensionInfo(const Extension* extension, Reason reason);
};
+// The details sent for EXTENSION_PERMISSIONS_UPDATED notifications.
+struct UpdatedExtensionPermissionsInfo {
+ enum Reason {
+ ADDED, // The permissions were added to the extension.
+ REMOVED, // The permissions were removed from the extension.
+ };
+
+ Reason reason;
+
+ // The extension who's permissions have changed.
+ const Extension* extension;
+
+ // The permissions that have changed. For Reason::ADDED, this would contain
+ // only the permissions that have added, and for Reason::REMOVED, this would
+ // only contain the removed permissions.
+ const ExtensionPermissionSet* permissions;
+
+ UpdatedExtensionPermissionsInfo(
+ const Extension* extension,
+ const ExtensionPermissionSet* permissions,
+ Reason reason);
+};
+
#endif // CHROME_COMMON_EXTENSIONS_EXTENSION_H_
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index df532ad..a0eb53f 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -50,6 +50,7 @@ const char* kNaClModulesMIMEType = "mime_type";
const char* kNaClModulesPath = "path";
const char* kOmnibox = "omnibox";
const char* kOmniboxKeyword = "omnibox.keyword";
+const char* kOptionalPermissions = "optional_permissions";
const char* kOptionsPage = "options_page";
const char* kPageAction = "page_action";
const char* kPageActionDefaultIcon = "default_icon";
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index fe2c7bf..5c980e0f 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -55,6 +55,7 @@ namespace extension_manifest_keys {
extern const char* kName;
extern const char* kOmnibox;
extern const char* kOmniboxKeyword;
+ extern const char* kOptionalPermissions;
extern const char* kOptionsPage;
extern const char* kPageAction;
extern const char* kPageActionDefaultIcon;
diff --git a/chrome/common/extensions/extension_messages.cc b/chrome/common/extensions/extension_messages.cc
index b388234..fe88896 100644
--- a/chrome/common/extensions/extension_messages.cc
+++ b/chrome/common/extensions/extension_messages.cc
@@ -24,10 +24,14 @@ ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params(
}
ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params(
- const Extension* extension)
+ const Extension* extension,
+ const ExtensionPermissionSet* active)
: manifest(new DictionaryValue()),
location(extension->location()),
path(extension->path()),
+ apis(active->apis()),
+ explicit_hosts(active->explicit_hosts()),
+ scriptable_hosts(active->scriptable_hosts()),
id(extension->id()),
creation_flags(extension->creation_flags()) {
// As we need more bits of extension data in the renderer, add more keys to
@@ -65,6 +69,11 @@ scoped_refptr<Extension>
return extension;
}
+const ExtensionPermissionSet*
+ ExtensionMsg_Loaded_Params::GetActivePermissions() const {
+ return new ExtensionPermissionSet(apis, explicit_hosts, scriptable_hosts);
+}
+
namespace IPC {
template <>
@@ -101,8 +110,15 @@ bool ParamTraits<URLPattern>::Read(const Message* m, void** iter,
!ReadParam(m, iter, &spec))
return false;
+ // TODO(jstritar): We don't want the URLPattern to fail parsing when the
+ // scheme is invalid. Instead, the pattern should parse but it should not
+ // match the invalid patterns. We get around this by setting the valid
+ // schemes after parsing the pattern. Update these method calls once we can
+ // ignore scheme validation with URLPattern parse options. crbug.com/90544
+ p->SetValidSchemes(URLPattern::SCHEME_ALL);
+ URLPattern::ParseResult result = p->Parse(spec, URLPattern::IGNORE_PORTS);
p->SetValidSchemes(valid_schemes);
- return URLPattern::PARSE_SUCCESS == p->Parse(spec, URLPattern::IGNORE_PORTS);
+ return URLPattern::PARSE_SUCCESS == result;
}
void ParamTraits<URLPattern>::Log(const param_type& p, std::string* l) {
@@ -116,9 +132,7 @@ void ParamTraits<URLPatternSet>::Write(Message* m, const param_type& p) {
bool ParamTraits<URLPatternSet>::Read(const Message* m, void** iter,
param_type* p) {
std::set<URLPattern> patterns;
- bool success =
- ReadParam(m, iter, &patterns);
- if (!success)
+ if (!ReadParam(m, iter, &patterns))
return false;
for (std::set<URLPattern>::iterator i = patterns.begin();
@@ -131,12 +145,35 @@ void ParamTraits<URLPatternSet>::Log(const param_type& p, std::string* l) {
LogParam(p.patterns(), l);
}
+void ParamTraits<ExtensionAPIPermission::ID>::Write(
+ Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+}
+
+bool ParamTraits<ExtensionAPIPermission::ID>::Read(
+ const Message* m, void** iter, param_type* p) {
+ int api_id = -2;
+ if (!ReadParam(m, iter, &api_id))
+ return false;
+
+ *p = static_cast<ExtensionAPIPermission::ID>(api_id);
+ return true;
+}
+
+void ParamTraits<ExtensionAPIPermission::ID>::Log(
+ const param_type& p, std::string* l) {
+ LogParam(static_cast<int>(p), l);
+}
+
void ParamTraits<ExtensionMsg_Loaded_Params>::Write(Message* m,
const param_type& p) {
WriteParam(m, p.location);
WriteParam(m, p.path);
WriteParam(m, *(p.manifest));
WriteParam(m, p.creation_flags);
+ WriteParam(m, p.apis);
+ WriteParam(m, p.explicit_hosts);
+ WriteParam(m, p.scriptable_hosts);
}
bool ParamTraits<ExtensionMsg_Loaded_Params>::Read(const Message* m,
@@ -146,7 +183,10 @@ bool ParamTraits<ExtensionMsg_Loaded_Params>::Read(const Message* m,
return ReadParam(m, iter, &p->location) &&
ReadParam(m, iter, &p->path) &&
ReadParam(m, iter, p->manifest.get()) &&
- ReadParam(m, iter, &p->creation_flags);
+ ReadParam(m, iter, &p->creation_flags) &&
+ ReadParam(m, iter, &p->apis) &&
+ ReadParam(m, iter, &p->explicit_hosts) &&
+ ReadParam(m, iter, &p->scriptable_hosts);
}
void ParamTraits<ExtensionMsg_Loaded_Params>::Log(const param_type& p,
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index 53abba6..6d41b9c 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -8,6 +8,7 @@
#include "base/shared_memory.h"
#include "base/values.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_permission_set.h"
#include "chrome/common/extensions/url_pattern.h"
#include "chrome/common/extensions/url_pattern_set.h"
#include "chrome/common/web_apps.h"
@@ -90,7 +91,9 @@ typedef std::map<std::string, std::string> SubstitutionMap;
struct ExtensionMsg_Loaded_Params {
ExtensionMsg_Loaded_Params();
~ExtensionMsg_Loaded_Params();
- explicit ExtensionMsg_Loaded_Params(const Extension* extension);
+ explicit ExtensionMsg_Loaded_Params(
+ const Extension* extension,
+ const ExtensionPermissionSet* active_permissions);
// A copy constructor is needed because this structure can end up getting
// copied inside the IPC machinery on gcc <= 4.2.
@@ -99,6 +102,9 @@ struct ExtensionMsg_Loaded_Params {
// Creates a new extension from the data in this object.
scoped_refptr<Extension> ConvertToExtension() const;
+ // Passes ownership to the caller.
+ const ExtensionPermissionSet* GetActivePermissions() const;
+
// The subset of the extension manifest data we send to renderers.
scoped_ptr<DictionaryValue> manifest;
@@ -109,6 +115,11 @@ struct ExtensionMsg_Loaded_Params {
// to generate the extension ID for extensions that are loaded unpacked.
FilePath path;
+ // The extension's current active permissions.
+ ExtensionAPIPermissionSet apis;
+ URLPatternSet explicit_hosts;
+ URLPatternSet scriptable_hosts;
+
// We keep this separate so that it can be used in logging.
std::string id;
@@ -135,6 +146,14 @@ struct ParamTraits<URLPatternSet> {
};
template <>
+struct ParamTraits<ExtensionAPIPermission::ID> {
+ typedef ExtensionAPIPermission::ID param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
struct ParamTraits<ExtensionMsg_Loaded_Params> {
typedef ExtensionMsg_Loaded_Params param_type;
static void Write(Message* m, const param_type& p);
@@ -214,6 +233,13 @@ IPC_MESSAGE_ROUTED1(ExtensionMsg_GetApplicationInfo,
IPC_MESSAGE_ROUTED1(ExtensionMsg_UpdateBrowserWindowId,
int /* id of browser window */)
+// Tell the renderer to update an extension's permission set.
+IPC_MESSAGE_CONTROL4(ExtensionMsg_UpdatePermissions,
+ std::string /* extension_id*/,
+ ExtensionAPIPermissionSet,
+ URLPatternSet,
+ URLPatternSet)
+
// Tell the renderer which type this view is.
IPC_MESSAGE_ROUTED1(ExtensionMsg_NotifyRenderViewType,
ViewType::Type /* view_type */)
diff --git a/chrome/common/extensions/extension_permission_set.cc b/chrome/common/extensions/extension_permission_set.cc
index 0fbf2cd..462e022 100644
--- a/chrome/common/extensions/extension_permission_set.cc
+++ b/chrome/common/extensions/extension_permission_set.cc
@@ -247,6 +247,9 @@ ExtensionPermissionsInfo::ExtensionPermissionsInfo()
RegisterHostedAppPermission(
ExtensionAPIPermission::kUnlimitedStorage, "unlimitedStorage", 0,
ExtensionPermissionMessage::kNone);
+ RegisterHostedAppPermission(
+ ExtensionAPIPermission::kPermissions, "permissions", 0,
+ ExtensionPermissionMessage::kNone);
// Hosted app and private permissions.
RegisterPermission(
@@ -433,12 +436,62 @@ ExtensionPermissionSet::~ExtensionPermissionSet() {
}
// static
+ExtensionPermissionSet* ExtensionPermissionSet::CreateDifference(
+ const ExtensionPermissionSet* set1,
+ const ExtensionPermissionSet* set2) {
+ scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
+ const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
+ const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
+
+ ExtensionAPIPermissionSet apis;
+ std::set_difference(set1_safe->apis().begin(), set1_safe->apis().end(),
+ set2_safe->apis().begin(), set2_safe->apis().end(),
+ std::insert_iterator<ExtensionAPIPermissionSet>(
+ apis, apis.begin()));
+
+ URLPatternSet explicit_hosts;
+ URLPatternSet::CreateDifference(set1_safe->explicit_hosts(),
+ set2_safe->explicit_hosts(),
+ &explicit_hosts);
+
+ URLPatternSet scriptable_hosts;
+ URLPatternSet::CreateDifference(set1_safe->scriptable_hosts(),
+ set2_safe->scriptable_hosts(),
+ &scriptable_hosts);
+ return new ExtensionPermissionSet(apis, explicit_hosts, scriptable_hosts);
+}
+
+// static
+ExtensionPermissionSet* ExtensionPermissionSet::CreateIntersection(
+ const ExtensionPermissionSet* set1,
+ const ExtensionPermissionSet* set2) {
+ scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
+ const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
+ const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
+
+ ExtensionAPIPermissionSet apis;
+ std::set_intersection(set1_safe->apis().begin(), set1_safe->apis().end(),
+ set2_safe->apis().begin(), set2_safe->apis().end(),
+ std::insert_iterator<ExtensionAPIPermissionSet>(
+ apis, apis.begin()));
+ URLPatternSet explicit_hosts;
+ URLPatternSet::CreateIntersection(set1_safe->explicit_hosts(),
+ set2_safe->explicit_hosts(),
+ &explicit_hosts);
+
+ URLPatternSet scriptable_hosts;
+ URLPatternSet::CreateIntersection(set1_safe->scriptable_hosts(),
+ set2_safe->scriptable_hosts(),
+ &scriptable_hosts);
+ return new ExtensionPermissionSet(apis, explicit_hosts, scriptable_hosts);
+}
+// static
ExtensionPermissionSet* ExtensionPermissionSet::CreateUnion(
const ExtensionPermissionSet* set1,
const ExtensionPermissionSet* set2) {
- ExtensionPermissionSet empty;
- const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? &empty : set1;
- const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? &empty : set2;
+ scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
+ const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
+ const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
ExtensionAPIPermissionSet apis;
std::set_union(set1_safe->apis().begin(), set1_safe->apis().end(),
@@ -447,10 +500,11 @@ ExtensionPermissionSet* ExtensionPermissionSet::CreateUnion(
apis, apis.begin()));
URLPatternSet explicit_hosts;
- URLPatternSet scriptable_hosts;
URLPatternSet::CreateUnion(set1_safe->explicit_hosts(),
set2_safe->explicit_hosts(),
&explicit_hosts);
+
+ URLPatternSet scriptable_hosts;
URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(),
set2_safe->scriptable_hosts(),
&scriptable_hosts);
@@ -458,6 +512,31 @@ ExtensionPermissionSet* ExtensionPermissionSet::CreateUnion(
return new ExtensionPermissionSet(apis, explicit_hosts, scriptable_hosts);
}
+bool ExtensionPermissionSet::operator==(
+ const ExtensionPermissionSet& rhs) const {
+ return apis_ == rhs.apis_ &&
+ scriptable_hosts_ == rhs.scriptable_hosts_ &&
+ explicit_hosts_ == rhs.explicit_hosts_;
+}
+
+bool ExtensionPermissionSet::Contains(const ExtensionPermissionSet& set) const {
+ // Every set includes the empty set.
+ if (set.IsEmpty())
+ return true;
+
+ if (!std::includes(apis_.begin(), apis_.end(),
+ set.apis().begin(), set.apis().end()))
+ return false;
+
+ if (!explicit_hosts().Contains(set.explicit_hosts()))
+ return false;
+
+ if (!scriptable_hosts().Contains(set.scriptable_hosts()))
+ return false;
+
+ return true;
+}
+
std::set<std::string> ExtensionPermissionSet::GetAPIsAsStrings() const {
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
std::set<std::string> apis_str;
diff --git a/chrome/common/extensions/extension_permission_set.h b/chrome/common/extensions/extension_permission_set.h
index c9a67e9..3d4d353 100644
--- a/chrome/common/extensions/extension_permission_set.h
+++ b/chrome/common/extensions/extension_permission_set.h
@@ -13,6 +13,7 @@
#include "base/gtest_prod_util.h"
#include "base/memory/singleton.h"
+#include "base/memory/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/string16.h"
#include "chrome/common/extensions/url_pattern_set.h"
@@ -121,6 +122,7 @@ class ExtensionAPIPermission {
kWebstorePrivate,
kDevtools,
kPlugin,
+ kPermissions,
kEnumBoundary
};
@@ -266,7 +268,8 @@ class ExtensionPermissionsInfo {
// The ExtensionPermissionSet is an immutable class that encapsulates an
// extension's permissions. The class exposes set operations for combining and
// manipulating the permissions.
-class ExtensionPermissionSet {
+class ExtensionPermissionSet
+ : public base::RefCountedThreadSafe<ExtensionPermissionSet> {
public:
// Creates an empty permission set (e.g. default permissions).
ExtensionPermissionSet();
@@ -286,11 +289,26 @@ class ExtensionPermissionSet {
~ExtensionPermissionSet();
+ // Creates a new permission set equal to |set1| - |set2|, passing ownership of
+ // the new set to the caller.
+ static ExtensionPermissionSet* CreateDifference(
+ const ExtensionPermissionSet* set1, const ExtensionPermissionSet* set2);
+
+ // Creates a new permission set equal to the intersection of |set1| and
+ // |set2|, passing ownership of the new set to the caller.
+ static ExtensionPermissionSet* CreateIntersection(
+ const ExtensionPermissionSet* set1, const ExtensionPermissionSet* set2);
+
// Creates a new permission set equal to the union of |set1| and |set2|.
// Passes ownership of the new set to the caller.
static ExtensionPermissionSet* CreateUnion(
const ExtensionPermissionSet* set1, const ExtensionPermissionSet* set2);
+ bool operator==(const ExtensionPermissionSet& rhs) const;
+
+ // Returns true if |set| is a subset of this.
+ bool Contains(const ExtensionPermissionSet& set) const;
+
// Gets the API permissions in this set as a set of strings.
std::set<std::string> GetAPIsAsStrings() const;
@@ -353,6 +371,8 @@ class ExtensionPermissionSet {
FRIEND_TEST_ALL_PREFIXES(ExtensionPermissionSetTest,
HasLessHostPrivilegesThan);
+ friend class base::RefCountedThreadSafe<ExtensionPermissionSet>;
+
static std::set<std::string> GetDistinctHosts(
const URLPatternSet& host_patterns, bool include_rcd);
@@ -380,9 +400,11 @@ class ExtensionPermissionSet {
ExtensionAPIPermissionSet apis_;
// The list of hosts that can be accessed directly from the extension.
+ // TODO(jstritar): Rename to "hosts_"?
URLPatternSet explicit_hosts_;
// The list of hosts that can be scripted by content scripts.
+ // TODO(jstritar): Rename to "user_script_hosts_"?
URLPatternSet scriptable_hosts_;
// The list of hosts this effectively grants access to.
diff --git a/chrome/common/extensions/extension_permission_set_unittest.cc b/chrome/common/extensions/extension_permission_set_unittest.cc
index b1a08a3..7bba33a 100644
--- a/chrome/common/extensions/extension_permission_set_unittest.cc
+++ b/chrome/common/extensions/extension_permission_set_unittest.cc
@@ -152,6 +152,7 @@ TEST(ExtensionAPIPermissionTest, HostedAppPermissions) {
hosted_perms.insert(ExtensionAPIPermission::kNotification);
hosted_perms.insert(ExtensionAPIPermission::kUnlimitedStorage);
hosted_perms.insert(ExtensionAPIPermission::kWebstorePrivate);
+ hosted_perms.insert(ExtensionAPIPermission::kPermissions);
ExtensionAPIPermissionSet perms = info->GetAll();
size_t count = 0;
@@ -161,8 +162,8 @@ TEST(ExtensionAPIPermissionTest, HostedAppPermissions) {
EXPECT_EQ(hosted_perms.count(*i) > 0, info->GetByID(*i)->is_hosted_app());
}
- EXPECT_EQ(10u, count);
- EXPECT_EQ(10u, info->get_hosted_app_permission_count());
+ EXPECT_EQ(hosted_perms.size(), count);
+ EXPECT_EQ(hosted_perms.size(), info->get_hosted_app_permission_count());
}
TEST(ExtensionAPIPermissionTest, ComponentOnlyPermissions) {
@@ -188,17 +189,17 @@ TEST(ExtensionAPIPermissionTest, ComponentOnlyPermissions) {
TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
scoped_refptr<Extension> extension;
- const ExtensionPermissionSet* permissions = NULL;
+ scoped_refptr<const ExtensionPermissionSet> permissions;
extension = LoadManifest("effective_host_permissions", "empty.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_EQ(0u, extension->GetEffectiveHostPermissions().patterns().size());
EXPECT_FALSE(permissions->HasEffectiveAccessToURL(
GURL("http://www.google.com")));
EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
extension = LoadManifest("effective_host_permissions", "one_host.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
GURL("http://www.google.com")));
EXPECT_FALSE(permissions->HasEffectiveAccessToURL(
@@ -207,14 +208,14 @@ TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
extension = LoadManifest("effective_host_permissions",
"one_host_wildcard.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
GURL("http://foo.google.com")));
EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
extension = LoadManifest("effective_host_permissions", "two_hosts.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
GURL("http://www.google.com")));
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
@@ -223,14 +224,14 @@ TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
extension = LoadManifest("effective_host_permissions",
"https_not_considered.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://google.com")));
EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
extension = LoadManifest("effective_host_permissions",
"two_content_scripts.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
GURL("http://www.reddit.com")));
@@ -239,7 +240,7 @@ TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
extension = LoadManifest("effective_host_permissions", "all_hosts.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("https://test/")));
EXPECT_TRUE(
@@ -247,14 +248,14 @@ TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
extension = LoadManifest("effective_host_permissions", "all_hosts2.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
EXPECT_TRUE(
permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
extension = LoadManifest("effective_host_permissions", "all_hosts3.json");
- permissions = extension->permission_set();
+ permissions = extension->GetActivePermissions();
EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://test/")));
EXPECT_TRUE(
@@ -271,16 +272,17 @@ TEST(ExtensionPermissionSetTest, ExplicitAccessToOrigin) {
// The explicit host paths should get set to /*.
AddPattern(&explicit_hosts, "http://www.example.com/a/particular/path/*");
- ExtensionPermissionSet perm_set(apis, explicit_hosts, scriptable_hosts);
- ASSERT_TRUE(perm_set.HasExplicitAccessToOrigin(
+ scoped_refptr<ExtensionPermissionSet> perm_set = new ExtensionPermissionSet(
+ apis, explicit_hosts, scriptable_hosts);
+ ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin(
GURL("http://www.google.com/")));
- ASSERT_TRUE(perm_set.HasExplicitAccessToOrigin(
+ ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin(
GURL("http://test.google.com/")));
- ASSERT_TRUE(perm_set.HasExplicitAccessToOrigin(
+ ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin(
GURL("http://www.example.com")));
- ASSERT_TRUE(perm_set.HasEffectiveAccessToURL(
+ ASSERT_TRUE(perm_set->HasEffectiveAccessToURL(
GURL("http://www.example.com")));
- ASSERT_FALSE(perm_set.HasExplicitAccessToOrigin(
+ ASSERT_FALSE(perm_set->HasExplicitAccessToOrigin(
GURL("http://test.example.com")));
}
@@ -299,9 +301,9 @@ TEST(ExtensionPermissionSetTest, CreateUnion) {
URLPatternSet effective_hosts;
- scoped_ptr<ExtensionPermissionSet> set1;
- scoped_ptr<ExtensionPermissionSet> set2;
- scoped_ptr<ExtensionPermissionSet> union_set;
+ scoped_refptr<ExtensionPermissionSet> set1;
+ scoped_refptr<ExtensionPermissionSet> set2;
+ scoped_refptr<ExtensionPermissionSet> union_set;
// Union with an empty set.
apis1.insert(ExtensionAPIPermission::kTab);
@@ -313,11 +315,15 @@ TEST(ExtensionPermissionSetTest, CreateUnion) {
AddPattern(&expected_explicit_hosts, "http://*.google.com/*");
AddPattern(&effective_hosts, "http://*.google.com/*");
- set1.reset(new ExtensionPermissionSet(
- apis1, explicit_hosts1, scriptable_hosts1));
- set2.reset(new ExtensionPermissionSet(
- apis2, explicit_hosts2, scriptable_hosts2));
- union_set.reset(ExtensionPermissionSet::CreateUnion(set1.get(), set2.get()));
+ set1 = new ExtensionPermissionSet(apis1, explicit_hosts1, scriptable_hosts1);
+ set2 = new ExtensionPermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
+ union_set = ExtensionPermissionSet::CreateUnion(set1.get(), set2.get());
+ EXPECT_TRUE(set1->Contains(*set2));
+ EXPECT_TRUE(set1->Contains(*union_set));
+ EXPECT_FALSE(set2->Contains(*set1));
+ EXPECT_FALSE(set2->Contains(*union_set));
+ EXPECT_TRUE(union_set->Contains(*set1));
+ EXPECT_TRUE(union_set->Contains(*set2));
EXPECT_FALSE(union_set->HasEffectiveFullAccess());
EXPECT_EQ(expected_apis, union_set->apis());
@@ -343,9 +349,16 @@ TEST(ExtensionPermissionSetTest, CreateUnion) {
effective_hosts.ClearPatterns();
AddPattern(&effective_hosts, "<all_urls>");
- set2.reset(new ExtensionPermissionSet(
- apis2, explicit_hosts2, scriptable_hosts2));
- union_set.reset(ExtensionPermissionSet::CreateUnion(set1.get(), set2.get()));
+ set2 = new ExtensionPermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
+ union_set = ExtensionPermissionSet::CreateUnion(set1.get(), set2.get());
+
+ EXPECT_FALSE(set1->Contains(*set2));
+ EXPECT_FALSE(set1->Contains(*union_set));
+ EXPECT_FALSE(set2->Contains(*set1));
+ EXPECT_FALSE(set2->Contains(*union_set));
+ EXPECT_TRUE(union_set->Contains(*set1));
+ EXPECT_TRUE(union_set->Contains(*set2));
+
EXPECT_TRUE(union_set->HasEffectiveFullAccess());
EXPECT_TRUE(union_set->HasEffectiveAccessToAllHosts());
EXPECT_EQ(expected_apis, union_set->apis());
@@ -354,6 +367,146 @@ TEST(ExtensionPermissionSetTest, CreateUnion) {
EXPECT_EQ(effective_hosts, union_set->effective_hosts());
}
+TEST(ExtensionPermissionSetTest, CreateIntersection) {
+ ExtensionAPIPermissionSet apis1;
+ ExtensionAPIPermissionSet apis2;
+ ExtensionAPIPermissionSet expected_apis;
+
+ URLPatternSet explicit_hosts1;
+ URLPatternSet explicit_hosts2;
+ URLPatternSet expected_explicit_hosts;
+
+ URLPatternSet scriptable_hosts1;
+ URLPatternSet scriptable_hosts2;
+ URLPatternSet expected_scriptable_hosts;
+
+ URLPatternSet effective_hosts;
+
+ scoped_refptr<ExtensionPermissionSet> set1;
+ scoped_refptr<ExtensionPermissionSet> set2;
+ scoped_refptr<ExtensionPermissionSet> new_set;
+
+ // Intersection with an empty set.
+ apis1.insert(ExtensionAPIPermission::kTab);
+ apis1.insert(ExtensionAPIPermission::kBackground);
+
+ AddPattern(&explicit_hosts1, "http://*.google.com/*");
+ AddPattern(&scriptable_hosts1, "http://www.reddit.com/*");
+
+ set1 = new ExtensionPermissionSet(apis1, explicit_hosts1, scriptable_hosts1);
+ set2 = new ExtensionPermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
+ new_set = ExtensionPermissionSet::CreateIntersection(set1.get(), set2.get());
+ EXPECT_TRUE(set1->Contains(*new_set));
+ EXPECT_TRUE(set2->Contains(*new_set));
+ EXPECT_TRUE(set1->Contains(*set2));
+ EXPECT_FALSE(set2->Contains(*set1));
+ EXPECT_FALSE(new_set->Contains(*set1));
+ EXPECT_TRUE(new_set->Contains(*set2));
+
+ EXPECT_TRUE(new_set->IsEmpty());
+ EXPECT_FALSE(new_set->HasEffectiveFullAccess());
+ EXPECT_EQ(expected_apis, new_set->apis());
+ EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts());
+ EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts());
+ EXPECT_EQ(expected_explicit_hosts, new_set->effective_hosts());
+
+ // Now use a real second set.
+ apis2.insert(ExtensionAPIPermission::kTab);
+ apis2.insert(ExtensionAPIPermission::kProxy);
+ apis2.insert(ExtensionAPIPermission::kClipboardWrite);
+ apis2.insert(ExtensionAPIPermission::kPlugin);
+ expected_apis.insert(ExtensionAPIPermission::kTab);
+
+ AddPattern(&explicit_hosts2, "http://*.example.com/*");
+ AddPattern(&explicit_hosts2, "http://*.google.com/*");
+ AddPattern(&scriptable_hosts2, "http://*.google.com/*");
+ AddPattern(&expected_explicit_hosts, "http://*.google.com/*");
+
+ effective_hosts.ClearPatterns();
+ AddPattern(&effective_hosts, "http://*.google.com/*");
+
+ set2 = new ExtensionPermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
+ new_set = ExtensionPermissionSet::CreateIntersection(set1.get(), set2.get());
+
+ EXPECT_TRUE(set1->Contains(*new_set));
+ EXPECT_TRUE(set2->Contains(*new_set));
+ EXPECT_FALSE(set1->Contains(*set2));
+ EXPECT_FALSE(set2->Contains(*set1));
+ EXPECT_FALSE(new_set->Contains(*set1));
+ EXPECT_FALSE(new_set->Contains(*set2));
+
+ EXPECT_FALSE(new_set->HasEffectiveFullAccess());
+ EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts());
+ EXPECT_EQ(expected_apis, new_set->apis());
+ EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts());
+ EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts());
+ EXPECT_EQ(effective_hosts, new_set->effective_hosts());
+}
+
+TEST(ExtensionPermissionSetTest, CreateDifference) {
+ ExtensionAPIPermissionSet apis1;
+ ExtensionAPIPermissionSet apis2;
+ ExtensionAPIPermissionSet expected_apis;
+
+ URLPatternSet explicit_hosts1;
+ URLPatternSet explicit_hosts2;
+ URLPatternSet expected_explicit_hosts;
+
+ URLPatternSet scriptable_hosts1;
+ URLPatternSet scriptable_hosts2;
+ URLPatternSet expected_scriptable_hosts;
+
+ URLPatternSet effective_hosts;
+
+ scoped_refptr<ExtensionPermissionSet> set1;
+ scoped_refptr<ExtensionPermissionSet> set2;
+ scoped_refptr<ExtensionPermissionSet> new_set;
+
+ // Difference with an empty set.
+ apis1.insert(ExtensionAPIPermission::kTab);
+ apis1.insert(ExtensionAPIPermission::kBackground);
+
+ AddPattern(&explicit_hosts1, "http://*.google.com/*");
+ AddPattern(&scriptable_hosts1, "http://www.reddit.com/*");
+
+ set1 = new ExtensionPermissionSet(apis1, explicit_hosts1, scriptable_hosts1);
+ set2 = new ExtensionPermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
+ new_set = ExtensionPermissionSet::CreateDifference(set1.get(), set2.get());
+ EXPECT_EQ(*set1, *new_set);
+
+ // Now use a real second set.
+ apis2.insert(ExtensionAPIPermission::kTab);
+ apis2.insert(ExtensionAPIPermission::kProxy);
+ apis2.insert(ExtensionAPIPermission::kClipboardWrite);
+ apis2.insert(ExtensionAPIPermission::kPlugin);
+ expected_apis.insert(ExtensionAPIPermission::kBackground);
+
+ AddPattern(&explicit_hosts2, "http://*.example.com/*");
+ AddPattern(&explicit_hosts2, "http://*.google.com/*");
+ AddPattern(&scriptable_hosts2, "http://*.google.com/*");
+ AddPattern(&expected_scriptable_hosts, "http://www.reddit.com/*");
+
+ effective_hosts.ClearPatterns();
+ AddPattern(&effective_hosts, "http://www.reddit.com/*");
+
+ set2 = new ExtensionPermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
+ new_set = ExtensionPermissionSet::CreateDifference(set1.get(), set2.get());
+
+ EXPECT_TRUE(set1->Contains(*new_set));
+ EXPECT_FALSE(set2->Contains(*new_set));
+
+ EXPECT_FALSE(new_set->HasEffectiveFullAccess());
+ EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts());
+ EXPECT_EQ(expected_apis, new_set->apis());
+ EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts());
+ EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts());
+ EXPECT_EQ(effective_hosts, new_set->effective_hosts());
+
+ // |set3| = |set1| - |set2| --> |set3| intersect |set2| == empty_set
+ set1 = ExtensionPermissionSet::CreateIntersection(new_set.get(), set2.get());
+ EXPECT_TRUE(set1->IsEmpty());
+}
+
TEST(ExtensionPermissionSetTest, HasLessPrivilegesThan) {
const struct {
const char* base_name;
@@ -435,11 +588,13 @@ TEST(ExtensionPermissionSetTest, HasLessPrivilegesThan) {
if (!new_extension.get())
continue;
- const ExtensionPermissionSet* old_p = old_extension->permission_set();
- const ExtensionPermissionSet* new_p = new_extension->permission_set();
+ scoped_refptr<const ExtensionPermissionSet> old_p(
+ old_extension->GetActivePermissions());
+ scoped_refptr<const ExtensionPermissionSet> new_p(
+ new_extension->GetActivePermissions());
- EXPECT_EQ(kTests[i].expect_increase, old_p->HasLessPrivilegesThan(new_p))
- << kTests[i].base_name;
+ EXPECT_EQ(kTests[i].expect_increase,
+ old_p->HasLessPrivilegesThan(new_p)) << kTests[i].base_name;
}
}
@@ -491,6 +646,10 @@ TEST(ExtensionPermissionSetTest, PermissionMessages) {
// Warned as part of host permissions.
skip.insert(ExtensionAPIPermission::kDevtools);
+
+ // This will warn users later, when they request new permissions.
+ skip.insert(ExtensionAPIPermission::kPermissions);
+
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
ExtensionAPIPermissionSet permissions = info->GetAll();
for (ExtensionAPIPermissionSet::const_iterator i = permissions.begin();
@@ -538,10 +697,10 @@ TEST(ExtensionPermissionSetTest, DefaultFunctionAccess) {
{ "tabs.getSelected", false},
};
- ExtensionPermissionSet permissions;
+ scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
EXPECT_EQ(kTests[i].expect_success,
- permissions.HasAccessToFunction(kTests[i].permission_name));
+ empty->HasAccessToFunction(kTests[i].permission_name));
}
}
@@ -550,7 +709,7 @@ TEST(ExtensionPermissionSetTest, GetWarningMessages_ManyHosts) {
extension = LoadManifest("permissions", "many-hosts.json");
std::vector<string16> warnings =
- extension->permission_set()->GetWarningMessages();
+ extension->GetActivePermissions()->GetWarningMessages();
ASSERT_EQ(1u, warnings.size());
EXPECT_EQ("Your data on encrypted.google.com and www.google.com",
UTF16ToUTF8(warnings[0]));
@@ -558,11 +717,11 @@ TEST(ExtensionPermissionSetTest, GetWarningMessages_ManyHosts) {
TEST(ExtensionPermissionSetTest, GetWarningMessages_Plugins) {
scoped_refptr<Extension> extension;
- scoped_ptr<ExtensionPermissionSet> permissions;
+ scoped_refptr<ExtensionPermissionSet> permissions;
extension = LoadManifest("permissions", "plugins.json");
std::vector<string16> warnings =
- extension->permission_set()->GetWarningMessages();
+ extension->GetActivePermissions()->GetWarningMessages();
// We don't parse the plugins key on Chrome OS, so it should not ask for any
// permissions.
#if defined(OS_CHROMEOS)
@@ -575,7 +734,7 @@ TEST(ExtensionPermissionSetTest, GetWarningMessages_Plugins) {
}
TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
- scoped_ptr<ExtensionPermissionSet> perm_set;
+ scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
std::set<std::string> expected;
expected.insert("www.foo.com");
@@ -594,8 +753,8 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
URLPattern(URLPattern::SCHEME_HTTP, "http://www.bar.com/path"));
explicit_hosts.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path"));
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -607,8 +766,8 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
explicit_hosts.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path"));
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -618,8 +777,8 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
// Add a pattern that differs only by scheme. This should be filtered out.
explicit_hosts.AddPattern(
URLPattern(URLPattern::SCHEME_HTTPS, "https://www.bar.com/path"));
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -629,8 +788,8 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
// Add some dupes by path.
explicit_hosts.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.bar.com/pathypath"));
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -646,8 +805,8 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
expected.insert("monkey.www.bar.com");
expected.insert("bar.com");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -677,8 +836,8 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
expected.insert("www.foo.xyzzy");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -690,8 +849,8 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
expected.insert("*.google.com");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -709,14 +868,14 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
expected.insert("*.google.com");
expected.insert("*.example.com");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
}
TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_ComIsBestRcd) {
- scoped_ptr<ExtensionPermissionSet> perm_set;
+ scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
URLPatternSet explicit_hosts;
URLPatternSet scriptable_hosts;
@@ -735,13 +894,13 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_ComIsBestRcd) {
std::set<std::string> expected;
expected.insert("www.foo.com");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_NetIs2ndBestRcd) {
- scoped_ptr<ExtensionPermissionSet> perm_set;
+ scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
URLPatternSet explicit_hosts;
URLPatternSet scriptable_hosts;
@@ -759,14 +918,14 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_NetIs2ndBestRcd) {
std::set<std::string> expected;
expected.insert("www.foo.net");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
TEST(ExtensionPermissionSetTest,
GetDistinctHostsForDisplay_OrgIs3rdBestRcd) {
- scoped_ptr<ExtensionPermissionSet> perm_set;
+ scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
URLPatternSet explicit_hosts;
URLPatternSet scriptable_hosts;
@@ -783,14 +942,14 @@ TEST(ExtensionPermissionSetTest,
std::set<std::string> expected;
expected.insert("www.foo.org");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
TEST(ExtensionPermissionSetTest,
GetDistinctHostsForDisplay_FirstInListIs4thBestRcd) {
- scoped_ptr<ExtensionPermissionSet> perm_set;
+ scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
URLPatternSet explicit_hosts;
URLPatternSet scriptable_hosts;
@@ -806,8 +965,8 @@ TEST(ExtensionPermissionSetTest,
std::set<std::string> expected;
expected.insert("www.foo.ca");
- perm_set.reset(new ExtensionPermissionSet(
- empty_perms, explicit_hosts, scriptable_hosts));
+ perm_set = new ExtensionPermissionSet(
+ empty_perms, explicit_hosts, scriptable_hosts);
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
@@ -816,8 +975,8 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
URLPatternSet elist2;
URLPatternSet slist1;
URLPatternSet slist2;
- scoped_ptr<ExtensionPermissionSet> set1;
- scoped_ptr<ExtensionPermissionSet> set2;
+ scoped_refptr<ExtensionPermissionSet> set1;
+ scoped_refptr<ExtensionPermissionSet> set2;
ExtensionAPIPermissionSet empty_perms;
elist1.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path"));
@@ -830,8 +989,8 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
elist2.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path"));
- set1.reset(new ExtensionPermissionSet(empty_perms, elist1, slist1));
- set2.reset(new ExtensionPermissionSet(empty_perms, elist2, slist2));
+ set1 = new ExtensionPermissionSet(empty_perms, elist1, slist1);
+ set2 = new ExtensionPermissionSet(empty_perms, elist2, slist2);
EXPECT_FALSE(set1->HasLessHostPrivilegesThan(set2.get()));
EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
@@ -840,7 +999,7 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
elist2.ClearPatterns();
elist2.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/*"));
- set2.reset(new ExtensionPermissionSet(empty_perms, elist2, slist2));
+ set2 = new ExtensionPermissionSet(empty_perms, elist2, slist2);
EXPECT_FALSE(set1->HasLessHostPrivilegesThan(set2.get()));
EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
@@ -848,7 +1007,7 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
elist2.ClearPatterns();
elist2.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/*"));
- set2.reset(new ExtensionPermissionSet(empty_perms, elist2, slist2));
+ set2 = new ExtensionPermissionSet(empty_perms, elist2, slist2);
EXPECT_FALSE(set1->HasLessHostPrivilegesThan(set2.get()));
EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
@@ -856,7 +1015,7 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
elist2.ClearPatterns();
elist2.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com.hk/*"));
- set2.reset(new ExtensionPermissionSet(empty_perms, elist2, slist2));
+ set2 = new ExtensionPermissionSet(empty_perms, elist2, slist2);
EXPECT_TRUE(set1->HasLessHostPrivilegesThan(set2.get()));
//TODO(jstritar): Does not match subdomains properly. http://crbug.com/65337
//EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
@@ -867,7 +1026,7 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path"));
elist2.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://www.example.org/path"));
- set2.reset(new ExtensionPermissionSet(empty_perms, elist2, slist2));
+ set2 = new ExtensionPermissionSet(empty_perms, elist2, slist2);
EXPECT_TRUE(set1->HasLessHostPrivilegesThan(set2.get()));
EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
@@ -875,7 +1034,7 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
elist2.ClearPatterns();
elist2.AddPattern(
URLPattern(URLPattern::SCHEME_HTTP, "http://mail.google.com/*"));
- set2.reset(new ExtensionPermissionSet(empty_perms, elist2, slist2));
+ set2 = new ExtensionPermissionSet(empty_perms, elist2, slist2);
EXPECT_TRUE(set1->HasLessHostPrivilegesThan(set2.get()));
EXPECT_TRUE(set2->HasLessHostPrivilegesThan(set1.get()));
}
@@ -889,8 +1048,9 @@ TEST(ExtensionPermissionSetTest, GetAPIsAsStrings) {
apis.insert(ExtensionAPIPermission::kNotification);
apis.insert(ExtensionAPIPermission::kTab);
- ExtensionPermissionSet perm_set(apis, empty_set, empty_set);
- std::set<std::string> api_names = perm_set.GetAPIsAsStrings();
+ scoped_refptr<ExtensionPermissionSet> perm_set = new ExtensionPermissionSet(
+ apis, empty_set, empty_set);
+ std::set<std::string> api_names = perm_set->GetAPIsAsStrings();
// The result is correct if it has the same number of elements
// and we can convert it back to the id set.
@@ -903,27 +1063,28 @@ TEST(ExtensionPermissionSetTest, IsEmpty) {
ExtensionAPIPermissionSet empty_apis;
URLPatternSet empty_extent;
- ExtensionPermissionSet perm_set;
- EXPECT_TRUE(perm_set.IsEmpty());
+ scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
+ EXPECT_TRUE(empty->IsEmpty());
+ scoped_refptr<ExtensionPermissionSet> perm_set;
- perm_set = ExtensionPermissionSet(empty_apis, empty_extent, empty_extent);
- EXPECT_TRUE(perm_set.IsEmpty());
+ perm_set = new ExtensionPermissionSet(empty_apis, empty_extent, empty_extent);
+ EXPECT_TRUE(perm_set->IsEmpty());
ExtensionAPIPermissionSet non_empty_apis;
non_empty_apis.insert(ExtensionAPIPermission::kBackground);
- perm_set = ExtensionPermissionSet(
+ perm_set = new ExtensionPermissionSet(
non_empty_apis, empty_extent, empty_extent);
- EXPECT_FALSE(perm_set.IsEmpty());
+ EXPECT_FALSE(perm_set->IsEmpty());
// Try non standard host
URLPatternSet non_empty_extent;
AddPattern(&non_empty_extent, "http://www.google.com/*");
- perm_set = ExtensionPermissionSet(
+ perm_set = new ExtensionPermissionSet(
empty_apis, non_empty_extent, empty_extent);
- EXPECT_FALSE(perm_set.IsEmpty());
+ EXPECT_FALSE(perm_set->IsEmpty());
- perm_set = ExtensionPermissionSet(
+ perm_set = new ExtensionPermissionSet(
empty_apis, empty_extent, non_empty_extent);
- EXPECT_FALSE(perm_set.IsEmpty());
+ EXPECT_FALSE(perm_set->IsEmpty());
}
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 79cad1a..5115573 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -389,10 +389,10 @@ TEST(ExtensionTest, EffectiveHostPermissions) {
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com")));
EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com")));
- EXPECT_TRUE(extension->permission_set()->HasEffectiveAccessToURL(
+ EXPECT_TRUE(extension->GetActivePermissions()->HasEffectiveAccessToURL(
GURL("http://www.reddit.com")));
EXPECT_TRUE(hosts.MatchesURL(GURL("http://news.ycombinator.com")));
- EXPECT_TRUE(extension->permission_set()->HasEffectiveAccessToURL(
+ EXPECT_TRUE(extension->GetActivePermissions()->HasEffectiveAccessToURL(
GURL("http://news.ycombinator.com")));
EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
diff --git a/chrome/common/extensions/url_pattern_set.cc b/chrome/common/extensions/url_pattern_set.cc
index 3c8f52c..cf2b9a6 100644
--- a/chrome/common/extensions/url_pattern_set.cc
+++ b/chrome/common/extensions/url_pattern_set.cc
@@ -10,6 +10,29 @@
#include "chrome/common/extensions/url_pattern.h"
#include "googleurl/src/gurl.h"
+
+// static
+void URLPatternSet::CreateDifference(const URLPatternSet& set1,
+ const URLPatternSet& set2,
+ URLPatternSet* out) {
+ out->ClearPatterns();
+ std::set_difference(set1.patterns_.begin(), set1.patterns_.end(),
+ set2.patterns_.begin(), set2.patterns_.end(),
+ std::inserter<std::set<URLPattern> >(
+ out->patterns_, out->patterns_.begin()));
+}
+
+// static
+void URLPatternSet::CreateIntersection(const URLPatternSet& set1,
+ const URLPatternSet& set2,
+ URLPatternSet* out) {
+ out->ClearPatterns();
+ std::set_intersection(set1.patterns_.begin(), set1.patterns_.end(),
+ set2.patterns_.begin(), set2.patterns_.end(),
+ std::inserter<std::set<URLPattern> >(
+ out->patterns_, out->patterns_.begin()));
+}
+
// static
void URLPatternSet::CreateUnion(const URLPatternSet& set1,
const URLPatternSet& set2,
@@ -52,6 +75,11 @@ void URLPatternSet::ClearPatterns() {
patterns_.clear();
}
+bool URLPatternSet::Contains(const URLPatternSet& set) const {
+ return std::includes(patterns_.begin(), patterns_.end(),
+ set.patterns_.begin(), set.patterns_.end());
+}
+
bool URLPatternSet::MatchesURL(const GURL& url) const {
for (URLPatternSet::const_iterator pattern = patterns_.begin();
pattern != patterns_.end(); ++pattern) {
diff --git a/chrome/common/extensions/url_pattern_set.h b/chrome/common/extensions/url_pattern_set.h
index 1848e74..d26321c 100644
--- a/chrome/common/extensions/url_pattern_set.h
+++ b/chrome/common/extensions/url_pattern_set.h
@@ -18,6 +18,17 @@ class URLPatternSet {
typedef std::set<URLPattern>::const_iterator const_iterator;
typedef std::set<URLPattern>::iterator iterator;
+ // Clears |out| and populates the set with |set1| - |set2|.
+ static void CreateDifference(const URLPatternSet& set1,
+ const URLPatternSet& set2,
+ URLPatternSet* out);
+
+ // Clears |out| and populates the set with the intersection of |set1|
+ // and |set2|.
+ static void CreateIntersection(const URLPatternSet& set1,
+ const URLPatternSet& set2,
+ URLPatternSet* out);
+
// Clears |out| and populates the set with the union of |set1| and |set2|.
static void CreateUnion(const URLPatternSet& set1,
const URLPatternSet& set2,
@@ -39,6 +50,9 @@ class URLPatternSet {
void AddPattern(const URLPattern& pattern);
void ClearPatterns();
+ // Returns true if the permission |set| is a subset of this.
+ bool Contains(const URLPatternSet& set) const;
+
// Test if the extent contains a URL.
bool MatchesURL(const GURL& url) const;
diff --git a/chrome/common/extensions/url_pattern_set_unittest.cc b/chrome/common/extensions/url_pattern_set_unittest.cc
index f9717ef..ff78d90 100644
--- a/chrome/common/extensions/url_pattern_set_unittest.cc
+++ b/chrome/common/extensions/url_pattern_set_unittest.cc
@@ -7,88 +7,195 @@
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
-static const int kAllSchemes =
- URLPattern::SCHEME_HTTP |
- URLPattern::SCHEME_HTTPS |
- URLPattern::SCHEME_FILE |
- URLPattern::SCHEME_FTP |
- URLPattern::SCHEME_CHROMEUI;
+namespace {
+static void AddPattern(URLPatternSet* set, const std::string& pattern) {
+ int schemes = URLPattern::SCHEME_ALL;
+ set->AddPattern(URLPattern(schemes, pattern));
+}
+
+}
TEST(URLPatternSetTest, Empty) {
- URLPatternSet extent;
- EXPECT_FALSE(extent.MatchesURL(GURL("http://www.foo.com/bar")));
- EXPECT_FALSE(extent.MatchesURL(GURL()));
- EXPECT_FALSE(extent.MatchesURL(GURL("invalid")));
+ URLPatternSet set;
+ EXPECT_FALSE(set.MatchesURL(GURL("http://www.foo.com/bar")));
+ EXPECT_FALSE(set.MatchesURL(GURL()));
+ EXPECT_FALSE(set.MatchesURL(GURL("invalid")));
}
TEST(URLPatternSetTest, One) {
- URLPatternSet extent;
- extent.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/*"));
+ URLPatternSet set;
+ AddPattern(&set, "http://www.google.com/*");
- EXPECT_TRUE(extent.MatchesURL(GURL("http://www.google.com/")));
- EXPECT_TRUE(extent.MatchesURL(GURL("http://www.google.com/monkey")));
- EXPECT_FALSE(extent.MatchesURL(GURL("https://www.google.com/")));
- EXPECT_FALSE(extent.MatchesURL(GURL("https://www.microsoft.com/")));
+ EXPECT_TRUE(set.MatchesURL(GURL("http://www.google.com/")));
+ EXPECT_TRUE(set.MatchesURL(GURL("http://www.google.com/monkey")));
+ EXPECT_FALSE(set.MatchesURL(GURL("https://www.google.com/")));
+ EXPECT_FALSE(set.MatchesURL(GURL("https://www.microsoft.com/")));
}
TEST(URLPatternSetTest, Two) {
- URLPatternSet extent;
- extent.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/*"));
- extent.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/*"));
+ URLPatternSet set;
+ AddPattern(&set, "http://www.google.com/*");
+ AddPattern(&set, "http://www.yahoo.com/*");
- EXPECT_TRUE(extent.MatchesURL(GURL("http://www.google.com/monkey")));
- EXPECT_TRUE(extent.MatchesURL(GURL("http://www.yahoo.com/monkey")));
- EXPECT_FALSE(extent.MatchesURL(GURL("https://www.apple.com/monkey")));
+ EXPECT_TRUE(set.MatchesURL(GURL("http://www.google.com/monkey")));
+ EXPECT_TRUE(set.MatchesURL(GURL("http://www.yahoo.com/monkey")));
+ EXPECT_FALSE(set.MatchesURL(GURL("https://www.apple.com/monkey")));
}
TEST(URLPatternSetTest, OverlapsWith) {
- URLPatternSet extent1;
- extent1.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/f*"));
- extent1.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/b*"));
+ URLPatternSet set1;
+ AddPattern(&set1, "http://www.google.com/f*");
+ AddPattern(&set1, "http://www.yahoo.com/b*");
+
+ URLPatternSet set2;
+ AddPattern(&set2, "http://www.reddit.com/f*");
+ AddPattern(&set2, "http://www.yahoo.com/z*");
+
+ URLPatternSet set3;
+ AddPattern(&set3, "http://www.google.com/q/*");
+ AddPattern(&set3, "http://www.yahoo.com/b/*");
+
+ EXPECT_FALSE(set1.OverlapsWith(set2));
+ EXPECT_FALSE(set2.OverlapsWith(set1));
+
+ EXPECT_TRUE(set1.OverlapsWith(set3));
+ EXPECT_TRUE(set3.OverlapsWith(set1));
+}
+
+TEST(URLPatternSetTest, CreateDifference) {
+ URLPatternSet expected;
+ URLPatternSet set1;
+ URLPatternSet set2;
+ AddPattern(&set1, "http://www.google.com/f*");
+ AddPattern(&set1, "http://www.yahoo.com/b*");
- URLPatternSet extent2;
- extent2.AddPattern(URLPattern(kAllSchemes, "http://www.reddit.com/f*"));
- extent2.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/z*"));
+ // Subtract an empty set.
+ URLPatternSet result;
+ URLPatternSet::CreateDifference(set1, set2, &result);
+ EXPECT_EQ(set1, result);
- URLPatternSet extent3;
- extent3.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/q/*"));
- extent3.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/b/*"));
+ // Subtract a real set.
+ AddPattern(&set2, "http://www.reddit.com/f*");
+ AddPattern(&set2, "http://www.yahoo.com/z*");
+ AddPattern(&set2, "http://www.google.com/f*");
- EXPECT_FALSE(extent1.OverlapsWith(extent2));
- EXPECT_FALSE(extent2.OverlapsWith(extent1));
+ AddPattern(&expected, "http://www.yahoo.com/b*");
- EXPECT_TRUE(extent1.OverlapsWith(extent3));
- EXPECT_TRUE(extent3.OverlapsWith(extent1));
+ result.ClearPatterns();
+ URLPatternSet::CreateDifference(set1, set2, &result);
+ EXPECT_EQ(expected, result);
+ EXPECT_FALSE(result.is_empty());
+ EXPECT_TRUE(set1.Contains(result));
+ EXPECT_FALSE(result.Contains(set2));
+ EXPECT_FALSE(set2.Contains(result));
+
+ URLPatternSet intersection;
+ URLPatternSet::CreateIntersection(result, set2, &intersection);
+ EXPECT_TRUE(intersection.is_empty());
+}
+
+TEST(URLPatternSetTest, CreateIntersection) {
+ URLPatternSet empty_set;
+ URLPatternSet expected;
+ URLPatternSet set1;
+ AddPattern(&set1, "http://www.google.com/f*");
+ AddPattern(&set1, "http://www.yahoo.com/b*");
+
+ // Intersection with an empty set.
+ URLPatternSet result;
+ URLPatternSet::CreateIntersection(set1, empty_set, &result);
+ EXPECT_EQ(expected, result);
+ EXPECT_TRUE(result.is_empty());
+ EXPECT_TRUE(empty_set.Contains(result));
+ EXPECT_TRUE(result.Contains(empty_set));
+ EXPECT_TRUE(set1.Contains(result));
+
+ // Intersection with a real set.
+ URLPatternSet set2;
+ AddPattern(&set2, "http://www.reddit.com/f*");
+ AddPattern(&set2, "http://www.yahoo.com/z*");
+ AddPattern(&set2, "http://www.google.com/f*");
+
+ AddPattern(&expected, "http://www.google.com/f*");
+
+ result.ClearPatterns();
+ URLPatternSet::CreateIntersection(set1, set2, &result);
+ EXPECT_EQ(expected, result);
+ EXPECT_FALSE(result.is_empty());
+ EXPECT_TRUE(set1.Contains(result));
+ EXPECT_TRUE(set2.Contains(result));
}
TEST(URLPatternSetTest, CreateUnion) {
- URLPatternSet empty_extent;
+ URLPatternSet empty_set;
- URLPatternSet extent1;
- extent1.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/f*"));
- extent1.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/b*"));
+ URLPatternSet set1;
+ AddPattern(&set1, "http://www.google.com/f*");
+ AddPattern(&set1, "http://www.yahoo.com/b*");
URLPatternSet expected;
- expected.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/f*"));
- expected.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/b*"));
+ AddPattern(&expected, "http://www.google.com/f*");
+ AddPattern(&expected, "http://www.yahoo.com/b*");
// Union with an empty set.
URLPatternSet result;
- URLPatternSet::CreateUnion(extent1, empty_extent, &result);
+ URLPatternSet::CreateUnion(set1, empty_set, &result);
EXPECT_EQ(expected, result);
- // Union with a real set (including a duplicate).
- URLPatternSet extent2;
- extent2.AddPattern(URLPattern(kAllSchemes, "http://www.reddit.com/f*"));
- extent2.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/z*"));
- extent2.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/f*"));
+ // Union with a real set.
+ URLPatternSet set2;
+ AddPattern(&set2, "http://www.reddit.com/f*");
+ AddPattern(&set2, "http://www.yahoo.com/z*");
+ AddPattern(&set2, "http://www.google.com/f*");
- expected.AddPattern(URLPattern(kAllSchemes, "http://www.reddit.com/f*"));
- expected.AddPattern(URLPattern(kAllSchemes, "http://www.yahoo.com/z*"));
- // CreateUnion does not filter out duplicates right now.
- expected.AddPattern(URLPattern(kAllSchemes, "http://www.google.com/f*"));
+ AddPattern(&expected, "http://www.reddit.com/f*");
+ AddPattern(&expected, "http://www.yahoo.com/z*");
result.ClearPatterns();
- URLPatternSet::CreateUnion(extent1, extent2, &result);
+ URLPatternSet::CreateUnion(set1, set2, &result);
EXPECT_EQ(expected, result);
}
+
+TEST(URLPatternSetTest, Contains) {
+ URLPatternSet set1;
+ URLPatternSet set2;
+ URLPatternSet empty_set;
+
+ AddPattern(&set1, "http://www.google.com/*");
+ AddPattern(&set1, "http://www.yahoo.com/*");
+
+ AddPattern(&set2, "http://www.reddit.com/*");
+
+ EXPECT_FALSE(set1.Contains(set2));
+ EXPECT_TRUE(set1.Contains(empty_set));
+ EXPECT_FALSE(empty_set.Contains(set1));
+
+ AddPattern(&set2, "http://www.yahoo.com/*");
+
+ EXPECT_FALSE(set1.Contains(set2));
+ EXPECT_FALSE(set2.Contains(set1));
+
+ AddPattern(&set2, "http://www.google.com/*");
+
+ EXPECT_FALSE(set1.Contains(set2));
+ EXPECT_TRUE(set2.Contains(set1));
+
+ // Note that this just checks pattern equality, and not if individual patterns
+ // contain other patterns. For example:
+ AddPattern(&set1, "http://*.reddit.com/*");
+ EXPECT_FALSE(set1.Contains(set2));
+ EXPECT_FALSE(set2.Contains(set1));
+}
+
+TEST(URLPatternSetTest, Duplicates) {
+ URLPatternSet set1;
+ URLPatternSet set2;
+
+ AddPattern(&set1, "http://www.google.com/*");
+ AddPattern(&set2, "http://www.google.com/*");
+
+ AddPattern(&set1, "http://www.google.com/*");
+
+ // The sets should still be equal after adding a duplicate.
+ EXPECT_EQ(set2, set1);
+}