• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/browser/extensions/extension_page_actions_module.h"
6 
7 #include <string>
8 
9 #include "base/string_number_conversions.h"
10 #include "chrome/browser/extensions/extension_page_actions_module_constants.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_tab_helper.h"
13 #include "chrome/browser/extensions/extension_tabs_module.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser_list.h"
16 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
17 #include "chrome/common/extensions/extension.h"
18 #include "chrome/common/extensions/extension_action.h"
19 #include "chrome/common/extensions/extension_error_utils.h"
20 #include "chrome/common/render_messages.h"
21 #include "content/browser/tab_contents/navigation_entry.h"
22 #include "content/browser/tab_contents/tab_contents.h"
23 
24 namespace keys = extension_page_actions_module_constants;
25 
26 namespace {
27 // Errors.
28 const char kNoTabError[] = "No tab with id: *.";
29 const char kNoPageActionError[] =
30     "This extension has no page action specified.";
31 const char kUrlNotActiveError[] = "This url is no longer active: *.";
32 const char kIconIndexOutOfBounds[] = "Page action icon index out of bounds.";
33 const char kNoIconSpecified[] = "Page action has no icons to show.";
34 }
35 
36 // TODO(EXTENSIONS_DEPRECATED): obsolete API.
SetPageActionEnabled(bool enable)37 bool PageActionFunction::SetPageActionEnabled(bool enable) {
38   std::string page_action_id;
39   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &page_action_id));
40   DictionaryValue* action;
41   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &action));
42 
43   int tab_id;
44   EXTENSION_FUNCTION_VALIDATE(action->GetInteger(keys::kTabIdKey, &tab_id));
45   std::string url;
46   EXTENSION_FUNCTION_VALIDATE(action->GetString(keys::kUrlKey, &url));
47 
48   std::string title;
49   int icon_id = 0;
50   if (enable) {
51     // Both of those are optional.
52     if (action->HasKey(keys::kTitleKey))
53       EXTENSION_FUNCTION_VALIDATE(action->GetString(keys::kTitleKey, &title));
54     if (action->HasKey(keys::kIconIdKey)) {
55       EXTENSION_FUNCTION_VALIDATE(action->GetInteger(keys::kIconIdKey,
56                                                      &icon_id));
57     }
58   }
59 
60   ExtensionAction* page_action = GetExtension()->page_action();
61   if (!page_action) {
62     error_ = kNoPageActionError;
63     return false;
64   }
65 
66   if (icon_id < 0 ||
67       static_cast<size_t>(icon_id) >= page_action->icon_paths()->size()) {
68     error_ = (icon_id == 0) ? kNoIconSpecified : kIconIndexOutOfBounds;
69     return false;
70   }
71 
72   // Find the TabContents that contains this tab id.
73   TabContentsWrapper* contents = NULL;
74   bool result = ExtensionTabUtil::GetTabById(
75       tab_id, profile(), include_incognito(), NULL, NULL, &contents, NULL);
76   if (!result || !contents) {
77     error_ = ExtensionErrorUtils::FormatErrorMessage(
78         kNoTabError, base::IntToString(tab_id));
79     return false;
80   }
81 
82   // Make sure the URL hasn't changed.
83   NavigationEntry* entry = contents->controller().GetActiveEntry();
84   if (!entry || url != entry->url().spec()) {
85     error_ = ExtensionErrorUtils::FormatErrorMessage(kUrlNotActiveError, url);
86     return false;
87   }
88 
89   // Set visibility and broadcast notifications that the UI should be updated.
90   page_action->SetIsVisible(tab_id, enable);
91   page_action->SetTitle(tab_id, title);
92   page_action->SetIconIndex(tab_id, icon_id);
93   contents->extension_tab_helper()->PageActionStateChanged();
94 
95   return true;
96 }
97 
InitCommon(int tab_id)98 bool PageActionFunction::InitCommon(int tab_id) {
99   page_action_ = GetExtension()->page_action();
100   if (!page_action_) {
101     error_ = kNoPageActionError;
102     return false;
103   }
104 
105   // Find the TabContents that contains this tab id.
106   contents_ = NULL;
107   TabContentsWrapper* wrapper = NULL;
108   bool result = ExtensionTabUtil::GetTabById(
109       tab_id, profile(), include_incognito(), NULL, NULL, &wrapper, NULL);
110   if (!result || !wrapper) {
111     error_ = ExtensionErrorUtils::FormatErrorMessage(
112         kNoTabError, base::IntToString(tab_id));
113     return false;
114   }
115   contents_ = wrapper;
116 
117   return true;
118 }
119 
SetVisible(bool visible)120 bool PageActionFunction::SetVisible(bool visible) {
121   int tab_id;
122   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
123   if (!InitCommon(tab_id))
124     return false;
125 
126   page_action_->SetIsVisible(tab_id, visible);
127   contents_->extension_tab_helper()->PageActionStateChanged();
128   return true;
129 }
130 
RunImpl()131 bool EnablePageActionFunction::RunImpl() {
132   return SetPageActionEnabled(true);
133 }
134 
RunImpl()135 bool DisablePageActionFunction::RunImpl() {
136   return SetPageActionEnabled(false);
137 }
138 
RunImpl()139 bool PageActionShowFunction::RunImpl() {
140   return SetVisible(true);
141 }
142 
RunImpl()143 bool PageActionHideFunction::RunImpl() {
144   return SetVisible(false);
145 }
146 
RunImpl()147 bool PageActionSetIconFunction::RunImpl() {
148   DictionaryValue* args;
149   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
150 
151   int tab_id;
152   EXTENSION_FUNCTION_VALIDATE(args->GetInteger("tabId", &tab_id));
153   if (!InitCommon(tab_id))
154     return false;
155 
156   // setIcon can take a variant argument: either a canvas ImageData, or an
157   // icon index.
158   BinaryValue* binary;
159   int icon_index;
160   if (args->GetBinary("imageData", &binary)) {
161     IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize());
162     void* iter = NULL;
163     scoped_ptr<SkBitmap> bitmap(new SkBitmap);
164     EXTENSION_FUNCTION_VALIDATE(
165         IPC::ReadParam(&bitmap_pickle, &iter, bitmap.get()));
166     page_action_->SetIcon(tab_id, *bitmap);
167   } else if (args->GetInteger("iconIndex", &icon_index)) {
168     if (icon_index < 0 || static_cast<size_t>(icon_index) >=
169                               page_action_->icon_paths()->size()) {
170       error_ = kIconIndexOutOfBounds;
171       return false;
172     }
173     page_action_->SetIcon(tab_id, SkBitmap());
174     page_action_->SetIconIndex(tab_id, icon_index);
175   } else {
176     EXTENSION_FUNCTION_VALIDATE(false);
177   }
178 
179   contents_->extension_tab_helper()->PageActionStateChanged();
180   return true;
181 }
182 
RunImpl()183 bool PageActionSetTitleFunction::RunImpl() {
184   DictionaryValue* args;
185   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
186 
187   int tab_id;
188   EXTENSION_FUNCTION_VALIDATE(args->GetInteger("tabId", &tab_id));
189   if (!InitCommon(tab_id))
190     return false;
191 
192   std::string title;
193   EXTENSION_FUNCTION_VALIDATE(args->GetString("title", &title));
194 
195   page_action_->SetTitle(tab_id, title);
196   contents_->extension_tab_helper()->PageActionStateChanged();
197   return true;
198 }
199 
RunImpl()200 bool PageActionSetPopupFunction::RunImpl() {
201   DictionaryValue* args;
202   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
203 
204   int tab_id;
205   EXTENSION_FUNCTION_VALIDATE(args->GetInteger("tabId", &tab_id));
206   if (!InitCommon(tab_id))
207     return false;
208 
209   // TODO(skerner): Consider allowing null and undefined to mean the popup
210   // should be removed.
211   std::string popup_string;
212   EXTENSION_FUNCTION_VALIDATE(args->GetString("popup", &popup_string));
213 
214   GURL popup_url;
215   if (!popup_string.empty())
216     popup_url = GetExtension()->GetResourceURL(popup_string);
217 
218   page_action_->SetPopupUrl(tab_id, popup_url);
219   contents_->extension_tab_helper()->PageActionStateChanged();
220   return true;
221 }
222 
223 // Not currently exposed to extensions. To re-enable, add mapping in
224 // extension_function_dispatcher.
RunImpl()225 bool PageActionSetBadgeBackgroundColorFunction::RunImpl() {
226   DictionaryValue* args;
227   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
228 
229   int tab_id;
230   EXTENSION_FUNCTION_VALIDATE(args->GetInteger("tabId", &tab_id));
231   if (!InitCommon(tab_id))
232     return false;
233 
234   ListValue* color_value;
235   EXTENSION_FUNCTION_VALIDATE(args->GetList("color", &color_value));
236   EXTENSION_FUNCTION_VALIDATE(color_value->GetSize() == 4);
237 
238   int color_array[4] = {0};
239   for (size_t i = 0; i < arraysize(color_array); ++i)
240     EXTENSION_FUNCTION_VALIDATE(color_value->GetInteger(i, &color_array[i]));
241 
242   SkColor color = SkColorSetARGB(color_array[3], color_array[0], color_array[1],
243                                  color_array[2]);
244   page_action_->SetBadgeBackgroundColor(tab_id, color);
245   contents_->extension_tab_helper()->PageActionStateChanged();
246   return true;
247 }
248 
249 // Not currently exposed to extensions. To re-enable, add mapping in
250 // extension_function_dispatcher.
RunImpl()251 bool PageActionSetBadgeTextColorFunction::RunImpl() {
252   DictionaryValue* args;
253   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
254 
255   int tab_id;
256   EXTENSION_FUNCTION_VALIDATE(args->GetInteger("tabId", &tab_id));
257   if (!InitCommon(tab_id))
258     return false;
259 
260   ListValue* color_value;
261   EXTENSION_FUNCTION_VALIDATE(args->GetList("color", &color_value));
262   EXTENSION_FUNCTION_VALIDATE(color_value->GetSize() == 4);
263 
264   int color_array[4] = {0};
265   for (size_t i = 0; i < arraysize(color_array); ++i)
266     EXTENSION_FUNCTION_VALIDATE(color_value->GetInteger(i, &color_array[i]));
267 
268   SkColor color = SkColorSetARGB(color_array[3], color_array[0], color_array[1],
269                                  color_array[2]);
270   page_action_->SetBadgeTextColor(tab_id, color);
271   contents_->extension_tab_helper()->PageActionStateChanged();
272   return true;
273 }
274 
275 // Not currently exposed to extensions. To re-enable, add mapping in
276 // extension_function_dispatcher.
RunImpl()277 bool PageActionSetBadgeTextFunction::RunImpl() {
278   DictionaryValue* args;
279   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
280 
281   int tab_id;
282   EXTENSION_FUNCTION_VALIDATE(args->GetInteger("tabId", &tab_id));
283   if (!InitCommon(tab_id))
284     return false;
285 
286   std::string text;
287   EXTENSION_FUNCTION_VALIDATE(args->GetString("text", &text));
288 
289   page_action_->SetBadgeText(tab_id, text);
290   contents_->extension_tab_helper()->PageActionStateChanged();
291   return true;
292 }
293