| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 5 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 ACTIVE = 2, | 65 ACTIVE = 2, |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 // Whether the browser action is visible in the toolbar. | 68 // Whether the browser action is visible in the toolbar. |
| 69 const char kBrowserActionVisible[] = "browser_action_visible"; | 69 const char kBrowserActionVisible[] = "browser_action_visible"; |
| 70 | 70 |
| 71 // Errors. | 71 // Errors. |
| 72 const char kNoExtensionActionError[] = | 72 const char kNoExtensionActionError[] = |
| 73 "This extension has no action specified."; | 73 "This extension has no action specified."; |
| 74 const char kNoTabError[] = "No tab with id: *."; | 74 const char kNoTabError[] = "No tab with id: *."; |
| 75 const char kNoPageActionError[] = | |
| 76 "This extension has no page action specified."; | |
| 77 const char kUrlNotActiveError[] = "This url is no longer active: *."; | |
| 78 const char kOpenPopupError[] = | 75 const char kOpenPopupError[] = |
| 79 "Failed to show popup either because there is an existing popup or another " | 76 "Failed to show popup either because there is an existing popup or another " |
| 80 "error occurred."; | 77 "error occurred."; |
| 81 const char kInternalError[] = "Internal error."; | 78 const char kInternalError[] = "Internal error."; |
| 82 | 79 |
| 83 struct IconRepresentationInfo { | 80 struct IconRepresentationInfo { |
| 84 // Size as a string that will be used to retrieve representation value from | 81 // Size as a string that will be used to retrieve representation value from |
| 85 // SetIcon function arguments. | 82 // SetIcon function arguments. |
| 86 const char* size_string; | 83 const char* size_string; |
| 87 // Scale factor for which the represantion should be used. | 84 // Scale factor for which the represantion should be used. |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 registry->RegisterFunction<BrowserActionSetPopupFunction>(); | 249 registry->RegisterFunction<BrowserActionSetPopupFunction>(); |
| 253 registry->RegisterFunction<BrowserActionGetTitleFunction>(); | 250 registry->RegisterFunction<BrowserActionGetTitleFunction>(); |
| 254 registry->RegisterFunction<BrowserActionGetBadgeTextFunction>(); | 251 registry->RegisterFunction<BrowserActionGetBadgeTextFunction>(); |
| 255 registry->RegisterFunction<BrowserActionGetBadgeBackgroundColorFunction>(); | 252 registry->RegisterFunction<BrowserActionGetBadgeBackgroundColorFunction>(); |
| 256 registry->RegisterFunction<BrowserActionGetPopupFunction>(); | 253 registry->RegisterFunction<BrowserActionGetPopupFunction>(); |
| 257 registry->RegisterFunction<BrowserActionEnableFunction>(); | 254 registry->RegisterFunction<BrowserActionEnableFunction>(); |
| 258 registry->RegisterFunction<BrowserActionDisableFunction>(); | 255 registry->RegisterFunction<BrowserActionDisableFunction>(); |
| 259 registry->RegisterFunction<BrowserActionOpenPopupFunction>(); | 256 registry->RegisterFunction<BrowserActionOpenPopupFunction>(); |
| 260 | 257 |
| 261 // Page Actions | 258 // Page Actions |
| 262 registry->RegisterFunction<EnablePageActionsFunction>(); | |
| 263 registry->RegisterFunction<DisablePageActionsFunction>(); | |
| 264 registry->RegisterFunction<PageActionShowFunction>(); | 259 registry->RegisterFunction<PageActionShowFunction>(); |
| 265 registry->RegisterFunction<PageActionHideFunction>(); | 260 registry->RegisterFunction<PageActionHideFunction>(); |
| 266 registry->RegisterFunction<PageActionSetIconFunction>(); | 261 registry->RegisterFunction<PageActionSetIconFunction>(); |
| 267 registry->RegisterFunction<PageActionSetTitleFunction>(); | 262 registry->RegisterFunction<PageActionSetTitleFunction>(); |
| 268 registry->RegisterFunction<PageActionSetPopupFunction>(); | 263 registry->RegisterFunction<PageActionSetPopupFunction>(); |
| 269 registry->RegisterFunction<PageActionGetTitleFunction>(); | 264 registry->RegisterFunction<PageActionGetTitleFunction>(); |
| 270 registry->RegisterFunction<PageActionGetPopupFunction>(); | 265 registry->RegisterFunction<PageActionGetPopupFunction>(); |
| 271 } | 266 } |
| 272 | 267 |
| 273 ExtensionActionAPI::~ExtensionActionAPI() { | 268 ExtensionActionAPI::~ExtensionActionAPI() { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 302 ExtensionPrefs* prefs, | 297 ExtensionPrefs* prefs, |
| 303 const std::string& extension_id, | 298 const std::string& extension_id, |
| 304 bool visible) { | 299 bool visible) { |
| 305 if (GetBrowserActionVisibility(prefs, extension_id) == visible) | 300 if (GetBrowserActionVisibility(prefs, extension_id) == visible) |
| 306 return; | 301 return; |
| 307 | 302 |
| 308 prefs->UpdateExtensionPref(extension_id, | 303 prefs->UpdateExtensionPref(extension_id, |
| 309 kBrowserActionVisible, | 304 kBrowserActionVisible, |
| 310 new base::FundamentalValue(visible)); | 305 new base::FundamentalValue(visible)); |
| 311 content::NotificationService::current()->Notify( | 306 content::NotificationService::current()->Notify( |
| 312 extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, | 307 NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, |
| 313 content::Source<ExtensionPrefs>(prefs), | 308 content::Source<ExtensionPrefs>(prefs), |
| 314 content::Details<const std::string>(&extension_id)); | 309 content::Details<const std::string>(&extension_id)); |
| 315 } | 310 } |
| 316 | 311 |
| 317 // static | 312 // static |
| 318 void ExtensionActionAPI::BrowserActionExecuted( | 313 void ExtensionActionAPI::BrowserActionExecuted( |
| 319 content::BrowserContext* context, | 314 content::BrowserContext* context, |
| 320 const ExtensionAction& browser_action, | 315 const ExtensionAction& browser_action, |
| 321 WebContents* web_contents) { | 316 WebContents* web_contents) { |
| 322 ExtensionActionExecuted(context, browser_action, web_contents); | 317 ExtensionActionExecuted(context, browser_action, web_contents); |
| 323 } | 318 } |
| 324 | 319 |
| 325 // static | 320 // static |
| 326 void ExtensionActionAPI::PageActionExecuted(content::BrowserContext* context, | 321 void ExtensionActionAPI::PageActionExecuted(content::BrowserContext* context, |
| 327 const ExtensionAction& page_action, | 322 const ExtensionAction& page_action, |
| 328 int tab_id, | 323 int tab_id, |
| 329 const std::string& url, | 324 const std::string& url, |
| 330 int button) { | 325 int button) { |
| 331 DispatchOldPageActionEvent(context, | 326 DispatchOldPageActionEvent(context, |
| 332 page_action.extension_id(), | 327 page_action.extension_id(), |
| 333 page_action.id(), | 328 page_action.id(), |
| 334 tab_id, | 329 tab_id, |
| 335 url, | 330 url, |
| 336 button); | 331 button); |
| 337 WebContents* web_contents = NULL; | 332 WebContents* web_contents = NULL; |
| 338 if (!extensions::ExtensionTabUtil::GetTabById( | 333 if (!ExtensionTabUtil::GetTabById( |
| 339 tab_id, | 334 tab_id, |
| 340 Profile::FromBrowserContext(context), | 335 Profile::FromBrowserContext(context), |
| 341 context->IsOffTheRecord(), | 336 context->IsOffTheRecord(), |
| 342 NULL, | 337 NULL, |
| 343 NULL, | 338 NULL, |
| 344 &web_contents, | 339 &web_contents, |
| 345 NULL)) { | 340 NULL)) { |
| 346 return; | 341 return; |
| 347 } | 342 } |
| 348 ExtensionActionExecuted(context, page_action, web_contents); | 343 ExtensionActionExecuted(context, page_action, web_contents); |
| 349 } | 344 } |
| 350 | 345 |
| 351 // static | 346 // static |
| 352 void ExtensionActionAPI::DispatchEventToExtension( | 347 void ExtensionActionAPI::DispatchEventToExtension( |
| 353 content::BrowserContext* context, | 348 content::BrowserContext* context, |
| 354 const std::string& extension_id, | 349 const std::string& extension_id, |
| 355 const std::string& event_name, | 350 const std::string& event_name, |
| 356 scoped_ptr<base::ListValue> event_args) { | 351 scoped_ptr<base::ListValue> event_args) { |
| 357 if (!extensions::EventRouter::Get(context)) | 352 if (!EventRouter::Get(context)) |
| 358 return; | 353 return; |
| 359 | 354 |
| 360 scoped_ptr<Event> event(new Event(event_name, event_args.Pass())); | 355 scoped_ptr<Event> event(new Event(event_name, event_args.Pass())); |
| 361 event->restrict_to_browser_context = context; | 356 event->restrict_to_browser_context = context; |
| 362 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; | 357 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; |
| 363 EventRouter::Get(context) | 358 EventRouter::Get(context) |
| 364 ->DispatchEventToExtension(extension_id, event.Pass()); | 359 ->DispatchEventToExtension(extension_id, event.Pass()); |
| 365 } | 360 } |
| 366 | 361 |
| 367 // static | 362 // static |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 event_name = "pageAction.onClicked"; | 394 event_name = "pageAction.onClicked"; |
| 400 break; | 395 break; |
| 401 case ActionInfo::TYPE_SYSTEM_INDICATOR: | 396 case ActionInfo::TYPE_SYSTEM_INDICATOR: |
| 402 // The System Indicator handles its own clicks. | 397 // The System Indicator handles its own clicks. |
| 403 break; | 398 break; |
| 404 } | 399 } |
| 405 | 400 |
| 406 if (event_name) { | 401 if (event_name) { |
| 407 scoped_ptr<base::ListValue> args(new base::ListValue()); | 402 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 408 base::DictionaryValue* tab_value = | 403 base::DictionaryValue* tab_value = |
| 409 extensions::ExtensionTabUtil::CreateTabValue(web_contents); | 404 ExtensionTabUtil::CreateTabValue(web_contents); |
| 410 args->Append(tab_value); | 405 args->Append(tab_value); |
| 411 | 406 |
| 412 DispatchEventToExtension( | 407 DispatchEventToExtension( |
| 413 context, extension_action.extension_id(), event_name, args.Pass()); | 408 context, extension_action.extension_id(), event_name, args.Pass()); |
| 414 } | 409 } |
| 415 } | 410 } |
| 416 | 411 |
| 417 void ExtensionActionAPI::AddObserver(Observer* observer) { | 412 void ExtensionActionAPI::AddObserver(Observer* observer) { |
| 418 observers_.AddObserver(observer); | 413 observers_.AddObserver(observer); |
| 419 } | 414 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 } | 451 } |
| 457 | 452 |
| 458 // | 453 // |
| 459 // ExtensionActionStorageManager | 454 // ExtensionActionStorageManager |
| 460 // | 455 // |
| 461 | 456 |
| 462 ExtensionActionStorageManager::ExtensionActionStorageManager(Profile* profile) | 457 ExtensionActionStorageManager::ExtensionActionStorageManager(Profile* profile) |
| 463 : profile_(profile), extension_registry_observer_(this) { | 458 : profile_(profile), extension_registry_observer_(this) { |
| 464 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); | 459 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); |
| 465 registrar_.Add(this, | 460 registrar_.Add(this, |
| 466 extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, | 461 NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, |
| 467 content::NotificationService::AllBrowserContextsAndSources()); | 462 content::NotificationService::AllBrowserContextsAndSources()); |
| 468 | 463 |
| 469 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); | 464 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); |
| 470 if (storage) | 465 if (storage) |
| 471 storage->RegisterKey(kBrowserActionStorageKey); | 466 storage->RegisterKey(kBrowserActionStorageKey); |
| 472 } | 467 } |
| 473 | 468 |
| 474 ExtensionActionStorageManager::~ExtensionActionStorageManager() { | 469 ExtensionActionStorageManager::~ExtensionActionStorageManager() { |
| 475 } | 470 } |
| 476 | 471 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 489 base::Bind(&ExtensionActionStorageManager::ReadFromStorage, | 484 base::Bind(&ExtensionActionStorageManager::ReadFromStorage, |
| 490 AsWeakPtr(), | 485 AsWeakPtr(), |
| 491 extension->id())); | 486 extension->id())); |
| 492 } | 487 } |
| 493 } | 488 } |
| 494 | 489 |
| 495 void ExtensionActionStorageManager::Observe( | 490 void ExtensionActionStorageManager::Observe( |
| 496 int type, | 491 int type, |
| 497 const content::NotificationSource& source, | 492 const content::NotificationSource& source, |
| 498 const content::NotificationDetails& details) { | 493 const content::NotificationDetails& details) { |
| 499 DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED); | 494 DCHECK_EQ(type, NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED); |
| 500 ExtensionAction* extension_action = | 495 ExtensionAction* extension_action = |
| 501 content::Source<ExtensionAction>(source).ptr(); | 496 content::Source<ExtensionAction>(source).ptr(); |
| 502 Profile* profile = content::Details<Profile>(details).ptr(); | 497 Profile* profile = content::Details<Profile>(details).ptr(); |
| 503 if (profile != profile_) | 498 if (profile != profile_) |
| 504 return; | 499 return; |
| 505 | 500 |
| 506 WriteToStorage(extension_action); | 501 WriteToStorage(extension_action); |
| 507 } | 502 } |
| 508 | 503 |
| 509 void ExtensionActionStorageManager::WriteToStorage( | 504 void ExtensionActionStorageManager::WriteToStorage( |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 error_ = kInternalError; | 806 error_ = kInternalError; |
| 812 return false; | 807 return false; |
| 813 } | 808 } |
| 814 | 809 |
| 815 if (!model->ShowBrowserActionPopup(extension_)) { | 810 if (!model->ShowBrowserActionPopup(extension_)) { |
| 816 error_ = kOpenPopupError; | 811 error_ = kOpenPopupError; |
| 817 return false; | 812 return false; |
| 818 } | 813 } |
| 819 | 814 |
| 820 registrar_.Add(this, | 815 registrar_.Add(this, |
| 821 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 816 NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
| 822 content::Source<Profile>(GetProfile())); | 817 content::Source<Profile>(GetProfile())); |
| 823 | 818 |
| 824 // Set a timeout for waiting for the notification that the popup is loaded. | 819 // Set a timeout for waiting for the notification that the popup is loaded. |
| 825 // Waiting is required so that the popup view can be retrieved by the custom | 820 // Waiting is required so that the popup view can be retrieved by the custom |
| 826 // bindings for the response callback. It's also needed to keep this function | 821 // bindings for the response callback. It's also needed to keep this function |
| 827 // instance around until a notification is observed. | 822 // instance around until a notification is observed. |
| 828 base::MessageLoopForUI::current()->PostDelayedTask( | 823 base::MessageLoopForUI::current()->PostDelayedTask( |
| 829 FROM_HERE, | 824 FROM_HERE, |
| 830 base::Bind(&BrowserActionOpenPopupFunction::OpenPopupTimedOut, this), | 825 base::Bind(&BrowserActionOpenPopupFunction::OpenPopupTimedOut, this), |
| 831 base::TimeDelta::FromSeconds(10)); | 826 base::TimeDelta::FromSeconds(10)); |
| 832 return true; | 827 return true; |
| 833 } | 828 } |
| 834 | 829 |
| 835 void BrowserActionOpenPopupFunction::OpenPopupTimedOut() { | 830 void BrowserActionOpenPopupFunction::OpenPopupTimedOut() { |
| 836 if (response_sent_) | 831 if (response_sent_) |
| 837 return; | 832 return; |
| 838 | 833 |
| 839 DVLOG(1) << "chrome.browserAction.openPopup did not show a popup."; | 834 DVLOG(1) << "chrome.browserAction.openPopup did not show a popup."; |
| 840 error_ = kOpenPopupError; | 835 error_ = kOpenPopupError; |
| 841 SendResponse(false); | 836 SendResponse(false); |
| 842 response_sent_ = true; | 837 response_sent_ = true; |
| 843 } | 838 } |
| 844 | 839 |
| 845 void BrowserActionOpenPopupFunction::Observe( | 840 void BrowserActionOpenPopupFunction::Observe( |
| 846 int type, | 841 int type, |
| 847 const content::NotificationSource& source, | 842 const content::NotificationSource& source, |
| 848 const content::NotificationDetails& details) { | 843 const content::NotificationDetails& details) { |
| 849 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, type); | 844 DCHECK_EQ(NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, type); |
| 850 if (response_sent_) | 845 if (response_sent_) |
| 851 return; | 846 return; |
| 852 | 847 |
| 853 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); | 848 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); |
| 854 if (host->extension_host_type() != VIEW_TYPE_EXTENSION_POPUP || | 849 if (host->extension_host_type() != VIEW_TYPE_EXTENSION_POPUP || |
| 855 host->extension()->id() != extension_->id()) | 850 host->extension()->id() != extension_->id()) |
| 856 return; | 851 return; |
| 857 | 852 |
| 858 SendResponse(true); | 853 SendResponse(true); |
| 859 response_sent_ = true; | 854 response_sent_ = true; |
| 860 registrar_.RemoveAll(); | 855 registrar_.RemoveAll(); |
| 861 } | 856 } |
| 862 | 857 |
| 863 } // namespace extensions | 858 } // namespace extensions |
| 864 | |
| 865 // | |
| 866 // PageActionsFunction (deprecated) | |
| 867 // | |
| 868 | |
| 869 PageActionsFunction::PageActionsFunction() { | |
| 870 } | |
| 871 | |
| 872 PageActionsFunction::~PageActionsFunction() { | |
| 873 } | |
| 874 | |
| 875 bool PageActionsFunction::SetPageActionEnabled(bool enable) { | |
| 876 std::string extension_action_id; | |
| 877 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_action_id)); | |
| 878 base::DictionaryValue* action = NULL; | |
| 879 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &action)); | |
| 880 | |
| 881 int tab_id; | |
| 882 EXTENSION_FUNCTION_VALIDATE(action->GetInteger( | |
| 883 page_actions_keys::kTabIdKey, &tab_id)); | |
| 884 std::string url; | |
| 885 EXTENSION_FUNCTION_VALIDATE(action->GetString( | |
| 886 page_actions_keys::kUrlKey, &url)); | |
| 887 | |
| 888 std::string title; | |
| 889 if (enable) { | |
| 890 if (action->HasKey(page_actions_keys::kTitleKey)) | |
| 891 EXTENSION_FUNCTION_VALIDATE(action->GetString( | |
| 892 page_actions_keys::kTitleKey, &title)); | |
| 893 } | |
| 894 | |
| 895 ExtensionAction* page_action = extensions::ExtensionActionManager::Get( | |
| 896 GetProfile())->GetPageAction(*extension()); | |
| 897 if (!page_action) { | |
| 898 error_ = extensions::kNoPageActionError; | |
| 899 return false; | |
| 900 } | |
| 901 | |
| 902 // Find the WebContents that contains this tab id. | |
| 903 WebContents* contents = NULL; | |
| 904 bool result = extensions::ExtensionTabUtil::GetTabById( | |
| 905 tab_id, GetProfile(), include_incognito(), NULL, NULL, &contents, NULL); | |
| 906 if (!result || !contents) { | |
| 907 error_ = extensions::ErrorUtils::FormatErrorMessage( | |
| 908 extensions::kNoTabError, base::IntToString(tab_id)); | |
| 909 return false; | |
| 910 } | |
| 911 | |
| 912 // Make sure the URL hasn't changed. | |
| 913 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry(); | |
| 914 if (!entry || url != entry->GetURL().spec()) { | |
| 915 error_ = extensions::ErrorUtils::FormatErrorMessage( | |
| 916 extensions::kUrlNotActiveError, url); | |
| 917 return false; | |
| 918 } | |
| 919 | |
| 920 // Set visibility and broadcast notifications that the UI should be updated. | |
| 921 page_action->SetIsVisible(tab_id, enable); | |
| 922 page_action->SetTitle(tab_id, title); | |
| 923 extensions::LocationBarController::NotifyChange(contents); | |
| 924 | |
| 925 return true; | |
| 926 } | |
| 927 | |
| 928 bool EnablePageActionsFunction::RunSync() { | |
| 929 return SetPageActionEnabled(true); | |
| 930 } | |
| 931 | |
| 932 bool DisablePageActionsFunction::RunSync() { | |
| 933 return SetPageActionEnabled(false); | |
| 934 } | |
| OLD | NEW |