summaryrefslogtreecommitdiff
path: root/chromium/extensions/common/manifest_handlers
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/extensions/common/manifest_handlers')
-rw-r--r--chromium/extensions/common/manifest_handlers/app_isolation_info.cc1
-rw-r--r--chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.cc145
-rw-r--r--chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.h62
-rw-r--r--chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons_unittest.cc87
-rw-r--r--chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.cc195
-rw-r--r--chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.h70
-rw-r--r--chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items_unittest.cc135
7 files changed, 401 insertions, 294 deletions
diff --git a/chromium/extensions/common/manifest_handlers/app_isolation_info.cc b/chromium/extensions/common/manifest_handlers/app_isolation_info.cc
index dba036aa573..66fb4cad4ea 100644
--- a/chromium/extensions/common/manifest_handlers/app_isolation_info.cc
+++ b/chromium/extensions/common/manifest_handlers/app_isolation_info.cc
@@ -8,6 +8,7 @@
#include <memory>
+#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.cc b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.cc
deleted file mode 100644
index 8fc3404310a..00000000000
--- a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/common/manifest_handlers/web_app_linked_shortcut_icons.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/no_destructor.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "extensions/common/manifest.h"
-#include "extensions/common/manifest_constants.h"
-
-namespace extensions {
-
-namespace keys = manifest_keys;
-namespace errors = manifest_errors;
-
-namespace {
-
-bool ParseShortcutIconValue(const base::Value& value,
- WebAppLinkedShortcutIcons::ShortcutIconInfo* info,
- base::string16* error) {
- const base::DictionaryValue* shortcut_icon_dict = nullptr;
- if (!value.GetAsDictionary(&shortcut_icon_dict)) {
- *error =
- base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutIcon);
- return false;
- }
-
- std::string url_string;
- if (!shortcut_icon_dict->GetString(keys::kWebAppLinkedShortcutIconURL,
- &url_string)) {
- *error =
- base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutIconURL);
- return false;
- }
-
- info->url = GURL(url_string);
- if (!info->url.is_valid()) {
- *error =
- base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutIconURL);
- return false;
- }
-
- if (!shortcut_icon_dict->GetInteger(keys::kWebAppLinkedShortcutIconSize,
- &info->size)) {
- *error = base::UTF8ToUTF16(
- manifest_errors::kInvalidWebAppLinkedShortcutIconSize);
- return false;
- }
-
- if (!shortcut_icon_dict->GetInteger(keys::kWebAppLinkedShortcutItemIndex,
- &info->shortcut_item_index)) {
- *error = base::UTF8ToUTF16(
- manifest_errors::kInvalidWebAppLinkedShortcutItemIndex);
- return false;
- }
-
- if (!shortcut_icon_dict->GetString(keys::kWebAppLinkedShortcutItemName,
- &info->shortcut_item_name)) {
- *error = base::UTF8ToUTF16(
- manifest_errors::kInvalidWebAppLinkedShortcutItemName);
- return false;
- }
- return true;
-}
-
-} // namespace
-
-WebAppLinkedShortcutIcons::ShortcutIconInfo::ShortcutIconInfo() = default;
-
-WebAppLinkedShortcutIcons::ShortcutIconInfo::~ShortcutIconInfo() = default;
-
-WebAppLinkedShortcutIcons::WebAppLinkedShortcutIcons() = default;
-
-WebAppLinkedShortcutIcons::WebAppLinkedShortcutIcons(
- const WebAppLinkedShortcutIcons& other) = default;
-
-WebAppLinkedShortcutIcons::~WebAppLinkedShortcutIcons() = default;
-
-// static
-const WebAppLinkedShortcutIcons&
-WebAppLinkedShortcutIcons::GetWebAppLinkedShortcutIcons(
- const Extension* extension) {
- WebAppLinkedShortcutIcons* info = static_cast<WebAppLinkedShortcutIcons*>(
- extension->GetManifestData(keys::kWebAppLinkedShortcutIcons));
- if (info)
- return *info;
-
- static base::NoDestructor<WebAppLinkedShortcutIcons>
- empty_web_app_linked_shortcut_icons;
- return *empty_web_app_linked_shortcut_icons;
-}
-
-WebAppLinkedShortcutIconsHandler::WebAppLinkedShortcutIconsHandler() = default;
-
-WebAppLinkedShortcutIconsHandler::~WebAppLinkedShortcutIconsHandler() = default;
-
-bool WebAppLinkedShortcutIconsHandler::Parse(Extension* extension,
- base::string16* error) {
- // The "web_app_linked_shortcut_icons" key is only available for Bookmark
- // Apps. Including it elsewhere results in an install warning, and the linked
- // shortcut icons are not parsed.
- if (!extension->from_bookmark()) {
- extension->AddInstallWarning(InstallWarning(
- errors::kInvalidWebAppLinkedShortcutIconsNotBookmarkApp));
- return true;
- }
-
- auto web_app_linked_shortcut_icons =
- std::make_unique<WebAppLinkedShortcutIcons>();
-
- const base::Value* shortcut_icons_value = nullptr;
- if (!extension->manifest()->GetList(keys::kWebAppLinkedShortcutIcons,
- &shortcut_icons_value)) {
- *error =
- base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutIcons);
- return false;
- }
-
- base::Value::ConstListView shortcut_icons_list =
- shortcut_icons_value->GetList();
- web_app_linked_shortcut_icons->shortcut_icon_infos.reserve(
- shortcut_icons_list.size());
- for (const auto& shortcut_icon_value : shortcut_icons_list) {
- WebAppLinkedShortcutIcons::ShortcutIconInfo info;
- if (!ParseShortcutIconValue(shortcut_icon_value, &info, error)) {
- return false;
- }
- web_app_linked_shortcut_icons->shortcut_icon_infos.push_back(info);
- }
- extension->SetManifestData(keys::kWebAppLinkedShortcutIcons,
- std::move(web_app_linked_shortcut_icons));
- return true;
-}
-
-base::span<const char* const> WebAppLinkedShortcutIconsHandler::Keys() const {
- static constexpr const char* kKeys[] = {keys::kWebAppLinkedShortcutIcons};
- return kKeys;
-}
-
-} // namespace extensions
diff --git a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.h b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.h
deleted file mode 100644
index 6cbe933882f..00000000000
--- a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_APP_LINKED_SHORTCUT_ICONS_H_
-#define EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_APP_LINKED_SHORTCUT_ICONS_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/manifest_handler.h"
-
-class GURL;
-
-namespace extensions {
-
-// A structure to hold the parsed web app linked shortcut icon data.
-struct WebAppLinkedShortcutIcons : public Extension::ManifestData {
- struct ShortcutIconInfo {
- ShortcutIconInfo();
- ~ShortcutIconInfo();
-
- int shortcut_item_index;
- base::string16 shortcut_item_name;
- GURL url;
- int size;
- };
-
- WebAppLinkedShortcutIcons();
- WebAppLinkedShortcutIcons(const WebAppLinkedShortcutIcons& other);
- ~WebAppLinkedShortcutIcons() override;
-
- static const WebAppLinkedShortcutIcons& GetWebAppLinkedShortcutIcons(
- const Extension* extension);
-
- std::vector<ShortcutIconInfo> shortcut_icon_infos;
-};
-
-// Parses the "web_app_linked_shortcut_icons" manifest key.
-class WebAppLinkedShortcutIconsHandler : public ManifestHandler {
- public:
- WebAppLinkedShortcutIconsHandler();
- ~WebAppLinkedShortcutIconsHandler() override;
- WebAppLinkedShortcutIconsHandler(const WebAppLinkedShortcutIconsHandler&) =
- delete;
- WebAppLinkedShortcutIconsHandler& operator=(
- const WebAppLinkedShortcutIconsHandler&) = delete;
-
- // ManifestHandler:
- bool Parse(Extension* extension, base::string16* error) override;
-
- private:
- // ManifestHandler:
- base::span<const char* const> Keys() const override;
-};
-
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_APP_LINKED_SHORTCUT_ICONS_H_
diff --git a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons_unittest.cc b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons_unittest.cc
deleted file mode 100644
index 8630a351929..00000000000
--- a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_icons_unittest.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "extensions/common/extension.h"
-#include "extensions/common/manifest.h"
-#include "extensions/common/manifest_constants.h"
-#include "extensions/common/manifest_handlers/web_app_linked_shortcut_icons.h"
-#include "extensions/common/manifest_test.h"
-
-namespace extensions {
-
-namespace errors = manifest_errors;
-
-using WebAppLinkedShortcutIconsHandlerTest = ManifestTest;
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, Valid) {
- scoped_refptr<Extension> extension =
- LoadAndExpectSuccess("web_app_linked_shortcut_icons_valid.json",
- extensions::Manifest::Location::INTERNAL,
- extensions::Extension::FROM_BOOKMARK);
- ASSERT_TRUE(extension.get());
- ASSERT_TRUE(extension->from_bookmark());
-}
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, InvalidNotFromBookmarkApp) {
- scoped_refptr<Extension> extension =
- LoadAndExpectSuccess("web_app_linked_shortcut_icons_valid.json");
-
- ASSERT_TRUE(extension.get());
- ASSERT_FALSE(extension->from_bookmark());
-
- std::vector<InstallWarning> expected_install_warnings;
- expected_install_warnings.push_back(
- InstallWarning(errors::kInvalidWebAppLinkedShortcutIconsNotBookmarkApp));
- EXPECT_EQ(expected_install_warnings, extension->install_warnings());
-
- const WebAppLinkedShortcutIcons& web_app_linked_shortcut_icons =
- WebAppLinkedShortcutIcons::GetWebAppLinkedShortcutIcons(extension.get());
- ASSERT_TRUE(web_app_linked_shortcut_icons.shortcut_icon_infos.empty());
-}
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, InvalidLinkedShortcutIndex) {
- LoadAndExpectError("web_app_linked_shortcut_icons_invalid1.json",
- errors::kInvalidWebAppLinkedShortcutItemIndex,
- extensions::Manifest::Location::INTERNAL,
- extensions::Extension::FROM_BOOKMARK);
-}
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, InvalidLinkedShortcutName) {
- LoadAndExpectError("web_app_linked_shortcut_icons_invalid2.json",
- errors::kInvalidWebAppLinkedShortcutItemName,
- extensions::Manifest::Location::INTERNAL,
- extensions::Extension::FROM_BOOKMARK);
-}
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, InvalidLinkedShortcutIconUrl) {
- LoadAndExpectError("web_app_linked_shortcut_icons_invalid3.json",
- errors::kInvalidWebAppLinkedShortcutIconURL,
- extensions::Manifest::Location::INTERNAL,
- extensions::Extension::FROM_BOOKMARK);
-}
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, InvalidLinkedShortcutIconSize) {
- LoadAndExpectError("web_app_linked_shortcut_icons_invalid4.json",
- errors::kInvalidWebAppLinkedShortcutIconSize,
- extensions::Manifest::Location::INTERNAL,
- extensions::Extension::FROM_BOOKMARK);
-}
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, InvalidLinkedShortcutIcons) {
- LoadAndExpectError("web_app_linked_shortcut_icons_invalid5.json",
- errors::kInvalidWebAppLinkedShortcutIcons,
- extensions::Manifest::Location::INTERNAL,
- extensions::Extension::FROM_BOOKMARK);
-}
-
-TEST_F(WebAppLinkedShortcutIconsHandlerTest, InvalidLinkedShortcutIcon) {
- LoadAndExpectError("web_app_linked_shortcut_icons_invalid6.json",
- errors::kInvalidWebAppLinkedShortcutIcon,
- extensions::Manifest::Location::INTERNAL,
- extensions::Extension::FROM_BOOKMARK);
-}
-
-} // namespace extensions
diff --git a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.cc b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.cc
new file mode 100644
index 00000000000..e2e7b21bfc9
--- /dev/null
+++ b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.cc
@@ -0,0 +1,195 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/manifest_handlers/web_app_linked_shortcut_items.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/no_destructor.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/manifest_constants.h"
+
+namespace extensions {
+
+namespace keys = manifest_keys;
+namespace errors = manifest_errors;
+
+namespace {
+
+bool ParseShortcutItemIconValue(
+ const base::Value& value,
+ WebAppLinkedShortcutItems::ShortcutItemInfo::IconInfo* icon_info,
+ base::string16* error) {
+ const base::DictionaryValue* shortcut_item_icon_dict = nullptr;
+ if (!value.GetAsDictionary(&shortcut_item_icon_dict)) {
+ *error = base::UTF8ToUTF16(
+ manifest_errors::kInvalidWebAppLinkedShortcutItemIcon);
+ return false;
+ }
+
+ std::string icon_url;
+ if (!shortcut_item_icon_dict->GetString(
+ keys::kWebAppLinkedShortcutItemIconURL, &icon_url)) {
+ *error = base::UTF8ToUTF16(
+ manifest_errors::kInvalidWebAppLinkedShortcutItemIconUrl);
+ return false;
+ }
+
+ icon_info->url = GURL(icon_url);
+ if (!icon_info->url.is_valid()) {
+ *error = base::UTF8ToUTF16(
+ manifest_errors::kInvalidWebAppLinkedShortcutItemIconUrl);
+ return false;
+ }
+
+ if (!shortcut_item_icon_dict->GetInteger(
+ keys::kWebAppLinkedShortcutItemIconSize, &icon_info->size)) {
+ *error = base::UTF8ToUTF16(
+ manifest_errors::kInvalidWebAppLinkedShortcutItemIconSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ParseShortcutItemValue(const base::Value& value,
+ WebAppLinkedShortcutItems::ShortcutItemInfo* info,
+ base::string16* error) {
+ const base::DictionaryValue* shortcut_item_dict = nullptr;
+ if (!value.GetAsDictionary(&shortcut_item_dict)) {
+ *error =
+ base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutItem);
+ return false;
+ }
+
+ if (!shortcut_item_dict->GetString(keys::kWebAppLinkedShortcutItemName,
+ &info->name)) {
+ *error = base::UTF8ToUTF16(
+ manifest_errors::kInvalidWebAppLinkedShortcutItemName);
+ return false;
+ }
+
+ std::string url_string;
+ if (!shortcut_item_dict->GetString(keys::kWebAppLinkedShortcutItemURL,
+ &url_string)) {
+ *error =
+ base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutItemUrl);
+ return false;
+ }
+
+ info->url = GURL(url_string);
+ if (!info->url.is_valid()) {
+ *error =
+ base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutItemUrl);
+ return false;
+ }
+
+ const base::ListValue* shortcut_item_icons_value = nullptr;
+ if (!shortcut_item_dict->GetList(keys::kWebAppLinkedShortcutItemIcons,
+ &shortcut_item_icons_value)) {
+ *error = base::UTF8ToUTF16(
+ manifest_errors::kInvalidWebAppLinkedShortcutItemIcons);
+ return false;
+ }
+
+ base::Value::ConstListView shortcut_item_icons_list =
+ shortcut_item_icons_value->GetList();
+ info->shortcut_item_icon_infos.reserve(shortcut_item_icons_list.size());
+
+ for (const auto& shortcut_item_icon_value : shortcut_item_icons_list) {
+ WebAppLinkedShortcutItems::ShortcutItemInfo::IconInfo icon_info;
+ if (!ParseShortcutItemIconValue(shortcut_item_icon_value, &icon_info,
+ error)) {
+ return false;
+ }
+ info->shortcut_item_icon_infos.push_back(icon_info);
+ }
+
+ return true;
+}
+
+} // namespace
+
+WebAppLinkedShortcutItems::ShortcutItemInfo::IconInfo::IconInfo() = default;
+
+WebAppLinkedShortcutItems::ShortcutItemInfo::IconInfo::~IconInfo() = default;
+
+WebAppLinkedShortcutItems::ShortcutItemInfo::ShortcutItemInfo() = default;
+
+WebAppLinkedShortcutItems::ShortcutItemInfo::ShortcutItemInfo(
+ const WebAppLinkedShortcutItems::ShortcutItemInfo& other) = default;
+
+WebAppLinkedShortcutItems::ShortcutItemInfo::~ShortcutItemInfo() = default;
+
+WebAppLinkedShortcutItems::WebAppLinkedShortcutItems() = default;
+
+WebAppLinkedShortcutItems::WebAppLinkedShortcutItems(
+ const WebAppLinkedShortcutItems& other) = default;
+
+WebAppLinkedShortcutItems::~WebAppLinkedShortcutItems() = default;
+
+// static
+const WebAppLinkedShortcutItems&
+WebAppLinkedShortcutItems::GetWebAppLinkedShortcutItems(
+ const Extension* extension) {
+ WebAppLinkedShortcutItems* info = static_cast<WebAppLinkedShortcutItems*>(
+ extension->GetManifestData(keys::kWebAppLinkedShortcutItems));
+ if (info)
+ return *info;
+
+ static base::NoDestructor<WebAppLinkedShortcutItems>
+ empty_web_app_linked_shortcut_items;
+ return *empty_web_app_linked_shortcut_items;
+}
+
+WebAppLinkedShortcutItemsHandler::WebAppLinkedShortcutItemsHandler() = default;
+
+WebAppLinkedShortcutItemsHandler::~WebAppLinkedShortcutItemsHandler() = default;
+
+bool WebAppLinkedShortcutItemsHandler::Parse(Extension* extension,
+ base::string16* error) {
+ // The "web_app_linked_shortcut_items" key is only available for Bookmark
+ // Apps. Including it elsewhere results in an install warning, and the linked
+ // shortcut items are not parsed.
+ if (!extension->from_bookmark()) {
+ extension->AddInstallWarning(InstallWarning(
+ errors::kInvalidWebAppLinkedShortcutItemsNotBookmarkApp));
+ return true;
+ }
+
+ auto web_app_linked_shortcut_items =
+ std::make_unique<WebAppLinkedShortcutItems>();
+
+ const base::Value* shortcut_items_value = nullptr;
+ if (!extension->manifest()->GetList(keys::kWebAppLinkedShortcutItems,
+ &shortcut_items_value)) {
+ *error =
+ base::UTF8ToUTF16(manifest_errors::kInvalidWebAppLinkedShortcutItems);
+ return false;
+ }
+
+ base::Value::ConstListView shortcut_items_list =
+ shortcut_items_value->GetList();
+ web_app_linked_shortcut_items->shortcut_item_infos.reserve(
+ shortcut_items_list.size());
+ for (const auto& shortcut_item_value : shortcut_items_list) {
+ WebAppLinkedShortcutItems::ShortcutItemInfo info;
+ if (!ParseShortcutItemValue(shortcut_item_value, &info, error))
+ return false;
+ web_app_linked_shortcut_items->shortcut_item_infos.push_back(info);
+ }
+ extension->SetManifestData(keys::kWebAppLinkedShortcutItems,
+ std::move(web_app_linked_shortcut_items));
+ return true;
+}
+
+base::span<const char* const> WebAppLinkedShortcutItemsHandler::Keys() const {
+ static constexpr const char* kKeys[] = {keys::kWebAppLinkedShortcutItems};
+ return kKeys;
+}
+
+} // namespace extensions
diff --git a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.h b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.h
new file mode 100644
index 00000000000..7baae167e00
--- /dev/null
+++ b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items.h
@@ -0,0 +1,70 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_APP_LINKED_SHORTCUT_ITEMS_H_
+#define EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_APP_LINKED_SHORTCUT_ITEMS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest_handler.h"
+
+class GURL;
+
+namespace extensions {
+
+// A structure to hold the parsed web app linked shortcut item data.
+struct WebAppLinkedShortcutItems : public Extension::ManifestData {
+ struct ShortcutItemInfo {
+ struct IconInfo {
+ IconInfo();
+ ~IconInfo();
+
+ GURL url;
+ int size;
+ };
+
+ ShortcutItemInfo();
+ ShortcutItemInfo(const ShortcutItemInfo& other);
+ ~ShortcutItemInfo();
+
+ base::string16 name;
+ GURL url;
+ std::vector<IconInfo> shortcut_item_icon_infos;
+ };
+
+ WebAppLinkedShortcutItems();
+ WebAppLinkedShortcutItems(const WebAppLinkedShortcutItems& other);
+ ~WebAppLinkedShortcutItems() override;
+
+ static const WebAppLinkedShortcutItems& GetWebAppLinkedShortcutItems(
+ const Extension* extension);
+
+ std::vector<ShortcutItemInfo> shortcut_item_infos;
+};
+
+// Parses the "web_app_linked_shortcut_items" manifest key.
+class WebAppLinkedShortcutItemsHandler : public ManifestHandler {
+ public:
+ WebAppLinkedShortcutItemsHandler();
+ WebAppLinkedShortcutItemsHandler(const WebAppLinkedShortcutItemsHandler&) =
+ delete;
+ WebAppLinkedShortcutItemsHandler& operator=(
+ const WebAppLinkedShortcutItemsHandler&) = delete;
+ ~WebAppLinkedShortcutItemsHandler() override;
+
+ // ManifestHandler:
+ bool Parse(Extension* extension, base::string16* error) override;
+
+ private:
+ // ManifestHandler:
+ base::span<const char* const> Keys() const override;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_APP_LINKED_SHORTCUT_ITEMS_H_
diff --git a/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items_unittest.cc b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items_unittest.cc
new file mode 100644
index 00000000000..818e54eedef
--- /dev/null
+++ b/chromium/extensions/common/manifest_handlers/web_app_linked_shortcut_items_unittest.cc
@@ -0,0 +1,135 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/manifest_constants.h"
+#include "extensions/common/manifest_handlers/web_app_linked_shortcut_items.h"
+#include "extensions/common/manifest_test.h"
+
+namespace extensions {
+
+namespace errors = manifest_errors;
+
+using WebAppLinkedShortcutItemsHandlerTest = ManifestTest;
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, Valid) {
+ scoped_refptr<Extension> extension =
+ LoadAndExpectSuccess("web_app_linked_shortcut_items_valid.json",
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+ ASSERT_TRUE(extension.get());
+ ASSERT_TRUE(extension->from_bookmark());
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidNotFromBookmarkApp) {
+ scoped_refptr<Extension> extension =
+ LoadAndExpectSuccess("web_app_linked_shortcut_items_valid.json");
+ ASSERT_TRUE(extension.get());
+ ASSERT_FALSE(extension->from_bookmark());
+
+ std::vector<InstallWarning> expected_install_warnings;
+ expected_install_warnings.emplace_back(
+ InstallWarning(errors::kInvalidWebAppLinkedShortcutItemsNotBookmarkApp));
+ EXPECT_EQ(expected_install_warnings, extension->install_warnings());
+
+ const WebAppLinkedShortcutItems& web_app_linked_shortcut_items =
+ WebAppLinkedShortcutItems::GetWebAppLinkedShortcutItems(extension.get());
+ EXPECT_TRUE(web_app_linked_shortcut_items.shortcut_item_infos.empty());
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItems) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid1.json",
+ errors::kInvalidWebAppLinkedShortcutItems,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItem) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid2.json",
+ errors::kInvalidWebAppLinkedShortcutItem,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItemName) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid3.json",
+ errors::kInvalidWebAppLinkedShortcutItemName,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItemUrl) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid4.json",
+ errors::kInvalidWebAppLinkedShortcutItemUrl,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItemUrl2) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid10.json",
+ errors::kInvalidWebAppLinkedShortcutItemUrl,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItemIcons) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid5.json",
+ errors::kInvalidWebAppLinkedShortcutItemIcons,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItemIcon) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid6.json",
+ errors::kInvalidWebAppLinkedShortcutItemIcon,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, InvalidLinkedShortcutItemIconUrl) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid7.json",
+ errors::kInvalidWebAppLinkedShortcutItemIconUrl,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest,
+ InvalidLinkedShortcutItemIconUrl2) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid8.json",
+ errors::kInvalidWebAppLinkedShortcutItemIconUrl,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest,
+ InvalidLinkedShortcutItemIconSize) {
+ LoadAndExpectError("web_app_linked_shortcut_items_invalid9.json",
+ errors::kInvalidWebAppLinkedShortcutItemIconSize,
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest, ValidLinkedShortcutItemNoIcons) {
+ scoped_refptr<Extension> extension =
+ LoadAndExpectSuccess("web_app_linked_shortcut_items_valid_no_icons.json",
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+ ASSERT_TRUE(extension.get());
+ ASSERT_TRUE(extension->from_bookmark());
+}
+
+TEST_F(WebAppLinkedShortcutItemsHandlerTest,
+ ValidLinkedShortcutItemMultipleIcons) {
+ scoped_refptr<Extension> extension = LoadAndExpectSuccess(
+ "web_app_linked_shortcut_items_valid_multiple_icons.json",
+ extensions::Manifest::Location::INTERNAL,
+ extensions::Extension::FROM_BOOKMARK);
+ ASSERT_TRUE(extension.get());
+ ASSERT_TRUE(extension->from_bookmark());
+}
+
+} // namespace extensions