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