Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/activity_log/activity_log.h" | 5 #include "chrome/browser/extensions/activity_log/activity_log.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 ActivityLog* ActivityLog::GetInstance(content::BrowserContext* context) { | 538 ActivityLog* ActivityLog::GetInstance(content::BrowserContext* context) { |
| 539 return ActivityLog::GetFactoryInstance()->Get( | 539 return ActivityLog::GetFactoryInstance()->Get( |
| 540 Profile::FromBrowserContext(context)); | 540 Profile::FromBrowserContext(context)); |
| 541 } | 541 } |
| 542 | 542 |
| 543 // Use GetInstance instead of directly creating an ActivityLog. | 543 // Use GetInstance instead of directly creating an ActivityLog. |
| 544 ActivityLog::ActivityLog(content::BrowserContext* context) | 544 ActivityLog::ActivityLog(content::BrowserContext* context) |
| 545 : database_policy_(NULL), | 545 : database_policy_(NULL), |
| 546 database_policy_type_(ActivityLogPolicy::POLICY_INVALID), | 546 database_policy_type_(ActivityLogPolicy::POLICY_INVALID), |
| 547 profile_(Profile::FromBrowserContext(context)), | 547 profile_(Profile::FromBrowserContext(context)), |
| 548 extension_system_(ExtensionSystem::Get(context)), | |
| 548 db_enabled_(false), | 549 db_enabled_(false), |
| 549 testing_mode_(false), | 550 testing_mode_(false), |
| 550 has_threads_(true), | 551 has_threads_(true), |
| 551 extension_registry_observer_(this), | 552 extension_registry_observer_(this), |
| 552 watchdog_apps_active_(0), | 553 active_consumers_(0), |
| 553 is_active_(false) { | 554 cached_consumer_count_(0), |
| 555 is_active_(false), | |
| 556 weak_factory_(this) { | |
| 554 SetActivityHandlers(); | 557 SetActivityHandlers(); |
| 555 | 558 |
| 556 // This controls whether logging statements are printed & which policy is set. | 559 // This controls whether logging statements are printed & which policy is set. |
| 557 testing_mode_ = base::CommandLine::ForCurrentProcess()->HasSwitch( | 560 testing_mode_ = base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 558 switches::kEnableExtensionActivityLogTesting); | 561 switches::kEnableExtensionActivityLogTesting); |
| 559 | 562 |
| 560 // Check if the watchdog extension is previously installed and active. | 563 // Check if the watchdog extension is previously installed and active. |
| 561 watchdog_apps_active_ = | 564 cached_consumer_count_ = |
| 562 profile_->GetPrefs()->GetInteger(prefs::kWatchdogExtensionActive); | 565 profile_->GetPrefs()->GetInteger(prefs::kWatchdogExtensionActive); |
| 563 | 566 |
| 564 observers_ = new base::ObserverListThreadSafe<Observer>; | 567 observers_ = new base::ObserverListThreadSafe<Observer>; |
| 565 | 568 |
| 566 // Check that the right threads exist for logging to the database. | 569 // Check that the right threads exist for logging to the database. |
| 567 // If not, we shouldn't try to do things that require them. | 570 // If not, we shouldn't try to do things that require them. |
| 568 if (!BrowserThread::IsMessageLoopValid(BrowserThread::DB) || | 571 if (!BrowserThread::IsMessageLoopValid(BrowserThread::DB) || |
| 569 !BrowserThread::IsMessageLoopValid(BrowserThread::FILE) || | 572 !BrowserThread::IsMessageLoopValid(BrowserThread::FILE) || |
| 570 !BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { | 573 !BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { |
| 571 has_threads_ = false; | 574 has_threads_ = false; |
| 572 } | 575 } |
| 573 | 576 |
| 574 db_enabled_ = | |
| 575 has_threads_ && (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 576 switches::kEnableExtensionActivityLogging) || | |
| 577 watchdog_apps_active_); | |
| 578 | |
| 579 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); | 577 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); |
| 580 ChooseDatabasePolicy(); | 578 CheckActive(true); // use cached |
| 581 | 579 extension_system_->ready().Post( |
| 582 CheckActive(); | 580 FROM_HERE, |
| 581 base::Bind(&ActivityLog::OnExtensionSystemReady, | |
| 582 weak_factory_.GetWeakPtr())); | |
| 583 } | 583 } |
| 584 | 584 |
| 585 void ActivityLog::SetDatabasePolicy( | 585 void ActivityLog::SetDatabasePolicy( |
| 586 ActivityLogPolicy::PolicyType policy_type) { | 586 ActivityLogPolicy::PolicyType policy_type) { |
| 587 if (database_policy_type_ == policy_type) | 587 if (database_policy_type_ == policy_type) |
| 588 return; | 588 return; |
| 589 if (!IsDatabaseEnabled() && !IsWatchdogAppActive()) | 589 if (!IsDatabaseEnabled() && !IsWatchdogAppActive()) |
| 590 return; | 590 return; |
| 591 | 591 |
| 592 // Deleting the old policy takes place asynchronously, on the database | 592 // Deleting the old policy takes place asynchronously, on the database |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 632 SetDatabasePolicy(ActivityLogPolicy::POLICY_COUNTS); | 632 SetDatabasePolicy(ActivityLogPolicy::POLICY_COUNTS); |
| 633 } | 633 } |
| 634 | 634 |
| 635 bool ActivityLog::IsDatabaseEnabled() { | 635 bool ActivityLog::IsDatabaseEnabled() { |
| 636 // Make sure we are not enabled when there are no threads. | 636 // Make sure we are not enabled when there are no threads. |
| 637 DCHECK(has_threads_ || !db_enabled_); | 637 DCHECK(has_threads_ || !db_enabled_); |
| 638 return db_enabled_; | 638 return db_enabled_; |
| 639 } | 639 } |
| 640 | 640 |
| 641 bool ActivityLog::IsWatchdogAppActive() { | 641 bool ActivityLog::IsWatchdogAppActive() { |
| 642 return (watchdog_apps_active_ > 0); | 642 return active_consumers_ > 0; |
| 643 } | |
| 644 | |
| 645 void ActivityLog::UpdateCachedConsumerCount() { | |
| 646 cached_consumer_count_ = active_consumers_; | |
| 647 profile_->GetPrefs()->SetInteger(prefs::kWatchdogExtensionActive, | |
| 648 cached_consumer_count_); | |
| 643 } | 649 } |
| 644 | 650 |
| 645 void ActivityLog::SetWatchdogAppActiveForTesting(bool active) { | 651 void ActivityLog::SetWatchdogAppActiveForTesting(bool active) { |
| 646 watchdog_apps_active_ = active ? 1 : 0; | 652 active_consumers_ = active ? 1 : 0; |
| 647 CheckActive(); | 653 CheckActive(false); // don't use cached |
| 648 } | 654 } |
| 649 | 655 |
| 650 void ActivityLog::OnExtensionLoaded(content::BrowserContext* browser_context, | 656 void ActivityLog::OnExtensionLoaded(content::BrowserContext* browser_context, |
| 651 const Extension* extension) { | 657 const Extension* extension) { |
| 652 if (!ActivityLogAPI::IsExtensionWhitelisted(extension->id())) | 658 if (!ActivityLogAPI::IsExtensionWhitelisted(extension->id())) |
| 653 return; | 659 return; |
| 654 if (has_threads_) | |
| 655 db_enabled_ = true; | |
| 656 g_activity_log_state.Get().AddWhitelistedId(extension->id()); | 660 g_activity_log_state.Get().AddWhitelistedId(extension->id()); |
| 657 watchdog_apps_active_++; | 661 ++active_consumers_; |
| 658 profile_->GetPrefs()->SetInteger(prefs::kWatchdogExtensionActive, | |
| 659 watchdog_apps_active_); | |
| 660 if (watchdog_apps_active_ == 1) | |
| 661 ChooseDatabasePolicy(); | |
| 662 | 662 |
| 663 if (!is_active_) | 663 if (!extension_system_->ready().is_signaled()) |
| 664 CheckActive(); | 664 return; |
| 665 | |
| 666 | |
|
asargent_no_longer_on_chrome
2016/09/27 22:54:07
nit: collapse double-newline to just one
Devlin
2016/09/29 17:59:42
Whoops, done.
| |
| 667 CheckActive(false); // don't use cached | |
| 668 UpdateCachedConsumerCount(); | |
| 665 } | 669 } |
| 666 | 670 |
| 667 void ActivityLog::OnExtensionUnloaded(content::BrowserContext* browser_context, | 671 void ActivityLog::OnExtensionUnloaded(content::BrowserContext* browser_context, |
| 668 const Extension* extension, | 672 const Extension* extension, |
| 669 UnloadedExtensionInfo::Reason reason) { | 673 UnloadedExtensionInfo::Reason reason) { |
| 670 if (!ActivityLogAPI::IsExtensionWhitelisted(extension->id())) | 674 if (!ActivityLogAPI::IsExtensionWhitelisted(extension->id())) |
| 671 return; | 675 return; |
| 672 watchdog_apps_active_--; | 676 --active_consumers_; |
| 673 profile_->GetPrefs()->SetInteger(prefs::kWatchdogExtensionActive, | |
| 674 watchdog_apps_active_); | |
| 675 if (watchdog_apps_active_ == 0 && | |
| 676 !base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 677 switches::kEnableExtensionActivityLogging)) { | |
| 678 db_enabled_ = false; | |
| 679 } | |
| 680 | 677 |
| 681 if (is_active_) | 678 if (!extension_system_->ready().is_signaled()) |
| 682 CheckActive(); | 679 return; |
| 680 | |
| 681 CheckActive(false); // don't use cached | |
| 682 UpdateCachedConsumerCount(); | |
| 683 } | 683 } |
| 684 | 684 |
| 685 // OnExtensionUnloaded will also be called right before this. | 685 // OnExtensionUnloaded will also be called right before this. |
| 686 void ActivityLog::OnExtensionUninstalled( | 686 void ActivityLog::OnExtensionUninstalled( |
| 687 content::BrowserContext* browser_context, | 687 content::BrowserContext* browser_context, |
| 688 const Extension* extension, | 688 const Extension* extension, |
| 689 extensions::UninstallReason reason) { | 689 extensions::UninstallReason reason) { |
| 690 if (ActivityLogAPI::IsExtensionWhitelisted(extension->id()) && | 690 if (ActivityLogAPI::IsExtensionWhitelisted(extension->id()) && |
| 691 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 691 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 692 switches::kEnableExtensionActivityLogging) && | 692 switches::kEnableExtensionActivityLogging) && |
| 693 watchdog_apps_active_ == 0) { | 693 active_consumers_ == 0) { |
| 694 DeleteDatabase(); | 694 DeleteDatabase(); |
| 695 } else if (database_policy_) { | 695 } else if (database_policy_) { |
| 696 database_policy_->RemoveExtensionData(extension->id()); | 696 database_policy_->RemoveExtensionData(extension->id()); |
| 697 } | 697 } |
| 698 } | 698 } |
| 699 | 699 |
| 700 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { | 700 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { |
| 701 observers_->AddObserver(observer); | 701 observers_->AddObserver(observer); |
| 702 } | 702 } |
| 703 | 703 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 725 base::StartsWith(action->api_name(), kDomXhrPrefix, | 725 base::StartsWith(action->api_name(), kDomXhrPrefix, |
| 726 base::CompareCase::SENSITIVE) && | 726 base::CompareCase::SENSITIVE) && |
| 727 action->other()) { | 727 action->other()) { |
| 728 base::DictionaryValue* other = action->mutable_other(); | 728 base::DictionaryValue* other = action->mutable_other(); |
| 729 int dom_verb = -1; | 729 int dom_verb = -1; |
| 730 if (other->GetInteger(constants::kActionDomVerb, &dom_verb) && | 730 if (other->GetInteger(constants::kActionDomVerb, &dom_verb) && |
| 731 dom_verb == DomActionType::METHOD) { | 731 dom_verb == DomActionType::METHOD) { |
| 732 other->SetInteger(constants::kActionDomVerb, DomActionType::XHR); | 732 other->SetInteger(constants::kActionDomVerb, DomActionType::XHR); |
| 733 } | 733 } |
| 734 } | 734 } |
| 735 | |
| 736 if (IsDatabaseEnabled() && database_policy_) | 735 if (IsDatabaseEnabled() && database_policy_) |
| 737 database_policy_->ProcessAction(action); | 736 database_policy_->ProcessAction(action); |
| 738 if (IsWatchdogAppActive()) | 737 if (IsWatchdogAppActive()) |
| 739 observers_->Notify(FROM_HERE, &Observer::OnExtensionActivity, action); | 738 observers_->Notify(FROM_HERE, &Observer::OnExtensionActivity, action); |
| 740 if (testing_mode_) | 739 if (testing_mode_) |
| 741 VLOG(1) << action->PrintForDebug(); | 740 VLOG(1) << action->PrintForDebug(); |
| 742 } | 741 } |
| 743 | 742 |
| 744 bool ActivityLog::ShouldLog(const std::string& extension_id) const { | 743 bool ActivityLog::ShouldLog(const std::string& extension_id) const { |
| 745 return is_active_ && !ActivityLogAPI::IsExtensionWhitelisted(extension_id); | 744 return is_active_ && !ActivityLogAPI::IsExtensionWhitelisted(extension_id); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 838 urls.push_back(url); | 837 urls.push_back(url); |
| 839 RemoveURLs(urls); | 838 RemoveURLs(urls); |
| 840 } | 839 } |
| 841 | 840 |
| 842 void ActivityLog::DeleteDatabase() { | 841 void ActivityLog::DeleteDatabase() { |
| 843 if (!database_policy_) | 842 if (!database_policy_) |
| 844 return; | 843 return; |
| 845 database_policy_->DeleteDatabase(); | 844 database_policy_->DeleteDatabase(); |
| 846 } | 845 } |
| 847 | 846 |
| 848 void ActivityLog::CheckActive() { | 847 void ActivityLog::CheckActive(bool use_cached) { |
| 849 bool has_db = db_enabled_ && database_policy_; | 848 bool has_consumer = |
| 849 active_consumers_ || (use_cached && cached_consumer_count_); | |
| 850 bool needs_db = | |
| 851 has_threads_ && (has_consumer || | |
| 852 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 853 switches::kEnableExtensionActivityLogging)); | |
| 854 bool should_be_active = needs_db || has_consumer; | |
| 855 | |
| 856 if (should_be_active == is_active_) | |
| 857 return; | |
| 858 | |
| 850 ActivityLogState& state = g_activity_log_state.Get(); | 859 ActivityLogState& state = g_activity_log_state.Get(); |
| 851 content::BrowserContext* off_the_record = | 860 content::BrowserContext* off_the_record = |
| 852 profile_->HasOffTheRecordProfile() ? profile_->GetOffTheRecordProfile() | 861 profile_->HasOffTheRecordProfile() ? profile_->GetOffTheRecordProfile() |
| 853 : nullptr; | 862 : nullptr; |
| 863 bool has_db = db_enabled_ && database_policy_; | |
| 864 bool old_is_active = is_active_; | |
| 854 | 865 |
| 855 bool old_is_active = is_active_; | 866 if (should_be_active) { |
| 856 if (has_db || IsWatchdogAppActive()) { | 867 if (needs_db && !has_db) { |
| 857 if (is_active_) | 868 db_enabled_ = true; |
| 858 return; // Already enabled. | 869 ChooseDatabasePolicy(); |
| 870 } | |
| 871 | |
| 859 state.AddActiveContext(profile_); | 872 state.AddActiveContext(profile_); |
| 860 if (off_the_record) | 873 if (off_the_record) |
| 861 state.AddActiveContext(off_the_record); | 874 state.AddActiveContext(off_the_record); |
| 862 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | 875 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, |
| 863 content::NotificationService::AllSources()); | 876 content::NotificationService::AllSources()); |
| 864 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 877 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 865 content::NotificationService::AllSources()); | 878 content::NotificationService::AllSources()); |
| 866 is_active_ = true; | 879 is_active_ = true; |
| 867 } else if (is_active_) { | 880 } else { |
| 881 if (has_db && !needs_db) | |
| 882 db_enabled_ = false; | |
| 868 state.RemoveActiveContext(profile_); | 883 state.RemoveActiveContext(profile_); |
| 869 if (off_the_record) | 884 if (off_the_record) |
| 870 state.RemoveActiveContext(off_the_record); | 885 state.RemoveActiveContext(off_the_record); |
| 871 registrar_.RemoveAll(); | 886 registrar_.RemoveAll(); |
| 872 is_active_ = false; | 887 is_active_ = false; |
| 873 } | 888 } |
| 874 | 889 |
| 875 if (old_is_active != is_active_) { | 890 DCHECK_NE(is_active_, old_is_active); |
| 876 for (content::RenderProcessHost::iterator iter( | 891 for (content::RenderProcessHost::iterator iter( |
| 877 content::RenderProcessHost::AllHostsIterator()); | 892 content::RenderProcessHost::AllHostsIterator()); |
| 878 !iter.IsAtEnd(); iter.Advance()) { | 893 !iter.IsAtEnd(); iter.Advance()) { |
| 879 content::RenderProcessHost* host = iter.GetCurrentValue(); | 894 content::RenderProcessHost* host = iter.GetCurrentValue(); |
| 880 if (profile_->IsSameProfile( | 895 if (profile_->IsSameProfile( |
| 881 Profile::FromBrowserContext(host->GetBrowserContext()))) { | 896 Profile::FromBrowserContext(host->GetBrowserContext()))) { |
| 882 host->Send(new ExtensionMsg_SetActivityLoggingEnabled(is_active_)); | 897 host->Send(new ExtensionMsg_SetActivityLoggingEnabled(is_active_)); |
| 883 } | |
| 884 } | 898 } |
| 885 } | 899 } |
| 886 } | 900 } |
| 887 | 901 |
| 888 void ActivityLog::Observe(int type, | 902 void ActivityLog::Observe(int type, |
| 889 const content::NotificationSource& source, | 903 const content::NotificationSource& source, |
| 890 const content::NotificationDetails& details) { | 904 const content::NotificationDetails& details) { |
| 891 DCHECK(is_active_); | 905 DCHECK(is_active_); |
| 892 switch (type) { | 906 switch (type) { |
| 893 case chrome::NOTIFICATION_PROFILE_CREATED: { | 907 case chrome::NOTIFICATION_PROFILE_CREATED: { |
| 894 Profile* profile = content::Source<Profile>(source).ptr(); | 908 Profile* profile = content::Source<Profile>(source).ptr(); |
| 895 if (profile_->IsSameProfile(profile)) | 909 if (profile_->IsSameProfile(profile)) |
| 896 g_activity_log_state.Get().AddActiveContext(profile); | 910 g_activity_log_state.Get().AddActiveContext(profile); |
| 897 break; | 911 break; |
| 898 } | 912 } |
| 899 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | 913 case chrome::NOTIFICATION_PROFILE_DESTROYED: { |
| 900 Profile* profile = content::Source<Profile>(source).ptr(); | 914 Profile* profile = content::Source<Profile>(source).ptr(); |
| 901 if (profile_->IsSameProfile(profile)) | 915 if (profile_->IsSameProfile(profile)) |
| 902 g_activity_log_state.Get().RemoveActiveContext(profile); | 916 g_activity_log_state.Get().RemoveActiveContext(profile); |
| 903 break; | 917 break; |
| 904 } | 918 } |
| 905 default: | 919 default: |
| 906 NOTREACHED(); | 920 NOTREACHED(); |
| 907 } | 921 } |
| 908 } | 922 } |
| 909 | 923 |
| 924 void ActivityLog::OnExtensionSystemReady() { | |
| 925 if (active_consumers_ != cached_consumer_count_) { | |
| 926 CheckActive(false); | |
| 927 UpdateCachedConsumerCount(); | |
| 928 } | |
| 929 } | |
| 930 | |
| 910 template <> | 931 template <> |
| 911 void BrowserContextKeyedAPIFactory<ActivityLog>::DeclareFactoryDependencies() { | 932 void BrowserContextKeyedAPIFactory<ActivityLog>::DeclareFactoryDependencies() { |
| 912 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); | 933 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); |
| 913 DependsOn(ExtensionRegistryFactory::GetInstance()); | 934 DependsOn(ExtensionRegistryFactory::GetInstance()); |
| 914 } | 935 } |
| 915 | 936 |
| 916 } // namespace extensions | 937 } // namespace extensions |
| OLD | NEW |