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