15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/base64.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/badge_util.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/icon_with_badge_image_source.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/constants.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "grit/ui_resources.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ipc/ipc_message.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ipc/ipc_message_utils.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkPaint.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/effects/SkGradientShader.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/animation_delegate.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/color_utils.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/image/image.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_source.h" 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/gfx/ipc/gfx_param_traits.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skbitmap_operations.h" 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GetAttentionImageSource : public gfx::ImageSkiaSource { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit GetAttentionImageSource(const gfx::ImageSkia& icon) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : icon_(icon) {} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // gfx::ImageSkiaSource overrides: 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE { 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::HSL shift = {-1, 0, 0.5}; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::ImageSkiaRep( 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift), 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) icon_rep.scale()); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia icon_; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct IconRepresentationInfo { 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Size as a string that will be used to retrieve a representation value from 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // SetIcon function arguments. 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const char* size_string; 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Scale factor for which the represantion should be used. 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::ScaleFactor scale; 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst IconRepresentationInfo kIconSizes[] = {{"19", ui::SCALE_FACTOR_100P}, 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {"38", ui::SCALE_FACTOR_200P}}; 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <class T> 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool HasValue(const std::map<int, T>& map, int tab_id) { 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return map.find(tab_id) != map.end(); 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int ExtensionAction::kDefaultTabId = -1; 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int ExtensionAction::kPageActionIconMaxSize = 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_misc::EXTENSION_ICON_ACTION; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ExtensionAction::ExtensionAction(const std::string& extension_id, 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::ActionInfo::Type action_type, 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const extensions::ActionInfo& manifest_data) 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : extension_id_(extension_id), action_type_(action_type) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Page/script actions are hidden/disabled by default, and browser actions are 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visible/enabled by default. 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetIsVisible(kDefaultTabId, 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action_type == extensions::ActionInfo::TYPE_BROWSER); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetTitle(kDefaultTabId, manifest_data.default_title); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetPopupUrl(kDefaultTabId, manifest_data.default_popup_url); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!manifest_data.default_icon.empty()) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_default_icon(make_scoped_ptr(new ExtensionIconSet( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manifest_data.default_icon))); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_id(manifest_data.id); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionAction::~ExtensionAction() { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<ExtensionAction> ExtensionAction::CopyForTest() const { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ExtensionAction> copy( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ExtensionAction(extension_id_, action_type_, 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ActionInfo())); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->popup_url_ = popup_url_; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->title_ = title_; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->icon_ = icon_; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->badge_text_ = badge_text_; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->badge_background_color_ = badge_background_color_; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->badge_text_color_ = badge_text_color_; 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) copy->is_visible_ = is_visible_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->id_ = id_; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (default_icon_) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->default_icon_.reset(new ExtensionIconSet(*default_icon_)); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return copy.Pass(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionAction::GetIconSizeForType( 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ActionInfo::Type type) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case extensions::ActionInfo::TYPE_BROWSER: 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case extensions::ActionInfo::TYPE_PAGE: 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case extensions::ActionInfo::TYPE_SYSTEM_INDICATOR: 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(dewittj) Report the actual icon size of the system 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // indicator. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extension_misc::EXTENSION_ICON_ACTION; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We store |url| even if it is empty, rather than removing a URL from the 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // map. If an extension has a default popup, and removes it for a tab via 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the API, we must remember that there is no popup for that specific tab. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we removed the tab's URL, GetPopupURL would incorrectly return the 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default URL. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetValue(&popup_url_, tab_id, url); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionAction::HasPopup(int tab_id) const { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !GetPopupUrl(tab_id).is_empty(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL ExtensionAction::GetPopupUrl(int tab_id) const { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetValue(&popup_url_, tab_id); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetValue(&icon_, tab_id, image.AsImageSkia()); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ExtensionAction::ParseIconFromCanvasDictionary( 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::DictionaryValue& dict, 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::ImageSkia* icon) { 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Try to extract an icon for each known scale. 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < arraysize(kIconSizes); i++) { 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::BinaryValue* image_data; 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string binary_string64; 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC::Message pickle; 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (dict.GetBinary(kIconSizes[i].size_string, &image_data)) { 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pickle = IPC::Message(image_data->GetBuffer(), image_data->GetSize()); 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (dict.GetString(kIconSizes[i].size_string, &binary_string64)) { 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string binary_string; 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!base::Base64Decode(binary_string64, &binary_string)) 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pickle = IPC::Message(binary_string.c_str(), binary_string.length()); 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PickleIterator iter(pickle); 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SkBitmap bitmap; 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!IPC::ReadParam(&pickle, &iter, &bitmap)) 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(!bitmap.isNull()); 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci float scale = ui::GetScaleForScaleFactor(kIconSizes[i].scale); 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci icon->AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia ExtensionAction::GetExplicitlySetIcon(int tab_id) const { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetValue(&icon_, tab_id); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ExtensionAction::SetIsVisible(int tab_id, bool new_visibility) { 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const bool old_visibility = GetValue(&is_visible_, tab_id); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (old_visibility == new_visibility) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetValue(&is_visible_, tab_id, new_visibility); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionAction::DeclarativeShow(int tab_id) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(tab_id, kDefaultTabId); 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++declarative_show_count_[tab_id]; // Use default initialization to 0. 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionAction::UndoDeclarativeShow(int tab_id) { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int& show_count = declarative_show_count_[tab_id]; 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GT(show_count, 0); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (--show_count == 0) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) declarative_show_count_.erase(tab_id); 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionAction::DeclarativeSetIcon(int tab_id, 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int priority, 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Image& icon) { 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(tab_id, kDefaultTabId); 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci declarative_icon_[tab_id][priority].push_back(icon); 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionAction::UndoDeclarativeSetIcon(int tab_id, 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int priority, 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Image& icon) { 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<gfx::Image>& icons = declarative_icon_[tab_id][priority]; 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::vector<gfx::Image>::iterator it = icons.begin(); it != icons.end(); 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++it) { 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (it->AsImageSkia().BackedBySameObjectAs(icon.AsImageSkia())) { 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci icons.erase(it); 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst gfx::ImageSkia ExtensionAction::GetDeclarativeIcon(int tab_id) const { 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (declarative_icon_.find(tab_id) != declarative_icon_.end() && 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !declarative_icon_.find(tab_id)->second.rbegin()->second.empty()) { 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return declarative_icon_.find(tab_id)->second.rbegin() 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->second.back().AsImageSkia(); 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return gfx::ImageSkia(); 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAction::ClearAllValuesForTab(int tab_id) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_url_.erase(tab_id); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_.erase(tab_id); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_.erase(tab_id); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) badge_text_.erase(tab_id); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) badge_text_color_.erase(tab_id); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) badge_background_color_.erase(tab_id); 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_visible_.erase(tab_id); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(jyasskin): Erase the element from declarative_show_count_ 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // when the tab's closed. There's a race between the 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // LocationBarController and the ContentRulesRegistry on navigation, 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // which prevents me from cleaning everything up now. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAction::PaintBadge(gfx::Canvas* canvas, 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& bounds, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id) { 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) badge_util::PaintBadge( 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBadgeText(tab_id), 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBadgeTextColor(tab_id), 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBadgeBackgroundColor(tab_id), 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetIconWidth(tab_id), 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action_type()); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia ExtensionAction::GetIconWithBadge( 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia& icon, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& spacing) const { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id < 0) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::ImageSkia( 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new IconWithBadgeImageSource(icon, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon.size(), 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spacing, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBadgeText(tab_id), 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBadgeTextColor(tab_id), 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBadgeBackgroundColor(tab_id), 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action_type()), 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon.size()); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ExtensionAction::HasPopupUrl(int tab_id) const { 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasValue(popup_url_, tab_id); 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ExtensionAction::HasTitle(int tab_id) const { 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasValue(title_, tab_id); 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ExtensionAction::HasBadgeText(int tab_id) const { 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasValue(badge_text_, tab_id); 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ExtensionAction::HasBadgeBackgroundColor(int tab_id) const { 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasValue(badge_background_color_, tab_id); 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ExtensionAction::HasBadgeTextColor(int tab_id) const { 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasValue(badge_text_color_, tab_id); 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ExtensionAction::HasIsVisible(int tab_id) const { 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasValue(is_visible_, tab_id); 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ExtensionAction::HasIcon(int tab_id) const { 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasValue(icon_, tab_id); 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Determines which icon would be returned by |GetIcon|, and returns its width. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionAction::GetIconWidth(int tab_id) const { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If icon has been set, return its width. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia icon = GetValue(&icon_, tab_id); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon.isNull()) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon.width(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is a default icon, the icon width will be set depending on our 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // action type. 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (default_icon_) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetIconSizeForType(action_type()); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no icon has been set and there is no default icon, we need favicon 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // width. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::ResourceBundle::GetSharedInstance().GetImageNamed( 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_EXTENSIONS_FAVICON).ToImageSkia()->width(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 329