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_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