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 #ifndef CHROME_BROWSER_EXTENSIONS_API_EXTENSION_ACTION_EXTENSION_ACTION_API_H_ 6 #define CHROME_BROWSER_EXTENSIONS_API_EXTENSION_ACTION_EXTENSION_ACTION_API_H_ 7 8 #include <string> 9 10 #include "base/memory/weak_ptr.h" 11 #include "base/scoped_observer.h" 12 #include "chrome/browser/extensions/chrome_extension_function.h" 13 #include "chrome/browser/extensions/extension_action.h" 14 #include "content/public/browser/notification_observer.h" 15 #include "content/public/browser/notification_registrar.h" 16 #include "extensions/browser/browser_context_keyed_api_factory.h" 17 #include "extensions/browser/extension_registry_observer.h" 18 19 namespace base { 20 class DictionaryValue; 21 } 22 23 namespace content { 24 class BrowserContext; 25 class WebContents; 26 } 27 28 namespace extensions { 29 class ExtensionPrefs; 30 class ExtensionRegistry; 31 class TabHelper; 32 33 class ExtensionActionAPI : public BrowserContextKeyedAPI { 34 public: 35 explicit ExtensionActionAPI(content::BrowserContext* context); 36 virtual ~ExtensionActionAPI(); 37 38 // Convenience method to get the instance for a profile. 39 static ExtensionActionAPI* Get(content::BrowserContext* context); 40 41 static bool GetBrowserActionVisibility(const ExtensionPrefs* prefs, 42 const std::string& extension_id); 43 static void SetBrowserActionVisibility(ExtensionPrefs* prefs, 44 const std::string& extension_id, 45 bool visible); 46 47 // Fires the onClicked event for page_action. 48 static void PageActionExecuted(content::BrowserContext* context, 49 const ExtensionAction& page_action, 50 int tab_id, 51 const std::string& url, 52 int button); 53 54 // Fires the onClicked event for browser_action. 55 static void BrowserActionExecuted(content::BrowserContext* context, 56 const ExtensionAction& browser_action, 57 content::WebContents* web_contents); 58 59 // BrowserContextKeyedAPI implementation. 60 static BrowserContextKeyedAPIFactory<ExtensionActionAPI>* 61 GetFactoryInstance(); 62 63 private: 64 friend class BrowserContextKeyedAPIFactory<ExtensionActionAPI>; 65 66 // The DispatchEvent methods forward events to the |profile|'s event router. 67 static void DispatchEventToExtension(content::BrowserContext* context, 68 const std::string& extension_id, 69 const std::string& event_name, 70 scoped_ptr<base::ListValue> event_args); 71 72 // Called to dispatch a deprecated style page action click event that was 73 // registered like: 74 // chrome.pageActions["name"].addListener(function(actionId, info){}) 75 static void DispatchOldPageActionEvent(content::BrowserContext* context, 76 const std::string& extension_id, 77 const std::string& page_action_id, 78 int tab_id, 79 const std::string& url, 80 int button); 81 82 // Called when either a browser or page action is executed. Figures out which 83 // event to send based on what the extension wants. 84 static void ExtensionActionExecuted(content::BrowserContext* context, 85 const ExtensionAction& extension_action, 86 content::WebContents* web_contents); 87 88 // BrowserContextKeyedAPI implementation. 89 static const char* service_name() { return "ExtensionActionAPI"; } 90 91 DISALLOW_COPY_AND_ASSIGN(ExtensionActionAPI); 92 }; 93 94 // This class manages reading and writing browser action values from storage. 95 class ExtensionActionStorageManager 96 : public content::NotificationObserver, 97 public ExtensionRegistryObserver, 98 public base::SupportsWeakPtr<ExtensionActionStorageManager> { 99 public: 100 explicit ExtensionActionStorageManager(Profile* profile); 101 virtual ~ExtensionActionStorageManager(); 102 103 private: 104 // NotificationObserver: 105 virtual void Observe(int type, 106 const content::NotificationSource& source, 107 const content::NotificationDetails& details) OVERRIDE; 108 109 // ExtensionRegistryObserver: 110 virtual void OnExtensionLoaded(content::BrowserContext* browser_context, 111 const Extension* extension) OVERRIDE; 112 113 // Reads/Writes the ExtensionAction's default values to/from storage. 114 void WriteToStorage(ExtensionAction* extension_action); 115 void ReadFromStorage( 116 const std::string& extension_id, scoped_ptr<base::Value> value); 117 118 Profile* profile_; 119 content::NotificationRegistrar registrar_; 120 121 // Listen to extension loaded notification. 122 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> 123 extension_registry_observer_; 124 }; 125 126 // Implementation of the browserAction and pageAction APIs. 127 // 128 // Divergent behaviour between the two is minimal (pageAction has required 129 // tabIds while browserAction's are optional, they have different internal 130 // browser notification requirements, and not all functions are defined for all 131 // APIs). 132 class ExtensionActionFunction : public ChromeSyncExtensionFunction { 133 public: 134 static bool ParseCSSColorString(const std::string& color_string, 135 SkColor* result); 136 137 protected: 138 ExtensionActionFunction(); 139 virtual ~ExtensionActionFunction(); 140 virtual bool RunSync() OVERRIDE; 141 virtual bool RunExtensionAction() = 0; 142 143 bool ExtractDataFromArguments(); 144 void NotifyChange(); 145 void NotifyBrowserActionChange(); 146 void NotifyLocationBarChange(); 147 void NotifySystemIndicatorChange(); 148 bool SetVisible(bool visible); 149 150 // Extension-related information for |tab_id_|. 151 // CHECK-fails if there is no tab. 152 extensions::TabHelper& tab_helper() const; 153 154 // All the extension action APIs take a single argument called details that 155 // is a dictionary. 156 base::DictionaryValue* details_; 157 158 // The tab id the extension action function should apply to, if any, or 159 // kDefaultTabId if none was specified. 160 int tab_id_; 161 162 // WebContents for |tab_id_| if one exists. 163 content::WebContents* contents_; 164 165 // The extension action for the current extension. 166 ExtensionAction* extension_action_; 167 }; 168 169 // 170 // Implementations of each extension action API. 171 // 172 // pageAction and browserAction bindings are created for these by extending them 173 // then declaring an EXTENSION_FUNCTION_NAME. 174 // 175 176 // show 177 class ExtensionActionShowFunction : public ExtensionActionFunction { 178 protected: 179 virtual ~ExtensionActionShowFunction() {} 180 virtual bool RunExtensionAction() OVERRIDE; 181 }; 182 183 // hide 184 class ExtensionActionHideFunction : public ExtensionActionFunction { 185 protected: 186 virtual ~ExtensionActionHideFunction() {} 187 virtual bool RunExtensionAction() OVERRIDE; 188 }; 189 190 // setIcon 191 class ExtensionActionSetIconFunction : public ExtensionActionFunction { 192 protected: 193 virtual ~ExtensionActionSetIconFunction() {} 194 virtual bool RunExtensionAction() OVERRIDE; 195 }; 196 197 // setTitle 198 class ExtensionActionSetTitleFunction : public ExtensionActionFunction { 199 protected: 200 virtual ~ExtensionActionSetTitleFunction() {} 201 virtual bool RunExtensionAction() OVERRIDE; 202 }; 203 204 // setPopup 205 class ExtensionActionSetPopupFunction : public ExtensionActionFunction { 206 protected: 207 virtual ~ExtensionActionSetPopupFunction() {} 208 virtual bool RunExtensionAction() OVERRIDE; 209 }; 210 211 // setBadgeText 212 class ExtensionActionSetBadgeTextFunction : public ExtensionActionFunction { 213 protected: 214 virtual ~ExtensionActionSetBadgeTextFunction() {} 215 virtual bool RunExtensionAction() OVERRIDE; 216 }; 217 218 // setBadgeBackgroundColor 219 class ExtensionActionSetBadgeBackgroundColorFunction 220 : public ExtensionActionFunction { 221 protected: 222 virtual ~ExtensionActionSetBadgeBackgroundColorFunction() {} 223 virtual bool RunExtensionAction() OVERRIDE; 224 }; 225 226 // getTitle 227 class ExtensionActionGetTitleFunction : public ExtensionActionFunction { 228 protected: 229 virtual ~ExtensionActionGetTitleFunction() {} 230 virtual bool RunExtensionAction() OVERRIDE; 231 }; 232 233 // getPopup 234 class ExtensionActionGetPopupFunction : public ExtensionActionFunction { 235 protected: 236 virtual ~ExtensionActionGetPopupFunction() {} 237 virtual bool RunExtensionAction() OVERRIDE; 238 }; 239 240 // getBadgeText 241 class ExtensionActionGetBadgeTextFunction : public ExtensionActionFunction { 242 protected: 243 virtual ~ExtensionActionGetBadgeTextFunction() {} 244 virtual bool RunExtensionAction() OVERRIDE; 245 }; 246 247 // getBadgeBackgroundColor 248 class ExtensionActionGetBadgeBackgroundColorFunction 249 : public ExtensionActionFunction { 250 protected: 251 virtual ~ExtensionActionGetBadgeBackgroundColorFunction() {} 252 virtual bool RunExtensionAction() OVERRIDE; 253 }; 254 255 // 256 // browserAction.* aliases for supported browserAction APIs. 257 // 258 259 class BrowserActionSetIconFunction : public ExtensionActionSetIconFunction { 260 public: 261 DECLARE_EXTENSION_FUNCTION("browserAction.setIcon", BROWSERACTION_SETICON) 262 263 protected: 264 virtual ~BrowserActionSetIconFunction() {} 265 }; 266 267 class BrowserActionSetTitleFunction : public ExtensionActionSetTitleFunction { 268 public: 269 DECLARE_EXTENSION_FUNCTION("browserAction.setTitle", BROWSERACTION_SETTITLE) 270 271 protected: 272 virtual ~BrowserActionSetTitleFunction() {} 273 }; 274 275 class BrowserActionSetPopupFunction : public ExtensionActionSetPopupFunction { 276 public: 277 DECLARE_EXTENSION_FUNCTION("browserAction.setPopup", BROWSERACTION_SETPOPUP) 278 279 protected: 280 virtual ~BrowserActionSetPopupFunction() {} 281 }; 282 283 class BrowserActionGetTitleFunction : public ExtensionActionGetTitleFunction { 284 public: 285 DECLARE_EXTENSION_FUNCTION("browserAction.getTitle", BROWSERACTION_GETTITLE) 286 287 protected: 288 virtual ~BrowserActionGetTitleFunction() {} 289 }; 290 291 class BrowserActionGetPopupFunction : public ExtensionActionGetPopupFunction { 292 public: 293 DECLARE_EXTENSION_FUNCTION("browserAction.getPopup", BROWSERACTION_GETPOPUP) 294 295 protected: 296 virtual ~BrowserActionGetPopupFunction() {} 297 }; 298 299 class BrowserActionSetBadgeTextFunction 300 : public ExtensionActionSetBadgeTextFunction { 301 public: 302 DECLARE_EXTENSION_FUNCTION("browserAction.setBadgeText", 303 BROWSERACTION_SETBADGETEXT) 304 305 protected: 306 virtual ~BrowserActionSetBadgeTextFunction() {} 307 }; 308 309 class BrowserActionSetBadgeBackgroundColorFunction 310 : public ExtensionActionSetBadgeBackgroundColorFunction { 311 public: 312 DECLARE_EXTENSION_FUNCTION("browserAction.setBadgeBackgroundColor", 313 BROWSERACTION_SETBADGEBACKGROUNDCOLOR) 314 315 protected: 316 virtual ~BrowserActionSetBadgeBackgroundColorFunction() {} 317 }; 318 319 class BrowserActionGetBadgeTextFunction 320 : public ExtensionActionGetBadgeTextFunction { 321 public: 322 DECLARE_EXTENSION_FUNCTION("browserAction.getBadgeText", 323 BROWSERACTION_GETBADGETEXT) 324 325 protected: 326 virtual ~BrowserActionGetBadgeTextFunction() {} 327 }; 328 329 class BrowserActionGetBadgeBackgroundColorFunction 330 : public ExtensionActionGetBadgeBackgroundColorFunction { 331 public: 332 DECLARE_EXTENSION_FUNCTION("browserAction.getBadgeBackgroundColor", 333 BROWSERACTION_GETBADGEBACKGROUNDCOLOR) 334 335 protected: 336 virtual ~BrowserActionGetBadgeBackgroundColorFunction() {} 337 }; 338 339 class BrowserActionEnableFunction : public ExtensionActionShowFunction { 340 public: 341 DECLARE_EXTENSION_FUNCTION("browserAction.enable", BROWSERACTION_ENABLE) 342 343 protected: 344 virtual ~BrowserActionEnableFunction() {} 345 }; 346 347 class BrowserActionDisableFunction : public ExtensionActionHideFunction { 348 public: 349 DECLARE_EXTENSION_FUNCTION("browserAction.disable", BROWSERACTION_DISABLE) 350 351 protected: 352 virtual ~BrowserActionDisableFunction() {} 353 }; 354 355 class BrowserActionOpenPopupFunction : public ChromeAsyncExtensionFunction, 356 public content::NotificationObserver { 357 public: 358 DECLARE_EXTENSION_FUNCTION("browserAction.openPopup", 359 BROWSERACTION_OPEN_POPUP) 360 BrowserActionOpenPopupFunction(); 361 362 private: 363 virtual ~BrowserActionOpenPopupFunction() {} 364 365 // ExtensionFunction: 366 virtual bool RunAsync() OVERRIDE; 367 368 virtual void Observe(int type, 369 const content::NotificationSource& source, 370 const content::NotificationDetails& details) OVERRIDE; 371 void OpenPopupTimedOut(); 372 373 content::NotificationRegistrar registrar_; 374 bool response_sent_; 375 376 DISALLOW_COPY_AND_ASSIGN(BrowserActionOpenPopupFunction); 377 }; 378 379 } // namespace extensions 380 381 // 382 // pageAction.* aliases for supported pageAction APIs. 383 // 384 385 class PageActionShowFunction : public extensions::ExtensionActionShowFunction { 386 public: 387 DECLARE_EXTENSION_FUNCTION("pageAction.show", PAGEACTION_SHOW) 388 389 protected: 390 virtual ~PageActionShowFunction() {} 391 }; 392 393 class PageActionHideFunction : public extensions::ExtensionActionHideFunction { 394 public: 395 DECLARE_EXTENSION_FUNCTION("pageAction.hide", PAGEACTION_HIDE) 396 397 protected: 398 virtual ~PageActionHideFunction() {} 399 }; 400 401 class PageActionSetIconFunction 402 : public extensions::ExtensionActionSetIconFunction { 403 public: 404 DECLARE_EXTENSION_FUNCTION("pageAction.setIcon", PAGEACTION_SETICON) 405 406 protected: 407 virtual ~PageActionSetIconFunction() {} 408 }; 409 410 class PageActionSetTitleFunction 411 : public extensions::ExtensionActionSetTitleFunction { 412 public: 413 DECLARE_EXTENSION_FUNCTION("pageAction.setTitle", PAGEACTION_SETTITLE) 414 415 protected: 416 virtual ~PageActionSetTitleFunction() {} 417 }; 418 419 class PageActionSetPopupFunction 420 : public extensions::ExtensionActionSetPopupFunction { 421 public: 422 DECLARE_EXTENSION_FUNCTION("pageAction.setPopup", PAGEACTION_SETPOPUP) 423 424 protected: 425 virtual ~PageActionSetPopupFunction() {} 426 }; 427 428 class PageActionGetTitleFunction 429 : public extensions::ExtensionActionGetTitleFunction { 430 public: 431 DECLARE_EXTENSION_FUNCTION("pageAction.getTitle", PAGEACTION_GETTITLE) 432 433 protected: 434 virtual ~PageActionGetTitleFunction() {} 435 }; 436 437 class PageActionGetPopupFunction 438 : public extensions::ExtensionActionGetPopupFunction { 439 public: 440 DECLARE_EXTENSION_FUNCTION("pageAction.getPopup", PAGEACTION_GETPOPUP) 441 442 protected: 443 virtual ~PageActionGetPopupFunction() {} 444 }; 445 446 // Base class for deprecated page actions APIs 447 class PageActionsFunction : public ChromeSyncExtensionFunction { 448 protected: 449 PageActionsFunction(); 450 virtual ~PageActionsFunction(); 451 bool SetPageActionEnabled(bool enable); 452 }; 453 454 // Implement chrome.pageActions.enableForTab(). 455 class EnablePageActionsFunction : public PageActionsFunction { 456 public: 457 DECLARE_EXTENSION_FUNCTION("pageActions.enableForTab", 458 PAGEACTIONS_ENABLEFORTAB) 459 460 protected: 461 virtual ~EnablePageActionsFunction() {} 462 463 // ExtensionFunction: 464 virtual bool RunSync() OVERRIDE; 465 }; 466 467 // Implement chrome.pageActions.disableForTab(). 468 class DisablePageActionsFunction : public PageActionsFunction { 469 public: 470 DECLARE_EXTENSION_FUNCTION("pageActions.disableForTab", 471 PAGEACTIONS_DISABLEFORTAB) 472 473 protected: 474 virtual ~DisablePageActionsFunction() {} 475 476 // ExtensionFunction: 477 virtual bool RunSync() OVERRIDE; 478 }; 479 480 #endif // CHROME_BROWSER_EXTENSIONS_API_EXTENSION_ACTION_EXTENSION_ACTION_API_H_ 481