15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/features/feature.h"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/features/simple_feature.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/install_warning.h"
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors;
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace keys = manifest_keys;
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Not named "ManifestTest" because a test utility class has that name.
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ManifestUnitTest : public testing::Test {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ManifestUnitTest() : default_value_("test") {}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AssertType(Manifest* manifest, Manifest::Type type) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(type, manifest->type());
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(type == Manifest::TYPE_THEME, manifest->is_theme());
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(type == Manifest::TYPE_PLATFORM_APP,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              manifest->is_platform_app());
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(type == Manifest::TYPE_LEGACY_PACKAGED_APP,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              manifest->is_legacy_packaged_app());
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(type == Manifest::TYPE_HOSTED_APP, manifest->is_hosted_app());
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_EQ(type == Manifest::TYPE_SHARED_MODULE,
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              manifest->is_shared_module());
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper function that replaces the Manifest held by |manifest| with a copy
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with its |key| changed to |value|. If |value| is NULL, then |key| will
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instead be deleted.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MutateManifest(scoped_ptr<Manifest>* manifest,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      const std::string& key,
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      base::Value* value) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> manifest_value(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest->get()->value()->DeepCopy());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manifest_value->Set(key, value);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manifest_value->Remove(key, NULL);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manifest->reset(new Manifest(Manifest::INTERNAL, manifest_value.Pass()));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string default_value_;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies that extensions can access the correct keys.
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(ManifestUnitTest, Extension) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> manifest_value(new base::DictionaryValue());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_value->SetString(keys::kName, "extension");
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_value->SetString(keys::kVersion, "1");
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only supported in manifest_version=1.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_value->SetString(keys::kBackgroundPageLegacy, "bg.html");
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_value->SetString("unknown_key", "foo");
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Manifest> manifest(
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new Manifest(Manifest::INTERNAL, manifest_value.Pass()));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string error;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<InstallWarning> warnings;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(manifest->ValidateManifest(&error, &warnings));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(error.empty());
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, warnings.size());
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_EXTENSION);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The known key 'background_page' should be accessible.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(manifest->GetString(keys::kBackgroundPageLegacy, &value));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bg.html", value);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The unknown key 'unknown_key' should be accesible.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value.clear();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(manifest->GetString("unknown_key", &value));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("foo", value);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the manifest_version to 2; background_page should stop working.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value.clear();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kManifestVersion, new base::FundamentalValue(2));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(manifest->GetString("background_page", &value));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("", value);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate should also give a warning.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  warnings.clear();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(manifest->ValidateManifest(&error, &warnings));
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(error.empty());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, warnings.size());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SimpleFeature feature;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    feature.set_name("background_page");
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    feature.set_max_manifest_version(1);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "'background_page' requires manifest version of 1 or lower.",
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        warnings[0].message);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test DeepCopy and Equals.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Manifest> manifest2(manifest->DeepCopy());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(manifest->Equals(manifest2.get()));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(manifest2->Equals(manifest.get()));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, "foo", new base::StringValue("blah"));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(manifest->Equals(manifest2.get()));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies that key restriction based on type works.
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(ManifestUnitTest, ExtensionTypes) {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString(keys::kName, "extension");
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString(keys::kVersion, "1");
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Manifest> manifest(
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new Manifest(Manifest::INTERNAL, value.Pass()));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string error;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<InstallWarning> warnings;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(manifest->ValidateManifest(&error, &warnings));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(error.empty());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(warnings.empty());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By default, the type is Extension.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_EXTENSION);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Theme.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kTheme, new base::DictionaryValue());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_THEME);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &manifest, keys::kTheme, NULL);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Shared module.
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MutateManifest(
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &manifest, keys::kExport, new base::DictionaryValue());
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_SHARED_MODULE);
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MutateManifest(
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &manifest, keys::kExport, NULL);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Packaged app.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kApp, new base::DictionaryValue());
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_LEGACY_PACKAGED_APP);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Platform app with event page.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kPlatformAppBackground, new base::DictionaryValue());
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_PLATFORM_APP);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &manifest, keys::kPlatformAppBackground, NULL);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hosted app.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kWebURLs, new base::ListValue());
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_HOSTED_APP);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &manifest, keys::kWebURLs, NULL);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kLaunchWebURL, new base::StringValue("foo"));
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_HOSTED_APP);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &manifest, keys::kLaunchWebURL, NULL);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies that the getters filter restricted keys.
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(ManifestUnitTest, RestrictedKeys) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString(keys::kName, "extension");
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString(keys::kVersion, "1");
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Manifest> manifest(
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new Manifest(Manifest::INTERNAL, value.Pass()));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string error;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<InstallWarning> warnings;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(manifest->ValidateManifest(&error, &warnings));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(error.empty());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(warnings.empty());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // "Commands" requires manifest version 2.
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::Value* output = NULL;
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MutateManifest(
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &manifest, keys::kCommands, new base::DictionaryValue());
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manifest->HasKey(keys::kCommands));
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manifest->Get(keys::kCommands, &output));
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MutateManifest(
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &manifest, keys::kManifestVersion, new base::FundamentalValue(2));
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manifest->HasKey(keys::kCommands));
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manifest->Get(keys::kCommands, &output));
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kPageAction, new base::DictionaryValue());
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_EXTENSION);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(manifest->HasKey(keys::kPageAction));
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(manifest->Get(keys::kPageAction, &output));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Platform apps cannot have a "page_action" key.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &manifest, keys::kPlatformAppBackground, new base::DictionaryValue());
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertType(manifest.get(), Manifest::TYPE_PLATFORM_APP);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(manifest->HasKey(keys::kPageAction));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(manifest->Get(keys::kPageAction, &output));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutateManifest(
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &manifest, keys::kPlatformAppBackground, NULL);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Platform apps also can't have a "Commands" key.
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manifest->HasKey(keys::kCommands));
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manifest->Get(keys::kCommands, &output));
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
223