1// Copyright (c) 2013 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/api/extension_action/page_action_handler.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "base/values.h"
9#include "chrome/common/extensions/extension_constants.h"
10#include "chrome/grit/generated_resources.h"
11#include "extensions/common/extension.h"
12#include "extensions/common/file_util.h"
13#include "extensions/common/manifest_constants.h"
14
15namespace extensions {
16
17namespace keys = manifest_keys;
18namespace errors = manifest_errors;
19
20PageActionHandler::PageActionHandler() {
21}
22
23PageActionHandler::~PageActionHandler() {
24}
25
26bool PageActionHandler::Parse(Extension* extension, base::string16* error) {
27  scoped_ptr<ActionInfo> page_action_info;
28  const base::DictionaryValue* page_action_value = NULL;
29
30  if (extension->manifest()->HasKey(keys::kPageActions)) {
31    const base::ListValue* list_value = NULL;
32    if (!extension->manifest()->GetList(keys::kPageActions, &list_value)) {
33      *error = base::ASCIIToUTF16(errors::kInvalidPageActionsList);
34      return false;
35    }
36
37    size_t list_value_length = list_value->GetSize();
38
39    if (list_value_length == 0u) {
40      // A list with zero items is allowed, and is equivalent to not having
41      // a page_actions key in the manifest.  Don't set |page_action_value|.
42    } else if (list_value_length == 1u) {
43      if (!list_value->GetDictionary(0, &page_action_value)) {
44        *error = base::ASCIIToUTF16(errors::kInvalidPageAction);
45        return false;
46      }
47    } else {  // list_value_length > 1u.
48      *error = base::ASCIIToUTF16(errors::kInvalidPageActionsListSize);
49      return false;
50    }
51  } else if (extension->manifest()->HasKey(keys::kPageAction)) {
52    if (!extension->manifest()->GetDictionary(keys::kPageAction,
53                                              &page_action_value)) {
54      *error = base::ASCIIToUTF16(errors::kInvalidPageAction);
55      return false;
56    }
57  }
58
59  // An extension cannot have both browser and page actions.
60  if (extension->manifest()->HasKey(keys::kBrowserAction)) {
61    *error = base::ASCIIToUTF16(errors::kOneUISurfaceOnly);
62    return false;
63  }
64
65  // If page_action_value is not NULL, then there was a valid page action.
66  if (page_action_value) {
67    page_action_info = ActionInfo::Load(extension, page_action_value, error);
68    if (!page_action_info)
69      return false;  // Failed to parse page action definition.
70  }
71  ActionInfo::SetPageActionInfo(extension, page_action_info.release());
72
73  return true;
74}
75
76bool PageActionHandler::Validate(const Extension* extension,
77                                 std::string* error,
78                                 std::vector<InstallWarning>* warnings) const {
79  const extensions::ActionInfo* action =
80      extensions::ActionInfo::GetPageActionInfo(extension);
81  if (action && !action->default_icon.empty() &&
82      !file_util::ValidateExtensionIconSet(
83          action->default_icon,
84          extension,
85          IDS_EXTENSION_LOAD_ICON_FOR_PAGE_ACTION_FAILED,
86          error)) {
87    return false;
88  }
89  return true;
90}
91
92const std::vector<std::string> PageActionHandler::Keys() const {
93  std::vector<std::string> keys;
94  keys.push_back(keys::kPageAction);
95  keys.push_back(keys::kPageActions);
96  return keys;
97}
98
99}  // namespace extensions
100