1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/pepper_permission_util.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <set> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/extensions/features/feature_channel.h" 1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/extension_builder.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/extension_set.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using chrome::IsExtensionOrSharedModuleWhitelisted; 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace extensions { 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Return an extension with |id| which imports a module with the given 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |import_id|. 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_refptr<Extension> CreateExtensionImportingModule( 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& import_id, 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id) { 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<base::DictionaryValue> manifest = 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryBuilder() 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("name", "Has Dependent Modules") 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("version", "1.0") 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("manifest_version", 2) 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("import", 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ListBuilder().Append(DictionaryBuilder().Set("id", import_id))) 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Build(); 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ExtensionBuilder() 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .SetManifest(manifest.Pass()) 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .AddFlags(Extension::FROM_WEBSTORE) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .SetID(id) 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Build(); 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST(PepperPermissionUtilTest, ExtensionWhitelisting) { 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScopedCurrentChannel current_channel(chrome::VersionInfo::CHANNEL_UNKNOWN); 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionSet extensions; 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string whitelisted_id = 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) crx_file::id_util::GenerateId("whitelisted_extension"); 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<base::DictionaryValue> manifest = 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryBuilder() 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("name", "Whitelisted Extension") 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("version", "1.0") 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("manifest_version", 2) 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Build(); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<Extension> ext = ExtensionBuilder() 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .SetManifest(manifest.Pass()) 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .SetID(whitelisted_id) 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Build(); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extensions.Insert(ext); 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::set<std::string> whitelist; 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string url = std::string("chrome-extension://") + whitelisted_id + 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string("/manifest.nmf"); 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string bad_scheme_url = 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string("http://") + whitelisted_id + std::string("/manifest.nmf"); 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string bad_host_url = std::string("chrome-extension://") + 6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) crx_file::id_util::GenerateId("bad_host"); 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string("/manifest.nmf"); 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE( 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IsExtensionOrSharedModuleWhitelisted(GURL(url), &extensions, whitelist)); 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) whitelist.insert(whitelisted_id); 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE( 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IsExtensionOrSharedModuleWhitelisted(GURL(url), &extensions, whitelist)); 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted( 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL(bad_scheme_url), &extensions, whitelist)); 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted( 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL(bad_host_url), &extensions, whitelist)); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST(PepperPermissionUtilTest, SharedModuleWhitelisting) { 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScopedCurrentChannel current_channel(chrome::VersionInfo::CHANNEL_UNKNOWN); 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionSet extensions; 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string whitelisted_id = crx_file::id_util::GenerateId("extension_id"); 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string bad_id = crx_file::id_util::GenerateId("bad_id"); 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<base::DictionaryValue> shared_module_manifest = 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryBuilder() 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("name", "Whitelisted Shared Module") 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("version", "1.0") 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("manifest_version", 2) 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("export", 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryBuilder() 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("resources", ListBuilder().Append("*")) 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Add the extension to the whitelist. This 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // restricts import to |whitelisted_id| only. 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Set("whitelist", ListBuilder().Append(whitelisted_id))) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .Build(); 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<Extension> shared_module = 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionBuilder().SetManifest(shared_module_manifest.Pass()).Build(); 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<Extension> ext = 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateExtensionImportingModule(shared_module->id(), whitelisted_id); 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string extension_url = 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string("chrome-extension://") + ext->id() + std::string("/foo.html"); 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::set<std::string> whitelist; 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Important: whitelist *only* the shared module. 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) whitelist.insert(shared_module->id()); 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extensions.Insert(ext); 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This should fail because shared_module is not in the set of extensions. 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted( 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL(extension_url), &extensions, whitelist)); 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extensions.Insert(shared_module); 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(IsExtensionOrSharedModuleWhitelisted( 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL(extension_url), &extensions, whitelist)); 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<Extension> not_in_sm_whitelist = 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateExtensionImportingModule(shared_module->id(), bad_id); 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string not_in_sm_whitelist_url = std::string("chrome-extension://") + 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci not_in_sm_whitelist->id() + 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string("/foo.html"); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions.Insert(not_in_sm_whitelist); 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This should succeed, even though |not_in_sm_whitelist| is not whitelisted 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to use shared_module, because the pepper permission utility does not care 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // about that whitelist. It is possible to install against the whitelist as 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // an unpacked extension. 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(IsExtensionOrSharedModuleWhitelisted( 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL(not_in_sm_whitelist_url), &extensions, whitelist)); 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Note that the whitelist should be empty after this call, so tests checking 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // for failure to import will fail because of this. 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) whitelist.erase(shared_module->id()); 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(IsExtensionOrSharedModuleWhitelisted( 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL(extension_url), &extensions, whitelist)); 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace extensions 140