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 #include "chrome/browser/extensions/extension_warning_service.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "chrome/browser/browser_process.h" 9 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/extensions/extension_service.h" 11 #include "chrome/browser/extensions/extension_system.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile_manager.h" 14 #include "chrome/common/extensions/extension.h" 15 16 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/notification_service.h" 18 19 using content::BrowserThread; 20 21 namespace extensions { 22 23 ExtensionWarningService::ExtensionWarningService(Profile* profile) 24 : profile_(profile) { 25 DCHECK(CalledOnValidThread()); 26 if (profile_) { 27 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 28 content::Source<Profile>(profile_->GetOriginalProfile())); 29 } 30 } 31 32 ExtensionWarningService::~ExtensionWarningService() {} 33 34 void ExtensionWarningService::ClearWarnings( 35 const std::set<ExtensionWarning::WarningType>& types) { 36 DCHECK(CalledOnValidThread()); 37 bool deleted_anything = false; 38 for (ExtensionWarningSet::iterator i = warnings_.begin(); 39 i != warnings_.end();) { 40 if (types.find(i->warning_type()) != types.end()) { 41 deleted_anything = true; 42 warnings_.erase(i++); 43 } else { 44 ++i; 45 } 46 } 47 48 if (deleted_anything) 49 NotifyWarningsChanged(); 50 } 51 52 std::set<ExtensionWarning::WarningType> 53 ExtensionWarningService::GetWarningTypesAffectingExtension( 54 const std::string& extension_id) const { 55 DCHECK(CalledOnValidThread()); 56 std::set<ExtensionWarning::WarningType> result; 57 for (ExtensionWarningSet::const_iterator i = warnings_.begin(); 58 i != warnings_.end(); ++i) { 59 if (i->extension_id() == extension_id) 60 result.insert(i->warning_type()); 61 } 62 return result; 63 } 64 65 std::vector<std::string> 66 ExtensionWarningService::GetWarningMessagesForExtension( 67 const std::string& extension_id) const { 68 DCHECK(CalledOnValidThread()); 69 std::vector<std::string> result; 70 71 const ExtensionService* extension_service = 72 ExtensionSystem::Get(profile_)->extension_service(); 73 74 for (ExtensionWarningSet::const_iterator i = warnings_.begin(); 75 i != warnings_.end(); ++i) { 76 if (i->extension_id() == extension_id) 77 result.push_back(i->GetLocalizedMessage(extension_service->extensions())); 78 } 79 return result; 80 } 81 82 void ExtensionWarningService::AddWarnings( 83 const ExtensionWarningSet& warnings) { 84 DCHECK(CalledOnValidThread()); 85 size_t old_size = warnings_.size(); 86 87 warnings_.insert(warnings.begin(), warnings.end()); 88 89 if (old_size != warnings_.size()) 90 NotifyWarningsChanged(); 91 } 92 93 // static 94 void ExtensionWarningService::NotifyWarningsOnUI( 95 void* profile_id, 96 const ExtensionWarningSet& warnings) { 97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 98 Profile* profile = reinterpret_cast<Profile*>(profile_id); 99 if (!profile || 100 !g_browser_process->profile_manager() || 101 !g_browser_process->profile_manager()->IsValidProfile(profile)) { 102 return; 103 } 104 105 extensions::ExtensionWarningService* warning_service = 106 extensions::ExtensionSystem::Get(profile)->warning_service(); 107 108 warning_service->AddWarnings(warnings); 109 } 110 111 void ExtensionWarningService::AddObserver(Observer* observer) { 112 observer_list_.AddObserver(observer); 113 } 114 115 void ExtensionWarningService::RemoveObserver(Observer* observer) { 116 observer_list_.RemoveObserver(observer); 117 } 118 119 void ExtensionWarningService::NotifyWarningsChanged() { 120 FOR_EACH_OBSERVER(Observer, observer_list_, ExtensionWarningsChanged()); 121 } 122 123 void ExtensionWarningService::Observe( 124 int type, 125 const content::NotificationSource& source, 126 const content::NotificationDetails& details) { 127 switch (type) { 128 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 129 const Extension* extension = 130 content::Details<extensions::UnloadedExtensionInfo>(details)-> 131 extension; 132 // Unloading one extension might have solved the problems of others. 133 // Therefore, we clear warnings of this type for all extensions. 134 std::set<ExtensionWarning::WarningType> warning_types = 135 GetWarningTypesAffectingExtension(extension->id()); 136 ClearWarnings(warning_types); 137 break; 138 } 139 default: 140 NOTREACHED(); 141 break; 142 } 143 } 144 145 } // namespace extensions 146