summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrockot@chromium.org <rockot@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-18 06:51:08 +0000
committerrockot@chromium.org <rockot@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-18 06:51:08 +0000
commit148404701d880a8ecd7d6a88cc8a6ef01739409b (patch)
treeeeed6725bbdad642a92c7ec47c537a4964fc127a
parentc377b298e2b5e8d9360b94ef5cb8690753bb1753 (diff)
downloadchromium_src-148404701d880a8ecd7d6a88cc8a6ef01739409b.zip
chromium_src-148404701d880a8ecd7d6a88cc8a6ef01739409b.tar.gz
chromium_src-148404701d880a8ecd7d6a88cc8a6ef01739409b.tar.bz2
Add inline installer support for multiple verified sites per Web Store item.
The manifest's verified_site property is being deprecated in favor of a new property named verified_sites. This is a whitelist of verified site strings against which the client will test the requestor URL before permitting installation. Relevant server changes are still in progress, so this patch retains compatibility with the current implementation. BUG=152427 Review URL: https://chromiumcodereview.appspot.com/14198003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194814 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/webstore_inline_installer.cc57
-rw-r--r--chrome/browser/extensions/webstore_inline_installer.h3
-rw-r--r--chrome/browser/extensions/webstore_inline_installer_unittest.cc173
3 files changed, 189 insertions, 44 deletions
diff --git a/chrome/browser/extensions/webstore_inline_installer.cc b/chrome/browser/extensions/webstore_inline_installer.cc
index 356659c..517bf07 100644
--- a/chrome/browser/extensions/webstore_inline_installer.cc
+++ b/chrome/browser/extensions/webstore_inline_installer.cc
@@ -10,25 +10,24 @@
using content::WebContents;
-
namespace extensions {
const char kVerifiedSiteKey[] = "verified_site";
+const char kVerifiedSitesKey[] = "verified_sites";
const char kInlineInstallNotSupportedKey[] = "inline_install_not_supported";
const char kRedirectUrlKey[] = "redirect_url";
const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
-const char kNoVerifiedSiteError[] =
+const char kNoVerifiedSitesError[] =
"Inline installs can only be initiated for Chrome Web Store items that "
- "have a verified site";
-const char kNotFromVerifiedSiteError[] =
- "Installs can only be initiated by the Chrome Web Store item's verified "
- "site";
+ "have one or more verified sites";
+const char kNotFromVerifiedSitesError[] =
+ "Installs can only be initiated by one of the Chrome Web Store item's "
+ "verified sites";
const char kInlineInstallSupportedError[] =
"Inline installation is not supported for this item. The user will be "
"redirected to the Chrome Web Store.";
-
WebstoreInlineInstaller::WebstoreInlineInstaller(
content::WebContents* web_contents,
const std::string& webstore_item_id,
@@ -112,21 +111,45 @@ bool WebstoreInlineInstaller::CheckInlineInstallPermitted(
bool WebstoreInlineInstaller::CheckRequestorPermitted(
const base::DictionaryValue& webstore_data,
std::string* error) const {
- // Check for a verified site.
- if (!webstore_data.HasKey(kVerifiedSiteKey)) {
- *error = kNoVerifiedSiteError;
+ // Ensure that there is at least one verified site present.
+ const bool data_has_single_site = webstore_data.HasKey(kVerifiedSiteKey);
+ const bool data_has_site_list = webstore_data.HasKey(kVerifiedSitesKey);
+ if (!data_has_single_site && !data_has_site_list) {
+ *error = kNoVerifiedSitesError;
return false;
}
- std::string verified_site;
- if (!webstore_data.GetString(kVerifiedSiteKey, &verified_site)) {
- *error = kInvalidWebstoreResponseError;
- return false;
+ bool requestor_is_ok = false;
+ // Handle the deprecated single-site case.
+ if (!data_has_site_list) {
+ std::string verified_site;
+ if (!webstore_data.GetString(kVerifiedSiteKey, &verified_site)) {
+ *error = kInvalidWebstoreResponseError;
+ return false;
+ }
+ requestor_is_ok = IsRequestorURLInVerifiedSite(requestor_url_,
+ verified_site);
+ } else {
+ const base::ListValue* verified_sites = NULL;
+ if (!webstore_data.GetList(kVerifiedSitesKey, &verified_sites)) {
+ *error = kInvalidWebstoreResponseError;
+ return false;
+ }
+ for (base::ListValue::const_iterator it = verified_sites->begin();
+ it != verified_sites->end() && !requestor_is_ok; ++it) {
+ std::string verified_site;
+ if (!(*it)->GetAsString(&verified_site)) {
+ *error = kInvalidWebstoreResponseError;
+ return false;
+ }
+ if (IsRequestorURLInVerifiedSite(requestor_url_, verified_site)) {
+ requestor_is_ok = true;
+ }
+ }
}
- if (!IsRequestorURLInVerifiedSite(requestor_url_, verified_site)) {
- *error = kNotFromVerifiedSiteError;
+ if (!requestor_is_ok) {
+ *error = kNotFromVerifiedSitesError;
return false;
}
-
*error = "";
return true;
}
diff --git a/chrome/browser/extensions/webstore_inline_installer.h b/chrome/browser/extensions/webstore_inline_installer.h
index b7ae584..380e65d 100644
--- a/chrome/browser/extensions/webstore_inline_installer.h
+++ b/chrome/browser/extensions/webstore_inline_installer.h
@@ -38,7 +38,6 @@ class WebstoreInlineInstaller
protected:
friend class base::RefCountedThreadSafe<WebstoreInlineInstaller>;
- FRIEND_TEST_ALL_PREFIXES(WebstoreInlineInstallerTest, DomainVerification);
virtual ~WebstoreInlineInstaller();
@@ -62,7 +61,7 @@ class WebstoreInlineInstaller
virtual void WebContentsDestroyed(
content::WebContents* web_contents) OVERRIDE;
- // Checks whether the install is initiated by a page in the verified site
+ // Checks whether the install is initiated by a page in a verified site
// (which is at least a domain, but can also have a port or a path).
static bool IsRequestorURLInVerifiedSite(const GURL& requestor_url,
const std::string& verified_site);
diff --git a/chrome/browser/extensions/webstore_inline_installer_unittest.cc b/chrome/browser/extensions/webstore_inline_installer_unittest.cc
index fa378ea..c5b7fc9 100644
--- a/chrome/browser/extensions/webstore_inline_installer_unittest.cc
+++ b/chrome/browser/extensions/webstore_inline_installer_unittest.cc
@@ -2,74 +2,197 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
+
#include "chrome/browser/extensions/webstore_inline_installer.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
-// A macro, so that the IsRequestorURLInVerifiedSite calls are inside of the
-// the test, which is marked as a friend of WebstoreStandaloneInstaller.
-#define IsVerified(requestor_url, verified_site) \
- WebstoreInlineInstaller::IsRequestorURLInVerifiedSite( \
- GURL(requestor_url), verified_site)
+namespace {
+
+// Wraps WebstoreInlineInstaller to provide access to domain verification
+// methods for testing.
+class TestWebstoreInlineInstaller : public WebstoreInlineInstaller {
+ public:
+ explicit TestWebstoreInlineInstaller(content::WebContents* contents,
+ const std::string& requestor_url);
+
+ bool TestCheckRequestorPermitted(const base::DictionaryValue& webstore_data) {
+ std::string error;
+ return CheckRequestorPermitted(webstore_data, &error);
+ }
+
+ protected:
+ virtual ~TestWebstoreInlineInstaller();
+};
+
+void TestInstallerCallback(bool success, const std::string& error) {}
+
+TestWebstoreInlineInstaller::TestWebstoreInlineInstaller(
+ content::WebContents* contents,
+ const std::string& requestor_url)
+ : WebstoreInlineInstaller(contents,
+ "",
+ GURL(requestor_url),
+ base::Bind(&TestInstallerCallback)) {
+}
-TEST(WebstoreInlineInstallerTest, DomainVerification) {
+TestWebstoreInlineInstaller::~TestWebstoreInlineInstaller() {}
+
+// We inherit from ChromeRenderViewHostTestHarness only for
+// CreateTestWebContents, because we need a mock WebContents to support the
+// underlying WebstoreInlineInstaller in each test case.
+class WebstoreInlineInstallerTest : public ChromeRenderViewHostTestHarness {
+ public:
+ bool TestSingleVerifiedSite(const std::string& requestor_url,
+ const std::string& verified_site);
+
+ bool TestMultipleVerifiedSites(
+ const std::string& requestor_url,
+ const std::vector<std::string>& verified_sites);
+
+ protected:
+ WebstoreInlineInstallerTest()
+ : thread_(content::BrowserThread::UI, &message_loop_) {}
+
+ content::TestBrowserThread thread_;
+};
+
+// Simulates a test against the verified site string from a Webstore item's
+// "verified_site" manifest entry.
+bool WebstoreInlineInstallerTest::TestSingleVerifiedSite(
+ const std::string& requestor_url,
+ const std::string& verified_site) {
+ base::DictionaryValue webstore_data;
+ webstore_data.SetString("verified_site", verified_site);
+
+ scoped_refptr<TestWebstoreInlineInstaller> installer =
+ new TestWebstoreInlineInstaller(CreateTestWebContents(), requestor_url);
+ return installer->TestCheckRequestorPermitted(webstore_data);
+}
+
+// Simulates a test against a list of verified site strings from a Webstore
+// item's "verified_sites" manifest entry.
+bool WebstoreInlineInstallerTest::TestMultipleVerifiedSites(
+ const std::string& requestor_url,
+ const std::vector<std::string>& verified_sites) {
+ base::ListValue* sites = new base::ListValue();
+ for (std::vector<std::string>::const_iterator it = verified_sites.begin();
+ it != verified_sites.end(); ++it) {
+ sites->Append(new base::StringValue(*it));
+ }
+ base::DictionaryValue webstore_data;
+ webstore_data.Set("verified_sites", sites);
+
+ scoped_refptr<TestWebstoreInlineInstaller> installer =
+ new TestWebstoreInlineInstaller(CreateTestWebContents(), requestor_url);
+ return installer->TestCheckRequestorPermitted(webstore_data);
+}
+
+} // namespace
+
+TEST_F(WebstoreInlineInstallerTest, DomainVerification) {
// Exact domain match.
- EXPECT_TRUE(IsVerified("http://example.com", "example.com"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com", "example.com"));
// The HTTPS scheme is allowed.
- EXPECT_TRUE(IsVerified("https://example.com", "example.com"));
+ EXPECT_TRUE(TestSingleVerifiedSite("https://example.com", "example.com"));
// The file: scheme is not allowed.
- EXPECT_FALSE(IsVerified("file:///example.com", "example.com"));
+ EXPECT_FALSE(TestSingleVerifiedSite("file:///example.com", "example.com"));
// Trailing slash in URL.
- EXPECT_TRUE(IsVerified("http://example.com/", "example.com"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com/", "example.com"));
// Page on the domain.
- EXPECT_TRUE(IsVerified("http://example.com/page.html", "example.com"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com/page.html",
+ "example.com"));
// Page on a subdomain.
- EXPECT_TRUE(IsVerified("http://sub.example.com/page.html", "example.com"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://sub.example.com/page.html",
+ "example.com"));
// Root domain when only a subdomain is verified.
- EXPECT_FALSE(IsVerified("http://example.com/", "sub.example.com"));
+ EXPECT_FALSE(TestSingleVerifiedSite("http://example.com/",
+ "sub.example.com"));
// Different subdomain when only a subdomain is verified.
- EXPECT_FALSE(IsVerified("http://www.example.com/", "sub.example.com"));
+ EXPECT_FALSE(TestSingleVerifiedSite("http://www.example.com/",
+ "sub.example.com"));
// Port matches.
- EXPECT_TRUE(IsVerified("http://example.com:123/", "example.com:123"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com:123/",
+ "example.com:123"));
// Port doesn't match.
- EXPECT_FALSE(IsVerified("http://example.com:456/", "example.com:123"));
+ EXPECT_FALSE(TestSingleVerifiedSite("http://example.com:456/",
+ "example.com:123"));
// Port is missing in the requestor URL.
- EXPECT_FALSE(IsVerified("http://example.com/", "example.com:123"));
+ EXPECT_FALSE(TestSingleVerifiedSite("http://example.com/",
+ "example.com:123"));
// Port is missing in the verified site (any port matches).
- EXPECT_TRUE(IsVerified("http://example.com:123/", "example.com"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com:123/", "example.com"));
// Path matches.
- EXPECT_TRUE(IsVerified("http://example.com/path", "example.com/path"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com/path",
+ "example.com/path"));
// Path doesn't match.
- EXPECT_FALSE(IsVerified("http://example.com/foo", "example.com/path"));
+ EXPECT_FALSE(TestSingleVerifiedSite("http://example.com/foo",
+ "example.com/path"));
// Path is missing.
- EXPECT_FALSE(IsVerified("http://example.com", "example.com/path"));
+ EXPECT_FALSE(TestSingleVerifiedSite("http://example.com",
+ "example.com/path"));
// Path matches (with trailing slash).
- EXPECT_TRUE(IsVerified("http://example.com/path/", "example.com/path"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com/path/",
+ "example.com/path"));
// Path matches (is a file under the path).
- EXPECT_TRUE(IsVerified(
- "http://example.com/path/page.html", "example.com/path"));
+ EXPECT_TRUE(TestSingleVerifiedSite("http://example.com/path/page.html",
+ "example.com/path"));
// Path and port match.
- EXPECT_TRUE(IsVerified(
+ EXPECT_TRUE(TestSingleVerifiedSite(
"http://example.com:123/path/page.html", "example.com:123/path"));
+
+ std::vector<std::string> verified_sites;
+ verified_sites.push_back("foo.example.com");
+ verified_sites.push_back("bar.example.com:123");
+ verified_sites.push_back("example.com/unicorns");
+
+ // Test valid examples against the site list.
+
+ EXPECT_TRUE(TestMultipleVerifiedSites("http://foo.example.com",
+ verified_sites));
+
+ EXPECT_TRUE(TestMultipleVerifiedSites("http://bar.example.com:123",
+ verified_sites));
+
+ EXPECT_TRUE(TestMultipleVerifiedSites(
+ "http://cooking.example.com/unicorns/bacon.html", verified_sites));
+
+ // Test invalid examples against the site list.
+
+ EXPECT_FALSE(TestMultipleVerifiedSites("http://example.com",
+ verified_sites));
+
+ EXPECT_FALSE(TestMultipleVerifiedSites("file://foo.example.com",
+ verified_sites));
+
+ EXPECT_FALSE(TestMultipleVerifiedSites("http://baz.example.com",
+ verified_sites));
+
+ EXPECT_FALSE(TestMultipleVerifiedSites("http://bar.example.com:456",
+ verified_sites));
}
} // namespace extensions