• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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