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 "chrome/common/extensions/api/extension_action/action_info.h"
6#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
7#include "extensions/common/constants.h"
8#include "extensions/common/error_utils.h"
9#include "extensions/common/extension.h"
10#include "extensions/common/manifest_constants.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace extensions {
14
15namespace errors = manifest_errors;
16namespace keys = manifest_keys;
17
18class PageActionManifestTest : public ExtensionManifestTest {
19 protected:
20  virtual const char* test_data_dir() OVERRIDE {
21    return "page_action";
22  }
23
24  scoped_ptr<ActionInfo> LoadAction(const std::string& manifest_filename);
25};
26
27scoped_ptr<ActionInfo> PageActionManifestTest::LoadAction(
28    const std::string& manifest_filename) {
29  scoped_refptr<Extension> extension = LoadAndExpectSuccess(
30      manifest_filename.c_str());
31  const ActionInfo* page_action_info =
32      ActionInfo::GetPageActionInfo(extension.get());
33  EXPECT_TRUE(page_action_info);
34  if (page_action_info) {
35    return make_scoped_ptr(new ActionInfo(*page_action_info));
36  }
37  ADD_FAILURE() << "Expected manifest in " << manifest_filename
38                << " to include a page_action section.";
39  return scoped_ptr<ActionInfo>();
40}
41
42TEST_F(PageActionManifestTest, ManifestVersion2) {
43  scoped_refptr<Extension> extension(
44      LoadAndExpectSuccess("page_action_manifest_version_2.json"));
45  ASSERT_TRUE(extension.get());
46  const ActionInfo* page_action_info =
47      ActionInfo::GetPageActionInfo(extension.get());
48  ASSERT_TRUE(page_action_info);
49
50  EXPECT_EQ("", page_action_info->id);
51  EXPECT_TRUE(page_action_info->default_icon.empty());
52  EXPECT_EQ("", page_action_info->default_title);
53  EXPECT_TRUE(page_action_info->default_popup_url.is_empty());
54
55  LoadAndExpectError("page_action_manifest_version_2b.json",
56                     errors::kInvalidPageActionPopup);
57}
58
59TEST_F(PageActionManifestTest, LoadPageActionHelper) {
60  scoped_ptr<ActionInfo> action;
61
62  // First try with an empty dictionary.
63  action = LoadAction("page_action_empty.json");
64  ASSERT_TRUE(action);
65
66  // Now setup some values to use in the action.
67  const std::string id("MyExtensionActionId");
68  const std::string name("MyExtensionActionName");
69  std::string img1("image1.png");
70
71  action = LoadAction("page_action.json");
72  ASSERT_TRUE(action);
73  ASSERT_EQ(id, action->id);
74
75  // No title, so fall back to name.
76  ASSERT_EQ(name, action->default_title);
77  ASSERT_EQ(img1,
78            action->default_icon.Get(extension_misc::EXTENSION_ICON_ACTION,
79                                     ExtensionIconSet::MATCH_EXACTLY));
80
81  // Same test with explicitly set type.
82  action = LoadAction("page_action_type.json");
83  ASSERT_TRUE(action);
84
85  // Try an action without id key.
86  action = LoadAction("page_action_no_id.json");
87  ASSERT_TRUE(action);
88
89  // Then try without the name key. It's optional, so no error.
90  action = LoadAction("page_action_no_name.json");
91  ASSERT_TRUE(action);
92  ASSERT_TRUE(action->default_title.empty());
93
94  // Then try without the icon paths key.
95  action = LoadAction("page_action_no_icon.json");
96  ASSERT_TRUE(action);
97
98  // Now test that we can parse the new format for page actions.
99  const std::string kTitle("MyExtensionActionTitle");
100  const std::string kIcon("image1.png");
101  const std::string kPopupHtmlFile("a_popup.html");
102
103  action = LoadAction("page_action_new_format.json");
104  ASSERT_TRUE(action);
105  ASSERT_EQ(kTitle, action->default_title);
106  ASSERT_FALSE(action->default_icon.empty());
107
108  // Invalid title should give an error even with a valid name.
109  LoadAndExpectError("page_action_invalid_title.json",
110                     errors::kInvalidPageActionDefaultTitle);
111
112  // Invalid name should give an error only with no title.
113  action = LoadAction("page_action_invalid_name.json");
114  ASSERT_TRUE(action);
115  ASSERT_EQ(kTitle, action->default_title);
116
117  LoadAndExpectError("page_action_invalid_name_no_title.json",
118                     errors::kInvalidPageActionName);
119
120  // Test that keys "popup" and "default_popup" both work, but can not
121  // be used at the same time.
122  // These tests require an extension_url, so we also load the manifest.
123
124  // Only use "popup", expect success.
125  scoped_refptr<Extension> extension =
126      LoadAndExpectSuccess("page_action_popup.json");
127  const ActionInfo* extension_action =
128      ActionInfo::GetPageActionInfo(extension.get());
129  ASSERT_TRUE(extension_action);
130  ASSERT_STREQ(
131      extension->url().Resolve(kPopupHtmlFile).spec().c_str(),
132      extension_action->default_popup_url.spec().c_str());
133
134  // Use both "popup" and "default_popup", expect failure.
135  LoadAndExpectError("page_action_popup_and_default_popup.json",
136                     ErrorUtils::FormatErrorMessage(
137                         errors::kInvalidPageActionOldAndNewKeys,
138                         keys::kPageActionDefaultPopup,
139                         keys::kPageActionPopup));
140
141  // Use only "default_popup", expect success.
142  extension = LoadAndExpectSuccess("page_action_popup.json");
143  extension_action = ActionInfo::GetPageActionInfo(extension.get());
144  ASSERT_TRUE(extension_action);
145  ASSERT_STREQ(
146      extension->url().Resolve(kPopupHtmlFile).spec().c_str(),
147      extension_action->default_popup_url.spec().c_str());
148
149  // Setting default_popup to "" is the same as having no popup.
150  action = LoadAction("page_action_empty_default_popup.json");
151  ASSERT_TRUE(action);
152  EXPECT_TRUE(action->default_popup_url.is_empty());
153  ASSERT_STREQ(
154      "",
155      action->default_popup_url.spec().c_str());
156
157  // Setting popup to "" is the same as having no popup.
158  action = LoadAction("page_action_empty_popup.json");
159
160  ASSERT_TRUE(action);
161  EXPECT_TRUE(action->default_popup_url.is_empty());
162  ASSERT_STREQ(
163      "",
164      action->default_popup_url.spec().c_str());
165}
166
167}  // namespace extensions
168