Home | History | Annotate | Download | only in preference
      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 
     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 
     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 
     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