external_policy_loader.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/external_policy_loader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/pref_service.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check an extension ID and an URL to be syntactically correct.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckExtension(const std::string& id, const std::string& update_url) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(update_url);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url.is_valid()) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Policy specifies invalid update URL for external "
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "extension: " << update_url;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Extension::IdIsValid(id)) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Policy specifies invalid ID for external "
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "extension: " << id;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExternalPolicyLoader::ExternalPolicyLoader(Profile* profile)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_change_registrar_.Init(profile_->GetPrefs());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(this,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              chrome::NOTIFICATION_PROFILE_DESTROYED,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              content::Source<Profile>(profile_));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalPolicyLoader::StartLoading() {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ListValue* forcelist =
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* result = new DictionaryValue();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (forcelist != NULL) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string extension_desc;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ListValue::const_iterator it = forcelist->begin();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != forcelist->end(); ++it) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!(*it)->GetAsString(&extension_desc)) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Failed to read forcelist string.";
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Each string item of the list has the following form:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // extension_id_code;extension_update_url
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The update URL might also contain semicolons.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t pos = extension_desc.find(';');
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string id = extension_desc.substr(0, pos);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string update_url = extension_desc.substr(pos+1);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (CheckExtension(id, update_url)) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->SetString(id + ".external_update_url", update_url);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs_.reset(result);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadFinished();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalPolicyLoader::Observe(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (profile_ == NULL) return;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type == chrome::NOTIFICATION_PROFILE_DESTROYED) <<
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Unexpected notification type.";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content::Source<Profile>(source).ptr() == profile_) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_registrar_.RemoveAll();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_change_registrar_.RemoveAll();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_ = NULL;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalPolicyLoader::OnPreferenceChanged(PrefServiceBase* service,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const std::string& pref_name) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service == profile_->GetPrefs()) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(std::string(prefs::kExtensionInstallForceList), pref_name);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartLoading();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
100