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/api/preference/preference_helpers.h" 6 7 #include "base/json/json_writer.h" 8 #include "base/prefs/pref_service.h" 9 #include "base/values.h" 10 #include "chrome/browser/extensions/api/preference/preference_api.h" 11 #include "chrome/browser/extensions/extension_prefs.h" 12 #include "chrome/browser/extensions/extension_service.h" 13 #include "chrome/browser/extensions/extension_system.h" 14 #include "chrome/browser/extensions/extension_util.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "extensions/browser/event_router.h" 17 #include "extensions/common/manifest_handlers/incognito_info.h" 18 19 namespace extensions { 20 namespace preference_helpers { 21 22 namespace { 23 24 const char kIncognitoPersistent[] = "incognito_persistent"; 25 const char kIncognitoSessionOnly[] = "incognito_session_only"; 26 const char kRegular[] = "regular"; 27 const char kRegularOnly[] = "regular_only"; 28 29 const char kLevelOfControlKey[] = "levelOfControl"; 30 31 const char kNotControllable[] = "not_controllable"; 32 const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; 33 const char kControllableByThisExtension[] = "controllable_by_this_extension"; 34 const char kControlledByThisExtension[] = "controlled_by_this_extension"; 35 36 } // namespace 37 38 bool StringToScope(const std::string& s, 39 ExtensionPrefsScope* scope) { 40 if (s == kRegular) 41 *scope = kExtensionPrefsScopeRegular; 42 else if (s == kRegularOnly) 43 *scope = kExtensionPrefsScopeRegularOnly; 44 else if (s == kIncognitoPersistent) 45 *scope = kExtensionPrefsScopeIncognitoPersistent; 46 else if (s == kIncognitoSessionOnly) 47 *scope = kExtensionPrefsScopeIncognitoSessionOnly; 48 else 49 return false; 50 return true; 51 } 52 53 const char* GetLevelOfControl( 54 Profile* profile, 55 const std::string& extension_id, 56 const std::string& browser_pref, 57 bool incognito) { 58 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() 59 : profile->GetPrefs(); 60 bool from_incognito = false; 61 bool* from_incognito_ptr = incognito ? &from_incognito : NULL; 62 const PrefService::Preference* pref = 63 prefs->FindPreference(browser_pref.c_str()); 64 CHECK(pref); 65 66 if (!pref->IsExtensionModifiable()) 67 return kNotControllable; 68 69 if (PreferenceAPI::Get(profile)->DoesExtensionControlPref( 70 extension_id, 71 browser_pref, 72 from_incognito_ptr)) { 73 return kControlledByThisExtension; 74 } 75 76 if (PreferenceAPI::Get(profile)->CanExtensionControlPref(extension_id, 77 browser_pref, 78 incognito)) { 79 return kControllableByThisExtension; 80 } 81 82 return kControlledByOtherExtensions; 83 } 84 85 void DispatchEventToExtensions( 86 Profile* profile, 87 const std::string& event_name, 88 base::ListValue* args, 89 APIPermission::ID permission, 90 bool incognito, 91 const std::string& browser_pref) { 92 EventRouter* router = 93 ExtensionSystem::Get(profile)->event_router(); 94 if (!router || !router->HasEventListener(event_name)) 95 return; 96 ExtensionService* extension_service = 97 ExtensionSystem::Get(profile)->extension_service(); 98 const ExtensionSet* extensions = extension_service->extensions(); 99 for (ExtensionSet::const_iterator it = extensions->begin(); 100 it != extensions->end(); ++it) { 101 std::string extension_id = (*it)->id(); 102 // TODO(bauerb): Only iterate over registered event listeners. 103 if (router->ExtensionHasEventListener(extension_id, event_name) && 104 (*it)->HasAPIPermission(permission) && 105 (!incognito || IncognitoInfo::IsSplitMode(it->get()) || 106 extension_util::CanCrossIncognito(it->get(), extension_service))) { 107 // Inject level of control key-value. 108 base::DictionaryValue* dict; 109 bool rv = args->GetDictionary(0, &dict); 110 DCHECK(rv); 111 std::string level_of_control = 112 GetLevelOfControl(profile, extension_id, browser_pref, incognito); 113 dict->SetString(kLevelOfControlKey, level_of_control); 114 115 // If the extension is in incognito split mode, 116 // a) incognito pref changes are visible only to the incognito tabs 117 // b) regular pref changes are visible only to the incognito tabs if the 118 // incognito pref has not alredy been set 119 Profile* restrict_to_profile = NULL; 120 bool from_incognito = false; 121 if (IncognitoInfo::IsSplitMode(it->get())) { 122 if (incognito && 123 extension_util::IsIncognitoEnabled(extension_id, 124 extension_service)) { 125 restrict_to_profile = profile->GetOffTheRecordProfile(); 126 } else if (!incognito && 127 PreferenceAPI::Get(profile)->DoesExtensionControlPref( 128 extension_id, 129 browser_pref, 130 &from_incognito) && 131 from_incognito) { 132 restrict_to_profile = profile; 133 } 134 } 135 136 scoped_ptr<base::ListValue> args_copy(args->DeepCopy()); 137 scoped_ptr<Event> event(new Event(event_name, args_copy.Pass())); 138 event->restrict_to_browser_context = restrict_to_profile; 139 router->DispatchEventToExtension(extension_id, event.Pass()); 140 } 141 } 142 } 143 144 } // namespace preference_helpers 145 } // namespace extensions 146