extension_manifests_platformapp_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "chrome/common/extensions/manifest_tests/extension_manifest_test.h" 6 7#include "base/command_line.h" 8#include "base/json/json_file_value_serializer.h" 9#include "base/scoped_temp_dir.h" 10#include "chrome/common/chrome_switches.h" 11#include "chrome/common/extensions/extension_manifest_constants.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14namespace errors = extension_manifest_errors; 15 16TEST_F(ExtensionManifestTest, PlatformApps) { 17 scoped_refptr<extensions::Extension> extension = 18 LoadAndExpectSuccess("init_valid_platform_app.json"); 19 EXPECT_TRUE(extension->is_storage_isolated()); 20 EXPECT_TRUE(extension->incognito_split_mode()); 21 22 extension = 23 LoadAndExpectSuccess("init_valid_platform_app_no_manifest_version.json"); 24 EXPECT_EQ(2, extension->manifest_version()); 25 26 extension = LoadAndExpectSuccess("incognito_valid_platform_app.json"); 27 EXPECT_TRUE(extension->incognito_split_mode()); 28 29 Testcase error_testcases[] = { 30 Testcase("init_invalid_platform_app_2.json", 31 errors::kBackgroundRequiredForPlatformApps), 32 Testcase("init_invalid_platform_app_3.json", 33 errors::kPlatformAppNeedsManifestVersion2), 34 Testcase("incognito_invalid_platform_app.json", 35 errors::kInvalidIncognitoModeForPlatformApp), 36 }; 37 RunTestcases(error_testcases, arraysize(error_testcases), EXPECT_TYPE_ERROR); 38 39 Testcase warning_testcases[] = { 40 Testcase( 41 "init_invalid_platform_app_1.json", 42 "'app.launch' is only allowed for hosted apps and legacy packaged " 43 "apps, and this is a packaged app."), 44 Testcase( 45 "init_invalid_platform_app_4.json", 46 "'background' is only allowed for extensions, hosted apps and legacy " 47 "packaged apps, and this is a packaged app."), 48 Testcase( 49 "init_invalid_platform_app_5.json", 50 "'background' is only allowed for extensions, hosted apps and legacy " 51 "packaged apps, and this is a packaged app.") 52 }; 53 RunTestcases( 54 warning_testcases, arraysize(warning_testcases), EXPECT_TYPE_WARNING); 55} 56 57TEST_F(ExtensionManifestTest, PlatformAppContentSecurityPolicy) { 58 // Normal platform apps can't specify a CSP value. 59 Testcase warning_testcases[] = { 60 Testcase( 61 "init_platform_app_csp_warning_1.json", 62 "'content_security_policy' is only allowed for extensions and legacy " 63 "packaged apps, and this is a packaged app."), 64 Testcase( 65 "init_platform_app_csp_warning_2.json", 66 "'app.content_security_policy' is not allowed for specified extension " 67 "ID.") 68 }; 69 RunTestcases( 70 warning_testcases, arraysize(warning_testcases), EXPECT_TYPE_WARNING); 71 72 // Whitelisted ones can (this is the ID corresponding to the base 64 encoded 73 // key in the init_platform_app_csp.json manifest.) 74 std::string test_id = "ahplfneplbnjcflhdgkkjeiglkkfeelb"; 75 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 76 switches::kWhitelistedExtensionID, test_id); 77 scoped_refptr<extensions::Extension> extension = 78 LoadAndExpectSuccess("init_platform_app_csp.json"); 79 EXPECT_EQ(0U, extension->install_warnings().size()) 80 << "Unexpected warning " << extension->install_warnings()[0].message; 81 EXPECT_TRUE(extension->is_platform_app()); 82 EXPECT_EQ( 83 "default-src 'self' https://www.google.com", 84 extension->GetResourceContentSecurityPolicy("")); 85 86 // But even whitelisted ones must specify a secure policy. 87 LoadAndExpectError( 88 "init_platform_app_csp_insecure.json", 89 errors::kInsecureContentSecurityPolicy); 90} 91 92TEST_F(ExtensionManifestTest, CertainApisRequirePlatformApps) { 93 // Put APIs here that should be restricted to platform apps, but that haven't 94 // yet graduated from experimental. 95 const char* kPlatformAppExperimentalApis[] = { 96 "dns", 97 "serial", 98 }; 99 // TODO(miket): When the first platform-app API leaves experimental, write 100 // similar code that tests without the experimental flag. 101 102 // This manifest is a skeleton used to build more specific manifests for 103 // testing. The requirements are that (1) it be a valid platform app, and (2) 104 // it contain no permissions dictionary. 105 std::string error; 106 scoped_ptr<DictionaryValue> manifest( 107 LoadManifestFile("init_valid_platform_app.json", &error)); 108 109 ScopedTempDir temp_dir; 110 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 111 112 // Create each manifest. 113 for (size_t i = 0; i < arraysize(kPlatformAppExperimentalApis); ++i) { 114 const char* api_name = kPlatformAppExperimentalApis[i]; 115 116 // DictionaryValue will take ownership of this ListValue. 117 ListValue *permissions = new ListValue(); 118 permissions->Append(base::Value::CreateStringValue("experimental")); 119 permissions->Append(base::Value::CreateStringValue(api_name)); 120 manifest->Set("permissions", permissions); 121 122 // Each of these files lives in the scoped temp directory, so it will be 123 // cleaned up at test teardown. 124 FilePath file_path = temp_dir.path().AppendASCII(api_name); 125 JSONFileValueSerializer serializer(file_path); 126 serializer.Serialize(*(manifest.get())); 127 } 128 129 // First try to load without any flags. This should fail for every API. 130 for (size_t i = 0; i < arraysize(kPlatformAppExperimentalApis); ++i) { 131 const char* api_name = kPlatformAppExperimentalApis[i]; 132 FilePath file_path = temp_dir.path().AppendASCII(api_name); 133 LoadAndExpectError(file_path.MaybeAsASCII().c_str(), 134 errors::kExperimentalFlagRequired); 135 } 136 137 // Now try again with the experimental flag set. 138 CommandLine::ForCurrentProcess()->AppendSwitch( 139 switches::kEnableExperimentalExtensionApis); 140 for (size_t i = 0; i < arraysize(kPlatformAppExperimentalApis); ++i) { 141 const char* api_name = kPlatformAppExperimentalApis[i]; 142 FilePath file_path = temp_dir.path().AppendASCII(api_name); 143 LoadAndExpectSuccess(file_path.MaybeAsASCII().c_str()); 144 } 145} 146