extension_manifests_platformapp_unittest.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/command_line.h" 6#include "base/json/json_file_value_serializer.h" 7#include "base/memory/linked_ptr.h" 8#include "chrome/common/chrome_switches.h" 9#include "chrome/common/extensions/csp_handler.h" 10#include "chrome/common/extensions/extension_manifest_constants.h" 11#include "chrome/common/extensions/incognito_handler.h" 12#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" 13#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h" 14#include "extensions/common/error_utils.h" 15#include "extensions/common/switches.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18namespace errors = extension_manifest_errors; 19 20namespace extensions { 21 22class PlatformAppsManifestTest : public ExtensionManifestTest { 23}; 24 25TEST_F(PlatformAppsManifestTest, PlatformApps) { 26 scoped_refptr<Extension> extension = 27 LoadAndExpectSuccess("init_valid_platform_app.json"); 28 EXPECT_TRUE(AppIsolationInfo::HasIsolatedStorage(extension.get())); 29 EXPECT_TRUE(IncognitoInfo::IsSplitMode(extension.get())); 30 31 extension = 32 LoadAndExpectSuccess("init_valid_platform_app_no_manifest_version.json"); 33 EXPECT_EQ(2, extension->manifest_version()); 34 35 extension = LoadAndExpectSuccess("incognito_valid_platform_app.json"); 36 EXPECT_TRUE(IncognitoInfo::IsSplitMode(extension.get())); 37 38 Testcase error_testcases[] = { 39 Testcase("init_invalid_platform_app_2.json", 40 errors::kBackgroundRequiredForPlatformApps), 41 Testcase("init_invalid_platform_app_3.json", 42 ErrorUtils::FormatErrorMessage( 43 errors::kInvalidManifestVersionOld, "2", "apps")), 44 }; 45 RunTestcases(error_testcases, arraysize(error_testcases), EXPECT_TYPE_ERROR); 46 47 Testcase warning_testcases[] = { 48 Testcase( 49 "init_invalid_platform_app_1.json", 50 "'app.launch' is only allowed for hosted apps and legacy packaged " 51 "apps, and this is a packaged app."), 52 Testcase( 53 "init_invalid_platform_app_4.json", 54 "'background' is only allowed for extensions, hosted apps and legacy " 55 "packaged apps, and this is a packaged app."), 56 Testcase( 57 "init_invalid_platform_app_5.json", 58 "'background' is only allowed for extensions, hosted apps and legacy " 59 "packaged apps, and this is a packaged app."), 60 Testcase("incognito_invalid_platform_app.json", 61 "'incognito' is only allowed for extensions and legacy packaged apps, " 62 "and this is a packaged app."), 63 }; 64 RunTestcases( 65 warning_testcases, arraysize(warning_testcases), EXPECT_TYPE_WARNING); 66} 67 68TEST_F(PlatformAppsManifestTest, PlatformAppContentSecurityPolicy) { 69 // Normal platform apps can't specify a CSP value. 70 Testcase warning_testcases[] = { 71 Testcase( 72 "init_platform_app_csp_warning_1.json", 73 "'content_security_policy' is only allowed for extensions and legacy " 74 "packaged apps, and this is a packaged app."), 75 Testcase( 76 "init_platform_app_csp_warning_2.json", 77 "'app.content_security_policy' is not allowed for specified extension " 78 "ID.") 79 }; 80 RunTestcases( 81 warning_testcases, arraysize(warning_testcases), EXPECT_TYPE_WARNING); 82 83 // Whitelisted ones can (this is the ID corresponding to the base 64 encoded 84 // key in the init_platform_app_csp.json manifest.) 85 std::string test_id = "ahplfneplbnjcflhdgkkjeiglkkfeelb"; 86 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 87 ::switches::kWhitelistedExtensionID, test_id); 88 scoped_refptr<Extension> extension = 89 LoadAndExpectSuccess("init_platform_app_csp.json"); 90 EXPECT_EQ(0U, extension->install_warnings().size()) 91 << "Unexpected warning " << extension->install_warnings()[0].message; 92 EXPECT_TRUE(extension->is_platform_app()); 93 EXPECT_EQ("default-src 'self' https://www.google.com", 94 CSPInfo::GetResourceContentSecurityPolicy(extension.get(), 95 std::string())); 96 97 // But even whitelisted ones must specify a secure policy. 98 LoadAndExpectError( 99 "init_platform_app_csp_insecure.json", 100 errors::kInsecureContentSecurityPolicy); 101} 102 103TEST_F(PlatformAppsManifestTest, CertainApisRequirePlatformApps) { 104 // Put APIs here that should be restricted to platform apps, but that haven't 105 // yet graduated from experimental. 106 const char* kPlatformAppExperimentalApis[] = { 107 "dns", 108 "serial", 109 }; 110 // TODO(miket): When the first platform-app API leaves experimental, write 111 // similar code that tests without the experimental flag. 112 113 // This manifest is a skeleton used to build more specific manifests for 114 // testing. The requirements are that (1) it be a valid platform app, and (2) 115 // it contain no permissions dictionary. 116 std::string error; 117 scoped_ptr<base::DictionaryValue> manifest( 118 LoadManifest("init_valid_platform_app.json", &error)); 119 120 std::vector<linked_ptr<DictionaryValue> > manifests; 121 // Create each manifest. 122 for (size_t i = 0; i < arraysize(kPlatformAppExperimentalApis); ++i) { 123 const char* api_name = kPlatformAppExperimentalApis[i]; 124 125 // DictionaryValue will take ownership of this ListValue. 126 base::ListValue *permissions = new base::ListValue(); 127 permissions->Append(new base::StringValue("experimental")); 128 permissions->Append(new base::StringValue(api_name)); 129 manifest->Set("permissions", permissions); 130 manifests.push_back(make_linked_ptr(manifest->DeepCopy())); 131 } 132 133 // First try to load without any flags. This should fail for every API. 134 for (size_t i = 0; i < arraysize(kPlatformAppExperimentalApis); ++i) { 135 LoadAndExpectError(Manifest(manifests[i].get(), ""), 136 errors::kExperimentalFlagRequired); 137 } 138 139 // Now try again with the experimental flag set. 140 CommandLine::ForCurrentProcess()->AppendSwitch( 141 switches::kEnableExperimentalExtensionApis); 142 for (size_t i = 0; i < arraysize(kPlatformAppExperimentalApis); ++i) { 143 LoadAndExpectSuccess(Manifest(manifests[i].get(), "")); 144 } 145} 146 147} // namespace extensions 148