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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/external_policy_extension_loader.h" 6 7 #include "base/logging.h" 8 #include "base/values.h" 9 #include "chrome/browser/prefs/pref_service.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/common/extensions/extension.h" 12 #include "chrome/common/pref_names.h" 13 #include "content/browser/browser_thread.h" 14 #include "content/common/notification_service.h" 15 #include "content/common/notification_type.h" 16 #include "googleurl/src/gurl.h" 17 18 namespace { 19 20 // Check an extension ID and an URL to be syntactically correct. 21 bool CheckExtension(const std::string& id, const std::string& update_url) { 22 GURL url(update_url); 23 if (!url.is_valid()) { 24 LOG(WARNING) << "Policy specifies invalid update URL for external " 25 << "extension: " << update_url; 26 return false; 27 } 28 if (!Extension::IdIsValid(id)) { 29 LOG(WARNING) << "Policy specifies invalid ID for external " 30 << "extension: " << id; 31 return false; 32 } 33 return true; 34 } 35 36 } // namespace 37 38 ExternalPolicyExtensionLoader::ExternalPolicyExtensionLoader( 39 Profile* profile) 40 : profile_(profile) { 41 pref_change_registrar_.Init(profile_->GetPrefs()); 42 pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this); 43 notification_registrar_.Add(this, 44 NotificationType::PROFILE_DESTROYED, 45 Source<Profile>(profile_)); 46 } 47 48 void ExternalPolicyExtensionLoader::StartLoading() { 49 const ListValue* forcelist = 50 profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList); 51 DictionaryValue* result = new DictionaryValue(); 52 if (forcelist != NULL) { 53 std::string extension_desc; 54 for (ListValue::const_iterator it = forcelist->begin(); 55 it != forcelist->end(); ++it) { 56 if (!(*it)->GetAsString(&extension_desc)) { 57 LOG(WARNING) << "Failed to read forcelist string."; 58 } else { 59 // Each string item of the list has the following form: 60 // extension_id_code;extension_update_url 61 // The update URL might also contain semicolons. 62 size_t pos = extension_desc.find(';'); 63 std::string id = extension_desc.substr(0, pos); 64 std::string update_url = extension_desc.substr(pos+1); 65 if (CheckExtension(id, update_url)) { 66 result->SetString(id + ".external_update_url", update_url); 67 } 68 } 69 } 70 } 71 prefs_.reset(result); 72 LoadFinished(); 73 } 74 75 void ExternalPolicyExtensionLoader::Observe( 76 NotificationType type, 77 const NotificationSource& source, 78 const NotificationDetails& details) { 79 if (profile_ == NULL) return; 80 switch (type.value) { 81 case NotificationType::PREF_CHANGED: { 82 if (Source<PrefService>(source).ptr() == profile_->GetPrefs()) { 83 std::string* pref_name = Details<std::string>(details).ptr(); 84 if (*pref_name == prefs::kExtensionInstallForceList) { 85 StartLoading(); 86 } else { 87 NOTREACHED() << "Unexpected preference name."; 88 } 89 } 90 break; 91 } 92 case NotificationType::PROFILE_DESTROYED: { 93 if (Source<Profile>(source).ptr() == profile_) { 94 notification_registrar_.RemoveAll(); 95 pref_change_registrar_.RemoveAll(); 96 profile_ = NULL; 97 } 98 break; 99 } 100 default: 101 NOTREACHED() << "Unexpected notification type."; 102 } 103 } 104