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