summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd30
-rw-r--r--chrome/browser/extensions/extension_install_ui.cc56
-rw-r--r--chrome/browser/extensions/extension_install_ui.h5
-rw-r--r--chrome/browser/extensions/extensions_service.cc8
-rw-r--r--chrome/browser/gtk/extension_install_prompt_gtk.cc7
-rw-r--r--chrome/browser/views/extensions/extension_install_prompt.cc61
-rw-r--r--chrome/common/extensions/extension.cc102
-rw-r--r--chrome/common/extensions/extension.h34
-rw-r--r--chrome/common/extensions/extension_unittest.cc214
-rw-r--r--chrome/common/extensions/user_script.cc4
-rw-r--r--chrome/common/extensions/user_script.h6
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/allhosts1_new.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/allhosts1_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/allhosts2_new.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/allhosts2_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/allhosts3_new.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/allhosts3_old.json4
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts1_new.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts1_old.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts2_new.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts2_old.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts3_new.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts3_old.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts4_new.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/hosts4_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions1_new.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions1_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions2_new.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions2_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions3_new.json8
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions3_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions4_new.json10
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/permissions4_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/plugin1_new.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/plugin1_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/plugin2_new.json4
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/plugin2_old.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/plugin3_new.json7
-rwxr-xr-xchrome/test/data/extensions/allow_silent_upgrade/plugin3_old.json4
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/all_hosts.json7
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/all_hosts2.json8
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/all_hosts3.json13
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/duplicate_content_script.json15
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/duplicate_host.json8
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/empty.json4
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/https_not_considered.json9
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/one_host.json7
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/one_host_wildcard.json7
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/two_content_scripts.json15
-rwxr-xr-xchrome/test/data/extensions/effective_host_permissions/two_hosts.json8
50 files changed, 656 insertions, 170 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 70e50b4..fe1ccc1 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -2096,7 +2096,7 @@ each locale. -->
The newest version of the extension "<ph name="EXTENSION_NAME">$1<ex>Flashblock</ex></ph>" requires more permissions, so it has been disabled.
</message>
<message name="IDS_EXTENSION_DISABLED_INFOBAR_ENABLE_BUTTON" desc="Text displayed on the button to re-enable the disabled extension.">
- Reenable
+ Re-enable
</message>
<!-- Extension install prompt -->
@@ -2106,6 +2106,33 @@ each locale. -->
<message name="IDS_EXTENSION_PROMPT_HEADING" desc="First bold line in the content area of the extension installation prompt. Asks the user if they want to install a particular extension.">
Install "<ph name="EXTENSION_NAME">$1<ex>Gmail Checker</ex></ph>"?
</message>
+
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_BROWSER" desc="Warning displayed in body of extension dialog when the extension requires access to browser APIs.">
+ This extension will have access to your browsing history.
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST" desc="Warning displayed in body of extension dialog when the extension requires access to a single host.">
+ This extension will have access to your private data on <ph name="HOST">$1<ex>maps.google.com</ex></ph>
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST_AND_BROWSER" desc="Warning displayed in body of extension dialog when the extension requires access to a single host and browser APIs.">
+ This extension will have access to your browsing history and private data on <ph name="HOST">$1<ex>maps.google.com</ex></ph>
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS" desc="Warning displayed in body of extension dialog when the extension requires access to multiple hosts, but not every host.">
+ This extension will have access to your private data on multiple websites.
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS_AND_BROWSER" desc="Warning displayed in body of extension dialog when the extension requires access to multiple hosts, but not every host, and browser APIs.">
+ This extension will have access to your browsing history and private data on multiple websites.
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS" desc="Warning displayed in body of extension dialog when the extension requires access to all hosts.">
+ This extension will have access to your private data on all websites.
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS_AND_BROWSER" desc="Warning displayed in body of extension dialog when the extension requires access to all hosts and browser APIs.">
+ This extension will have access to your browsing history and private data on all websites.
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_NEW_FULL_ACCESS" desc="Warning displayed in body of extension dialog when the extension requires access the local machine.">
+ This extension will have full access to your computer and private data.
+ </message>
+
+ <!-- TODO(aa): Remove these old warning messages when all the platforms are switched to the new ones, above. -->
<message name="IDS_EXTENSION_PROMPT_WARNING_1" desc="Humorous warning displayed in the extension install prompt that tells users that extensions have access to their computer and private data.">
Extensions have access to your computer and private data. This means they could forward all your email to your spouse.
</message>
@@ -2118,6 +2145,7 @@ each locale. -->
<message name="IDS_EXTENSION_PROMPT_WARNING_SEVERE" desc="A bolded warning below the humorous warning that reiterates that users should only install extensions they trust">
Only install extensions you trust.
</message>
+
<message name="IDS_EXTENSION_PROMPT_INSTALL_BUTTON" desc="Text for the install button on the extension install prompt">
Install
</message>
diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc
index 144ea78f..1023a5a 100644
--- a/chrome/browser/extensions/extension_install_ui.cc
+++ b/chrome/browser/extensions/extension_install_ui.cc
@@ -26,6 +26,59 @@
#include <CoreFoundation/CFUserNotification.h>
#endif
+namespace {
+
+#if defined(OS_WIN) || defined(TOOLKIT_GTK)
+
+static std::wstring GetInstallWarning(Extension* extension) {
+ // If the extension has a plugin, it's easy: the plugin has the most severe
+ // warning.
+ if (!extension->plugins().empty())
+ return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_FULL_ACCESS);
+
+ // Otherwise, we go in descending order of severity: all hosts, several hosts,
+ // a single host, no hosts. For each of these, we also have a variation of the
+ // message for when api permissions are also requested.
+ if (extension->HasAccessToAllHosts()) {
+ if (extension->api_permissions().empty())
+ return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS);
+ else
+ return l10n_util::GetString(
+ IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS_AND_BROWSER);
+ }
+
+ const std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
+ if (hosts.size() > 1) {
+ if (extension->api_permissions().empty())
+ return l10n_util::GetString(
+ IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS);
+ else
+ return l10n_util::GetString(
+ IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS_AND_BROWSER);
+ }
+
+ if (hosts.size() == 1) {
+ if (extension->api_permissions().empty())
+ return l10n_util::GetStringF(
+ IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST,
+ UTF8ToWide(*hosts.begin()));
+ else
+ return l10n_util::GetStringF(
+ IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST_AND_BROWSER,
+ UTF8ToWide(*hosts.begin()));
+ }
+
+ DCHECK(hosts.size() == 0);
+ if (extension->api_permissions().empty())
+ return L"";
+ else
+ return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_BROWSER);
+}
+
+#endif
+
+}
+
ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
: profile_(profile), ui_loop_(MessageLoop::current()) {
}
@@ -49,7 +102,8 @@ void ExtensionInstallUI::ConfirmInstall(Delegate* delegate,
}
#if defined(OS_WIN) || defined(TOOLKIT_GTK)
- ShowExtensionInstallPrompt(profile_, delegate, extension, install_icon);
+ ShowExtensionInstallPrompt(profile_, delegate, extension, install_icon,
+ GetInstallWarning(extension));
#elif defined(OS_MACOSX)
// TODO(port): Implement nicer UI.
diff --git a/chrome/browser/extensions/extension_install_ui.h b/chrome/browser/extensions/extension_install_ui.h
index 1914989..0147d9c 100644
--- a/chrome/browser/extensions/extension_install_ui.h
+++ b/chrome/browser/extensions/extension_install_ui.h
@@ -9,6 +9,8 @@
#include "base/gfx/native_widget_types.h"
#include "base/ref_counted.h"
+#include <string>
+
class Extension;
class ExtensionsService;
class MessageLoop;
@@ -34,7 +36,8 @@ class ExtensionInstallUI {
static void ShowExtensionInstallPrompt(Profile* profile,
Delegate* delegate,
Extension* extension,
- SkBitmap* install_icon);
+ SkBitmap* install_icon,
+ const std::wstring& warning_text);
ExtensionInstallUI(Profile* profile);
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 9b19ba9..d389aa6 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -381,16 +381,16 @@ void ExtensionsService::OnExtensionLoaded(Extension* extension) {
Extension* old = GetExtensionByIdInternal(extension->id(), true, true);
if (old) {
if (extension->version()->CompareTo(*(old->version())) > 0) {
- bool higher_permissions =
- (extension->GetPermissionClass() > old->GetPermissionClass());
+ bool allow_silent_upgrade = Extension::AllowSilentUpgrade(
+ old, extension);
// To upgrade an extension in place, unload the old one and
// then load the new one.
UnloadExtension(old->id());
old = NULL;
- if (higher_permissions) {
- // Extension was upgraded to a high permission class. Disable it and
+ if (!allow_silent_upgrade) {
+ // Extension has changed permissions significantly. Disable it and
// notify the user.
extension_prefs_->SetExtensionState(extension, Extension::DISABLED);
NotificationService::current()->Notify(
diff --git a/chrome/browser/gtk/extension_install_prompt_gtk.cc b/chrome/browser/gtk/extension_install_prompt_gtk.cc
index a195cff..c49102e 100644
--- a/chrome/browser/gtk/extension_install_prompt_gtk.cc
+++ b/chrome/browser/gtk/extension_install_prompt_gtk.cc
@@ -126,10 +126,9 @@ void ShowInstallPromptDialog(GtkWindow* parent, SkBitmap* skia_icon,
} // namespace
-void ExtensionInstallUI::ShowExtensionInstallPrompt(Profile* profile,
- Delegate* delegate,
- Extension* extension,
- SkBitmap* icon) {
+void ExtensionInstallUI::ShowExtensionInstallPrompt(
+ Profile* profile, Delegate* delegate, Extension* extension, SkBitmap* icon,
+ const std::wstring& warning_text) {
Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
if (!browser) {
delegate->ContinueInstall();
diff --git a/chrome/browser/views/extensions/extension_install_prompt.cc b/chrome/browser/views/extensions/extension_install_prompt.cc
index 6c58914..cc7d41c 100644
--- a/chrome/browser/views/extensions/extension_install_prompt.cc
+++ b/chrome/browser/views/extensions/extension_install_prompt.cc
@@ -23,24 +23,18 @@ class Profile;
namespace {
-const int kRightColumnWidth = 290;
+const int kRightColumnWidth = 270;
+const int kIconSize = 85;
// Implements the extension installation prompt for Windows.
-// TODO(aa): It would be cool to add an "extensions threat level" when we have
-// granular permissions implemented:
-// - red: npapi
-// - orange: access to any domains
-// - yellow: access to browser data
-// - green: nothing
-// We could have a collection of funny descriptions for each color.
class InstallDialogContent : public views::View, public views::DialogDelegate {
public:
InstallDialogContent(ExtensionInstallUI::Delegate* delegate,
- Extension* extension,
- SkBitmap* icon)
- : delegate_(delegate), icon_(NULL) {
+ Extension* extension, SkBitmap* icon, const std::wstring& warning_text)
+ : delegate_(delegate), icon_(NULL) {
if (icon) {
icon_ = new views::ImageView();
+ icon_->SetImageSize(gfx::Size(kIconSize, kIconSize));
icon_->SetImage(*icon);
AddChildView(icon_);
}
@@ -53,25 +47,10 @@ class InstallDialogContent : public views::View, public views::DialogDelegate {
heading_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
AddChildView(heading_);
- // Pick a random warning.
- std::wstring warnings[] = {
- l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_1),
- l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_2),
- l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_3)
- };
- warning_ = new views::Label(
- warnings[base::RandInt(0, arraysize(warnings) - 1)]);
+ warning_ = new views::Label(warning_text);
warning_->SetMultiLine(true);
warning_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
AddChildView(warning_);
-
- severe_ = new views::Label(
- l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_SEVERE));
- severe_->SetMultiLine(true);
- severe_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
- severe_->SetFont(heading_->GetFont().DeriveFont(0, gfx::Font::BOLD));
- severe_->SetColor(SK_ColorRED);
- AddChildView(severe_);
}
private:
@@ -116,7 +95,7 @@ class InstallDialogContent : public views::View, public views::DialogDelegate {
int width = kRightColumnWidth + kPanelHorizMargin + kPanelHorizMargin;
if (icon_) {
- width += Extension::EXTENSION_ICON_LARGE;
+ width += kIconSize;
width += kPanelHorizMargin;
}
@@ -125,11 +104,8 @@ class InstallDialogContent : public views::View, public views::DialogDelegate {
height += kPanelVertMargin;
height += warning_->GetHeightForWidth(kRightColumnWidth);
height += kPanelVertMargin;
- height += severe_->GetHeightForWidth(kRightColumnWidth);
- height += kPanelVertMargin;
- return gfx::Size(width, std::max(height,
- static_cast<int>(Extension::EXTENSION_ICON_LARGE)));
+ return gfx::Size(width, std::max(height, kIconSize));
}
virtual void Layout() {
@@ -137,9 +113,8 @@ class InstallDialogContent : public views::View, public views::DialogDelegate {
int y = kPanelVertMargin;
if (icon_) {
- icon_->SetBounds(x, y, Extension::EXTENSION_ICON_LARGE,
- Extension::EXTENSION_ICON_LARGE);
- x += Extension::EXTENSION_ICON_LARGE;
+ icon_->SetBounds(x, y, kIconSize, kIconSize);
+ x += kIconSize;
x += kPanelHorizMargin;
}
@@ -156,28 +131,21 @@ class InstallDialogContent : public views::View, public views::DialogDelegate {
y += warning_->height();
y += kPanelVertMargin;
-
- severe_->SizeToFit(kRightColumnWidth);
- severe_->SetX(x);
- severe_->SetY(y);
- y += severe_->height();
}
ExtensionInstallUI::Delegate* delegate_;
views::ImageView* icon_;
views::Label* heading_;
views::Label* warning_;
- views::Label* severe_;
DISALLOW_COPY_AND_ASSIGN(InstallDialogContent);
};
} // namespace
-void ExtensionInstallUI::ShowExtensionInstallPrompt(Profile* profile,
- Delegate* delegate,
- Extension* extension,
- SkBitmap* icon) {
+void ExtensionInstallUI::ShowExtensionInstallPrompt(
+ Profile* profile, Delegate* delegate, Extension* extension, SkBitmap* icon,
+ const std::wstring& warning_text) {
Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
if (!browser) {
delegate->ContinueInstall();
@@ -191,5 +159,6 @@ void ExtensionInstallUI::ShowExtensionInstallPrompt(Profile* profile,
}
views::Window::CreateChromeWindow(window->GetNativeHandle(), gfx::Rect(),
- new InstallDialogContent(delegate, extension, icon))->Show();
+ new InstallDialogContent(delegate, extension, icon,
+ warning_text))->Show();
}
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 1eb43e3..134ee3f 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -526,6 +526,51 @@ bool Extension::FormatPEMForFileOutput(const std::string input,
return true;
}
+// static
+// TODO(aa): A problem with this code is that we silently allow upgrades to
+// extensions that require less permissions than the current version, but then
+// we don't silently allow them to go back. In order to fix this, we would need
+// to remember the max set of permissions we ever granted a single extension.
+bool Extension::AllowSilentUpgrade(Extension* old_extension,
+ Extension* new_extension) {
+ // If the old extension had native code access, we don't need to go any
+ // further. Things can't get any worse.
+ if (old_extension->plugins().size() > 0)
+ return true;
+
+ // Otherwise, if the new extension has a plugin, no silent upgrade.
+ if (new_extension->plugins().size() > 0)
+ return false;
+
+ // If we are increasing the set of hosts we have access to, no silent upgrade.
+ if (!old_extension->HasAccessToAllHosts()) {
+ if (new_extension->HasAccessToAllHosts())
+ return false;
+
+ std::set<std::string> old_hosts =
+ old_extension->GetEffectiveHostPermissions();
+ std::set<std::string> new_hosts =
+ new_extension->GetEffectiveHostPermissions();
+
+ std::set<std::string> difference;
+ std::set_difference(new_hosts.begin(), new_hosts.end(),
+ old_hosts.begin(), old_hosts.end(),
+ std::insert_iterator<std::set<std::string> >(
+ difference, difference.end()));
+ if (difference.size() > 0)
+ return false;
+ }
+
+ // If we're going from not having api permissions to having them, no silent
+ // upgrade.
+ if (old_extension->api_permissions().size() == 0 &&
+ new_extension->api_permissions().size() > 0)
+ return false;
+
+ // Nothing much has changed. Allow the silent upgrade.
+ return true;
+}
+
bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
std::string* error) {
if (source.HasKey(keys::kPublicKey)) {
@@ -989,25 +1034,6 @@ std::set<FilePath> Extension::GetBrowserImages() {
return image_paths;
}
-Extension::PermissionClass Extension::GetPermissionClass() {
- // Native code can do anything. Highest class.
- if (!plugins_.empty())
- return PERMISSION_CLASS_FULL;
-
- // Access to other sites means the extension can steal cookies (login data)
- // from those sites.
- // TODO(mpcomplete): should we only classify for host access outside the
- // extension's origin? how?
- if (!host_permissions_.empty() || !content_scripts_.empty())
- return PERMISSION_CLASS_HIGH;
-
- // Extension can access history data, bookmarks, other personal info.
- if (!api_permissions_.empty())
- return PERMISSION_CLASS_MEDIUM;
-
- return PERMISSION_CLASS_LOW;
-}
-
bool Extension::GetBackgroundPageReady() {
return background_page_ready_ || background_url().is_empty();
}
@@ -1028,3 +1054,41 @@ FilePath Extension::GetIconPath(Icons icon) {
return FilePath();
return GetResourcePath(iter->second);
}
+
+const std::set<std::string> Extension::GetEffectiveHostPermissions() const {
+ std::set<std::string> effective_hosts;
+
+ for (HostPermissions::const_iterator host = host_permissions_.begin();
+ host != host_permissions_.end(); ++host)
+ effective_hosts.insert(host->host());
+
+ for (UserScriptList::const_iterator content_script = content_scripts_.begin();
+ content_script != content_scripts_.end(); ++content_script) {
+ UserScript::PatternList::const_iterator pattern =
+ content_script->url_patterns().begin();
+ for (; pattern != content_script->url_patterns().end(); ++pattern)
+ effective_hosts.insert(pattern->host());
+ }
+
+ return effective_hosts;
+}
+
+bool Extension::HasAccessToAllHosts() const {
+ for (HostPermissions::const_iterator host = host_permissions_.begin();
+ host != host_permissions_.end(); ++host) {
+ if (host->match_subdomains() && host->host().empty())
+ return true;
+ }
+
+ for (UserScriptList::const_iterator content_script = content_scripts_.begin();
+ content_script != content_scripts_.end(); ++content_script) {
+ UserScript::PatternList::const_iterator pattern =
+ content_script->url_patterns().begin();
+ for (; pattern != content_script->url_patterns().end(); ++pattern) {
+ if (pattern->match_subdomains() && pattern->host().empty())
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 34685fc..ab68d60 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -23,6 +23,8 @@
// Represents a Chrome extension.
class Extension {
public:
+ typedef std::vector<URLPattern> HostPermissions;
+
// What an extension was loaded from.
enum Location {
INVALID,
@@ -65,15 +67,6 @@ class Extension {
static const char* kPermissionNames[];
static const size_t kNumPermissions;
- // A classification of how dangerous an extension can be, based on what it has
- // access to.
- enum PermissionClass {
- PERMISSION_CLASS_LOW = 0, // green
- PERMISSION_CLASS_MEDIUM, // yellow
- PERMISSION_CLASS_HIGH, // orange
- PERMISSION_CLASS_FULL, // red
- };
-
struct PrivacyBlacklistInfo {
FilePath path; // Path to the plain-text blacklist.
};
@@ -175,6 +168,11 @@ class Extension {
static bool FormatPEMForFileOutput(const std::string input,
std::string* output, bool is_public);
+ // Determine whether we should allow a silent upgrade from |old_extension| to
+ // |new_extension|. If not, the user will have to approve the upgrade.
+ static bool AllowSilentUpgrade(Extension* old_extension,
+ Extension* new_extension);
+
// Initialize the extension from a parsed manifest.
// If |require_id| is true, will return an error if the "id" key is missing
// from the value.
@@ -201,12 +199,23 @@ class Extension {
const std::vector<PluginInfo>& plugins() const { return plugins_; }
const GURL& background_url() const { return background_url_; }
const std::vector<ToolstripInfo>& toolstrips() const { return toolstrips_; }
- const std::vector<URLPattern>& host_permissions() const {
+ const HostPermissions& host_permissions() const {
return host_permissions_;
}
const std::vector<std::string>& api_permissions() const {
return api_permissions_;
}
+
+ // Returns the set of hosts that the extension effectively has access to. This
+ // is used in the permissions UI and is a combination of the hosts accessible
+ // through content scripts and the hosts accessible through XHR.
+ const std::set<std::string> GetEffectiveHostPermissions() const;
+
+ // Whether the extension has access to all hosts. This is true if there is
+ // a content script that matches all hosts, or if there is a host permission
+ // for all hosts.
+ bool HasAccessToAllHosts() const;
+
const GURL& update_url() const { return update_url_; }
const std::map<int, std::string>& icons() { return icons_; }
@@ -230,9 +239,6 @@ class Extension {
// the browser might load (like themes and page action icons).
std::set<FilePath> GetBrowserImages();
- // Calculates and returns the permission class this extension is in.
- PermissionClass GetPermissionClass();
-
// Returns an absolute path to the given icon inside of the extension. Returns
// an empty FilePath if the extension does not have that icon.
FilePath GetIconPath(Icons icon);
@@ -359,7 +365,7 @@ class Extension {
std::vector<std::string> api_permissions_;
// The sites this extension has permission to talk to (using XHR, etc).
- std::vector<URLPattern> host_permissions_;
+ HostPermissions host_permissions_;
// The paths to the icons the extension contains mapped by their width.
std::map<int, std::string> icons_;
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 10edbbb..f0d7cce 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -21,14 +21,6 @@ namespace errors = extension_manifest_errors;
class ExtensionTest : public testing::Test {
};
-static Value* ValueFromJSON(const std::string& json_string) {
- std::string error;
- JSONStringValueSerializer content_scripts(json_string);
- Value* result = content_scripts.Deserialize(&error);
- DCHECK(result) << error;
- return result;
-}
-
TEST(ExtensionTest, InitFromValueInvalid) {
#if defined(OS_WIN)
FilePath path(FILE_PATH_LITERAL("c:\\foo"));
@@ -485,74 +477,144 @@ TEST(ExtensionTest, MimeTypeSniffing) {
EXPECT_EQ("application/octet-stream", result);
}
-TEST(ExtensionTest, PermissionClass) {
-#if defined(OS_WIN)
- FilePath path(FILE_PATH_LITERAL("C:\\foo"));
-#elif defined(OS_POSIX)
- FilePath path(FILE_PATH_LITERAL("/foo"));
-#endif
- Extension::ResetGeneratedIdCounter();
+static Extension* LoadManifest(const std::string& dir,
+ const std::string& test_file) {
+ FilePath path;
+ PathService::Get(chrome::DIR_TEST_DATA, &path);
+ path = path.AppendASCII("extensions")
+ .AppendASCII(dir)
+ .AppendASCII(test_file);
+
+ JSONFileValueSerializer serializer(path);
+ scoped_ptr<Value> result(serializer.Deserialize(NULL));
+ if (!result.get())
+ return NULL;
- Extension extension(path);
std::string error;
- DictionaryValue bare_manifest;
- scoped_ptr<DictionaryValue> manifest;
-
- // Start with a minimalist extension.
- bare_manifest.SetString(keys::kVersion, "1.0.0.0");
- bare_manifest.SetString(keys::kName, "my extension");
- EXPECT_TRUE(extension.InitFromValue(bare_manifest, false, &error));
- EXPECT_EQ(Extension::PERMISSION_CLASS_LOW, extension.GetPermissionClass());
-
- // Toolstrips don't affect the permission class.
- manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
- manifest->Set(keys::kToolstrips, ValueFromJSON(
- "[\"toolstrip.html\", \"toolstrip2.html\"]"));
- EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
- EXPECT_EQ(Extension::PERMISSION_CLASS_LOW, extension.GetPermissionClass());
-
- // Requesting API permissions bumps you to medium.
- manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
- manifest->Set(keys::kPermissions, ValueFromJSON(
- "[\"tabs\", \"bookmarks\"]"));
- EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
- EXPECT_EQ(Extension::PERMISSION_CLASS_MEDIUM, extension.GetPermissionClass());
-
- // Adding a content script bumps you to high.
- manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
- manifest->Set(keys::kContentScripts, ValueFromJSON(
- "[{"
- " \"matches\": [\"http://*.google.com/*\"],"
- " \"js\": [\"script.js\"]"
- "}]"));
- EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
- EXPECT_EQ(Extension::PERMISSION_CLASS_HIGH, extension.GetPermissionClass());
-
- // ... or asking for a host permission.
- manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
- manifest->Set(keys::kPermissions, ValueFromJSON(
- "[\"tabs\", \"http://google.com/*\"]"));
- EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
- EXPECT_EQ(Extension::PERMISSION_CLASS_HIGH, extension.GetPermissionClass());
-
- // Using native code (NPAPI) is automatically the max class.
- manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
- manifest->Set(keys::kPlugins, ValueFromJSON(
- "[{\"path\": \"harddrive_exploder.dll\"}]"));
- EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
- EXPECT_EQ(Extension::PERMISSION_CLASS_FULL, extension.GetPermissionClass());
-
- // Using everything at once should obviously be the max class as well.
- manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
- manifest->Set(keys::kPlugins, ValueFromJSON(
- "[{\"path\": \"harddrive_exploder.dll\"}]"));
- manifest->Set(keys::kPermissions, ValueFromJSON(
- "[\"tabs\", \"http://google.com/*\"]"));
- manifest->Set(keys::kContentScripts, ValueFromJSON(
- "[{"
- " \"matches\": [\"http://*.google.com/*\"],"
- " \"js\": [\"script.js\"]"
- "}]"));
- EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
- EXPECT_EQ(Extension::PERMISSION_CLASS_FULL, extension.GetPermissionClass());
+ scoped_ptr<Extension> extension(new Extension);
+ extension->InitFromValue(*static_cast<DictionaryValue*>(result.get()),
+ false, &error);
+
+ result.release();
+ return extension.release();
+}
+
+TEST(ExtensionTest, EffectiveHostPermissions) {
+ scoped_ptr<Extension> extension;
+ std::set<std::string> hosts;
+
+ extension.reset(LoadManifest("effective_host_permissions", "empty.json"));
+ EXPECT_EQ(0u, extension->GetEffectiveHostPermissions().size());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions", "one_host.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(1u, hosts.size());
+ EXPECT_TRUE(hosts.find("www.google.com") != hosts.end());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "one_host_wildcard.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(1u, hosts.size());
+ EXPECT_TRUE(hosts.find("google.com") != hosts.end());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "two_hosts.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(2u, hosts.size());
+ EXPECT_TRUE(hosts.find("www.google.com") != hosts.end());
+ EXPECT_TRUE(hosts.find("www.reddit.com") != hosts.end());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "duplicate_host.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(1u, hosts.size());
+ EXPECT_TRUE(hosts.find("google.com") != hosts.end());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "https_not_considered.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(1u, hosts.size());
+ EXPECT_TRUE(hosts.find("google.com") != hosts.end());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "two_content_scripts.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(3u, hosts.size());
+ EXPECT_TRUE(hosts.find("google.com") != hosts.end());
+ EXPECT_TRUE(hosts.find("www.reddit.com") != hosts.end());
+ EXPECT_TRUE(hosts.find("news.ycombinator.com") != hosts.end());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "duplicate_content_script.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(2u, hosts.size());
+ EXPECT_TRUE(hosts.find("google.com") != hosts.end());
+ EXPECT_TRUE(hosts.find("www.reddit.com") != hosts.end());
+ EXPECT_FALSE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "all_hosts.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(1u, hosts.size());
+ EXPECT_TRUE(hosts.find("") != hosts.end());
+ EXPECT_TRUE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "all_hosts2.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(2u, hosts.size());
+ EXPECT_TRUE(hosts.find("") != hosts.end());
+ EXPECT_TRUE(hosts.find("www.google.com") != hosts.end());
+ EXPECT_TRUE(extension->HasAccessToAllHosts());
+
+ extension.reset(LoadManifest("effective_host_permissions",
+ "all_hosts3.json"));
+ hosts = extension->GetEffectiveHostPermissions();
+ EXPECT_EQ(2u, hosts.size());
+ EXPECT_TRUE(hosts.find("") != hosts.end());
+ EXPECT_TRUE(hosts.find("www.google.com") != hosts.end());
+ EXPECT_TRUE(extension->HasAccessToAllHosts());
+}
+
+TEST(ExtensionTest, AllowSilentUpgrade) {
+ const struct {
+ const char* base_name;
+ bool expect_success;
+ } kTests[] = {
+ { "allhosts1", true }, // all -> all
+ { "allhosts2", true }, // all -> one
+ { "allhosts3", false }, // one -> all
+ { "hosts1", true }, // http://a,http://b -> http://a,http://b
+ { "hosts2", true }, // http://a,http://b -> https://a,http://*.b
+ { "hosts3", true }, // http://a,http://b -> http://a
+ { "hosts4", false }, // http://a -> http://a,http://b
+ { "permissions1", true}, // tabs -> tabs
+ { "permissions2", true}, // tabs -> tabs,bookmarks
+ { "permissions3", false}, // http://a -> http://a,tabs
+ { "permissions4", true}, // plugin -> plugin,tabs
+ { "plugin1", true}, // plugin -> plugin
+ { "plugin2", true}, // plugin -> none
+ { "plugin3", false} // none -> plugin
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
+ scoped_ptr<Extension> old_extension(
+ LoadManifest("allow_silent_upgrade",
+ std::string(kTests[i].base_name) + "_old.json"));
+ scoped_ptr<Extension> new_extension(
+ LoadManifest("allow_silent_upgrade",
+ std::string(kTests[i].base_name) + "_new.json"));
+
+ EXPECT_EQ(kTests[i].expect_success,
+ Extension::AllowSilentUpgrade(old_extension.get(),
+ new_extension.get()))
+ << kTests[i].base_name;
+ }
}
diff --git a/chrome/common/extensions/user_script.cc b/chrome/common/extensions/user_script.cc
index 22fa510..df34e52 100644
--- a/chrome/common/extensions/user_script.cc
+++ b/chrome/common/extensions/user_script.cc
@@ -14,7 +14,7 @@ bool UserScript::MatchesUrl(const GURL& url) const {
return true;
}
- for (std::vector<URLPattern>::const_iterator pattern = url_patterns_.begin();
+ for (PatternList::const_iterator pattern = url_patterns_.begin();
pattern != url_patterns_.end(); ++pattern) {
if (pattern->MatchesUrl(url))
return true;
@@ -52,7 +52,7 @@ void UserScript::Pickle(::Pickle* pickle) const {
// Write url patterns.
pickle->WriteSize(url_patterns_.size());
- for (std::vector<URLPattern>::const_iterator pattern = url_patterns_.begin();
+ for (PatternList::const_iterator pattern = url_patterns_.begin();
pattern != url_patterns_.end(); ++pattern) {
pickle->WriteString(pattern->GetAsString());
}
diff --git a/chrome/common/extensions/user_script.h b/chrome/common/extensions/user_script.h
index 57f8515..7416472 100644
--- a/chrome/common/extensions/user_script.h
+++ b/chrome/common/extensions/user_script.h
@@ -19,6 +19,8 @@ class Pickle;
// extension.
class UserScript {
public:
+ typedef std::vector<URLPattern> PatternList;
+
// Locations that user scripts can be run inside the document.
enum RunLocation {
DOCUMENT_START, // After the documentElemnet is created, but before
@@ -97,7 +99,7 @@ class UserScript {
// The URLPatterns, if any, that determine which pages this script runs
// against.
- const std::vector<URLPattern>& url_patterns() const { return url_patterns_; }
+ const PatternList& url_patterns() const { return url_patterns_; }
void add_url_pattern(const URLPattern& pattern) {
url_patterns_.push_back(pattern);
}
@@ -139,7 +141,7 @@ class UserScript {
// URLPatterns that determine pages to inject the script into. These are
// only used with scripts that are part of extensions.
- std::vector<URLPattern> url_patterns_;
+ PatternList url_patterns_;
// List of js scripts defined in content_scripts
FileList js_scripts_;
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/allhosts1_new.json b/chrome/test/data/extensions/allow_silent_upgrade/allhosts1_new.json
new file mode 100755
index 0000000..72d4b59
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/allhosts1_new.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://*/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/allhosts1_old.json b/chrome/test/data/extensions/allow_silent_upgrade/allhosts1_old.json
new file mode 100755
index 0000000..72d4b59
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/allhosts1_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://*/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/allhosts2_new.json b/chrome/test/data/extensions/allow_silent_upgrade/allhosts2_new.json
new file mode 100755
index 0000000..e29efef
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/allhosts2_new.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://google.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/allhosts2_old.json b/chrome/test/data/extensions/allow_silent_upgrade/allhosts2_old.json
new file mode 100755
index 0000000..72d4b59
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/allhosts2_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://*/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/allhosts3_new.json b/chrome/test/data/extensions/allow_silent_upgrade/allhosts3_new.json
new file mode 100755
index 0000000..72d4b59
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/allhosts3_new.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://*/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/allhosts3_old.json b/chrome/test/data/extensions/allow_silent_upgrade/allhosts3_old.json
new file mode 100755
index 0000000..c30dc11
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/allhosts3_old.json
@@ -0,0 +1,4 @@
+{
+ "name": "allow silent update",
+ "version": "1.0"
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts1_new.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts1_new.json
new file mode 100755
index 0000000..2aa5de3
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts1_new.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/",
+ "http://www.reddit.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts1_old.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts1_old.json
new file mode 100755
index 0000000..2aa5de3
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts1_old.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/",
+ "http://www.reddit.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts2_new.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts2_new.json
new file mode 100755
index 0000000..58f1f4d
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts2_new.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://*.www.google.com/",
+ "https://www.reddit.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts2_old.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts2_old.json
new file mode 100755
index 0000000..2aa5de3
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts2_old.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/",
+ "http://www.reddit.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts3_new.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts3_new.json
new file mode 100755
index 0000000..19f854d
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts3_new.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts3_old.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts3_old.json
new file mode 100755
index 0000000..2aa5de3
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts3_old.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/",
+ "http://www.reddit.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts4_new.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts4_new.json
new file mode 100755
index 0000000..2aa5de3
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts4_new.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/",
+ "http://www.reddit.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/hosts4_old.json b/chrome/test/data/extensions/allow_silent_upgrade/hosts4_old.json
new file mode 100755
index 0000000..19f854d
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/hosts4_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions1_new.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions1_new.json
new file mode 100755
index 0000000..44d20ec
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions1_new.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions1_old.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions1_old.json
new file mode 100755
index 0000000..44d20ec
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions1_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions2_new.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions2_new.json
new file mode 100755
index 0000000..eed035b
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions2_new.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "tabs",
+ "bookmarks"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions2_old.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions2_old.json
new file mode 100755
index 0000000..44d20ec
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions2_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions3_new.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions3_new.json
new file mode 100755
index 0000000..4f94df1
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions3_new.json
@@ -0,0 +1,8 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://*/*",
+ "tabs"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions3_old.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions3_old.json
new file mode 100755
index 0000000..499ea4a
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions3_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "permissions": [
+ "http://*/*"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions4_new.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions4_new.json
new file mode 100755
index 0000000..06e1e47
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions4_new.json
@@ -0,0 +1,10 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "plugins": [
+ {"path": "foo.dll"}
+ ],
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/permissions4_old.json b/chrome/test/data/extensions/allow_silent_upgrade/permissions4_old.json
new file mode 100755
index 0000000..0934ee9
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/permissions4_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "plugins": [
+ {"path": "foo.dll"}
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/plugin1_new.json b/chrome/test/data/extensions/allow_silent_upgrade/plugin1_new.json
new file mode 100755
index 0000000..d47efd7
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/plugin1_new.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "plugins": [
+ { "path": "foo.dll" }
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/plugin1_old.json b/chrome/test/data/extensions/allow_silent_upgrade/plugin1_old.json
new file mode 100755
index 0000000..d47efd7
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/plugin1_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "plugins": [
+ { "path": "foo.dll" }
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/plugin2_new.json b/chrome/test/data/extensions/allow_silent_upgrade/plugin2_new.json
new file mode 100755
index 0000000..c30dc11
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/plugin2_new.json
@@ -0,0 +1,4 @@
+{
+ "name": "allow silent update",
+ "version": "1.0"
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/plugin2_old.json b/chrome/test/data/extensions/allow_silent_upgrade/plugin2_old.json
new file mode 100755
index 0000000..d47efd7
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/plugin2_old.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "plugins": [
+ { "path": "foo.dll" }
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/plugin3_new.json b/chrome/test/data/extensions/allow_silent_upgrade/plugin3_new.json
new file mode 100755
index 0000000..d47efd7
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/plugin3_new.json
@@ -0,0 +1,7 @@
+{
+ "name": "allow silent update",
+ "version": "1.0",
+ "plugins": [
+ { "path": "foo.dll" }
+ ]
+}
diff --git a/chrome/test/data/extensions/allow_silent_upgrade/plugin3_old.json b/chrome/test/data/extensions/allow_silent_upgrade/plugin3_old.json
new file mode 100755
index 0000000..c30dc11
--- /dev/null
+++ b/chrome/test/data/extensions/allow_silent_upgrade/plugin3_old.json
@@ -0,0 +1,4 @@
+{
+ "name": "allow silent update",
+ "version": "1.0"
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/all_hosts.json b/chrome/test/data/extensions/effective_host_permissions/all_hosts.json
new file mode 100755
index 0000000..8d4c594
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/all_hosts.json
@@ -0,0 +1,7 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://*/"
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/all_hosts2.json b/chrome/test/data/extensions/effective_host_permissions/all_hosts2.json
new file mode 100755
index 0000000..662daf35
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/all_hosts2.json
@@ -0,0 +1,8 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://*/",
+ "http://www.google.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/all_hosts3.json b/chrome/test/data/extensions/effective_host_permissions/all_hosts3.json
new file mode 100755
index 0000000..ef5bd4b
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/all_hosts3.json
@@ -0,0 +1,13 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/"
+ ],
+ "content_scripts": [
+ {
+ "matches": ["https://*/"],
+ "js": ["foo.js"]
+ }
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/duplicate_content_script.json b/chrome/test/data/extensions/effective_host_permissions/duplicate_content_script.json
new file mode 100755
index 0000000..1baec13
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/duplicate_content_script.json
@@ -0,0 +1,15 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://*.google.com/",
+ "http://google.com",
+ "https://google.com"
+ ],
+ "content_scripts": [
+ {
+ "matches": ["http://www.reddit.com/", "http://google.com/"],
+ "js": ["foo.js"]
+ }
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/duplicate_host.json b/chrome/test/data/extensions/effective_host_permissions/duplicate_host.json
new file mode 100755
index 0000000..bc06d45
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/duplicate_host.json
@@ -0,0 +1,8 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://*.google.com/",
+ "http://google.com"
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/empty.json b/chrome/test/data/extensions/effective_host_permissions/empty.json
new file mode 100755
index 0000000..9b09b4a
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/empty.json
@@ -0,0 +1,4 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0"
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/https_not_considered.json b/chrome/test/data/extensions/effective_host_permissions/https_not_considered.json
new file mode 100755
index 0000000..94a7f2d
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/https_not_considered.json
@@ -0,0 +1,9 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://*.google.com/",
+ "http://google.com",
+ "https://google.com"
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/one_host.json b/chrome/test/data/extensions/effective_host_permissions/one_host.json
new file mode 100755
index 0000000..d14b62e
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/one_host.json
@@ -0,0 +1,7 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/one_host_wildcard.json b/chrome/test/data/extensions/effective_host_permissions/one_host_wildcard.json
new file mode 100755
index 0000000..b20bff8
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/one_host_wildcard.json
@@ -0,0 +1,7 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://*.google.com/"
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/two_content_scripts.json b/chrome/test/data/extensions/effective_host_permissions/two_content_scripts.json
new file mode 100755
index 0000000..a48213a
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/two_content_scripts.json
@@ -0,0 +1,15 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://*.google.com/",
+ "http://google.com",
+ "https://google.com"
+ ],
+ "content_scripts": [
+ {
+ "matches": ["http://www.reddit.com/", "http://news.ycombinator.com/"],
+ "js": ["foo.js"]
+ }
+ ]
+}
diff --git a/chrome/test/data/extensions/effective_host_permissions/two_hosts.json b/chrome/test/data/extensions/effective_host_permissions/two_hosts.json
new file mode 100755
index 0000000..997b817
--- /dev/null
+++ b/chrome/test/data/extensions/effective_host_permissions/two_hosts.json
@@ -0,0 +1,8 @@
+{
+ "name": "effective host permisions test",
+ "version": "1.0",
+ "permissions": [
+ "http://www.google.com/",
+ "http://www.reddit.com/"
+ ]
+}