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_service.h" 12#include "chrome/browser/extensions/extension_util.h" 13#include "chrome/browser/profiles/profile.h" 14#include "extensions/browser/event_router.h" 15#include "extensions/browser/extension_prefs.h" 16#include "extensions/browser/extension_system.h" 17#include "extensions/common/manifest_handlers/incognito_info.h" 18#include "extensions/common/permissions/permissions_data.h" 19 20namespace extensions { 21namespace preference_helpers { 22 23namespace { 24 25const char kIncognitoPersistent[] = "incognito_persistent"; 26const char kIncognitoSessionOnly[] = "incognito_session_only"; 27const char kRegular[] = "regular"; 28const char kRegularOnly[] = "regular_only"; 29 30const char kLevelOfControlKey[] = "levelOfControl"; 31 32const char kNotControllable[] = "not_controllable"; 33const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; 34const char kControllableByThisExtension[] = "controllable_by_this_extension"; 35const char kControlledByThisExtension[] = "controlled_by_this_extension"; 36 37} // namespace 38 39bool StringToScope(const std::string& s, 40 ExtensionPrefsScope* scope) { 41 if (s == kRegular) 42 *scope = kExtensionPrefsScopeRegular; 43 else if (s == kRegularOnly) 44 *scope = kExtensionPrefsScopeRegularOnly; 45 else if (s == kIncognitoPersistent) 46 *scope = kExtensionPrefsScopeIncognitoPersistent; 47 else if (s == kIncognitoSessionOnly) 48 *scope = kExtensionPrefsScopeIncognitoSessionOnly; 49 else 50 return false; 51 return true; 52} 53 54const char* GetLevelOfControl( 55 Profile* profile, 56 const std::string& extension_id, 57 const std::string& browser_pref, 58 bool incognito) { 59 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() 60 : profile->GetPrefs(); 61 bool from_incognito = false; 62 bool* from_incognito_ptr = incognito ? &from_incognito : NULL; 63 const PrefService::Preference* pref = 64 prefs->FindPreference(browser_pref.c_str()); 65 CHECK(pref); 66 67 if (!pref->IsExtensionModifiable()) 68 return kNotControllable; 69 70 if (PreferenceAPI::Get(profile)->DoesExtensionControlPref( 71 extension_id, 72 browser_pref, 73 from_incognito_ptr)) { 74 return kControlledByThisExtension; 75 } 76 77 if (PreferenceAPI::Get(profile)->CanExtensionControlPref(extension_id, 78 browser_pref, 79 incognito)) { 80 return kControllableByThisExtension; 81 } 82 83 return kControlledByOtherExtensions; 84} 85 86void DispatchEventToExtensions( 87 Profile* profile, 88 const std::string& event_name, 89 base::ListValue* args, 90 APIPermission::ID permission, 91 bool incognito, 92 const std::string& browser_pref) { 93 EventRouter* router = EventRouter::Get(profile); 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)->permissions_data()->HasAPIPermission(permission) && 105 (!incognito || IncognitoInfo::IsSplitMode(it->get()) || 106 util::CanCrossIncognito(it->get(), profile))) { 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 util::IsIncognitoEnabled(extension_id, profile)) { 124 restrict_to_profile = profile->GetOffTheRecordProfile(); 125 } else if (!incognito && 126 PreferenceAPI::Get(profile)->DoesExtensionControlPref( 127 extension_id, 128 browser_pref, 129 &from_incognito) && 130 from_incognito) { 131 restrict_to_profile = profile; 132 } 133 } 134 135 scoped_ptr<base::ListValue> args_copy(args->DeepCopy()); 136 scoped_ptr<Event> event(new Event(event_name, args_copy.Pass())); 137 event->restrict_to_browser_context = restrict_to_profile; 138 router->DispatchEventToExtension(extension_id, event.Pass()); 139 } 140 } 141} 142 143} // namespace preference_helpers 144} // namespace extensions 145