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