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
20 namespace extensions {
21 namespace preference_helpers {
22
23 namespace {
24
25 const char kIncognitoPersistent[] = "incognito_persistent";
26 const char kIncognitoSessionOnly[] = "incognito_session_only";
27 const char kRegular[] = "regular";
28 const char kRegularOnly[] = "regular_only";
29
30 const char kLevelOfControlKey[] = "levelOfControl";
31
32 const char kNotControllable[] = "not_controllable";
33 const char kControlledByOtherExtensions[] = "controlled_by_other_extensions";
34 const char kControllableByThisExtension[] = "controllable_by_this_extension";
35 const char kControlledByThisExtension[] = "controlled_by_this_extension";
36
37 } // namespace
38
StringToScope(const std::string & s,ExtensionPrefsScope * scope)39 bool 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
GetLevelOfControl(Profile * profile,const std::string & extension_id,const std::string & browser_pref,bool incognito)54 const 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
DispatchEventToExtensions(Profile * profile,const std::string & event_name,base::ListValue * args,APIPermission::ID permission,bool incognito,const std::string & browser_pref)86 void 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