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 |