// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome_frame/policy_settings.h"
#include <algorithm>
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "chrome_frame/utils.h"
#include "policy/policy_constants.h"
namespace {
// This array specifies the order in which registry keys are tested. Do not
// change this unless the decision is made product-wide (i.e., in Chrome's
// configuration policy provider).
const HKEY kRootKeys[] = {
HKEY_LOCAL_MACHINE,
HKEY_CURRENT_USER
};
} // namespace
PolicySettings::RendererForUrl PolicySettings::GetRendererForUrl(
const wchar_t* url) {
RendererForUrl renderer = default_renderer_;
std::vector<std::wstring>::const_iterator it;
for (it = renderer_exclusion_list_.begin();
it != renderer_exclusion_list_.end(); ++it) {
if (MatchPattern(url, (*it))) {
renderer = (renderer == RENDER_IN_HOST) ?
RENDER_IN_CHROME_FRAME : RENDER_IN_HOST;
break;
}
}
return renderer;
}
PolicySettings::RendererForUrl PolicySettings::GetRendererForContentType(
const wchar_t* content_type) {
DCHECK(content_type);
RendererForUrl renderer = RENDERER_NOT_SPECIFIED;
std::vector<std::wstring>::const_iterator it;
for (it = content_type_list_.begin();
it != content_type_list_.end(); ++it) {
if (lstrcmpiW(content_type, (*it).c_str()) == 0) {
renderer = RENDER_IN_CHROME_FRAME;
break;
}
}
return renderer;
}
const CommandLine& PolicySettings::AdditionalLaunchParameters() const {
return additional_launch_parameters_;
}
// static
void PolicySettings::ReadUrlSettings(
RendererForUrl* default_renderer,
std::vector<std::wstring>* renderer_exclusion_list) {
DCHECK(default_renderer);
DCHECK(renderer_exclusion_list);
*default_renderer = RENDERER_NOT_SPECIFIED;
renderer_exclusion_list->clear();
base::win::RegKey config_key;
DWORD value = RENDERER_NOT_SPECIFIED;
std::wstring settings_value(
ASCIIToWide(policy::key::kChromeFrameRendererSettings));
for (int i = 0; i < arraysize(kRootKeys); ++i) {
if ((config_key.Open(kRootKeys[i], policy::kRegistryChromePolicyKey,
KEY_READ) == ERROR_SUCCESS) &&
(config_key.ReadValueDW(settings_value.c_str(),
&value) == ERROR_SUCCESS)) {
break;
}
}
DCHECK(value == RENDERER_NOT_SPECIFIED ||
value == RENDER_IN_HOST ||
value == RENDER_IN_CHROME_FRAME)
<< "invalid default renderer setting: " << value;
if (value != RENDER_IN_HOST && value != RENDER_IN_CHROME_FRAME) {
DVLOG(1) << "default renderer not specified via policy";
} else {
*default_renderer = static_cast<RendererForUrl>(value);
const char* exclusion_list_name = (*default_renderer == RENDER_IN_HOST) ?
policy::key::kRenderInChromeFrameList :
policy::key::kRenderInHostList;
EnumerateKeyValues(config_key.Handle(),
ASCIIToWide(exclusion_list_name).c_str(), renderer_exclusion_list);
DVLOG(1) << "Default renderer as specified via policy: "
<< *default_renderer
<< " exclusion list size: " << renderer_exclusion_list->size();
}
}
// static
void PolicySettings::ReadMetadataCheckSettings(
SkipMetadataCheck* skip_metadata_check) {
DCHECK(skip_metadata_check);
*skip_metadata_check = SKIP_METADATA_CHECK_NOT_SPECIFIED;
base::win::RegKey config_key;
DWORD value = SKIP_METADATA_CHECK_NOT_SPECIFIED;
string16 settings_value(
ASCIIToWide(policy::key::kSkipMetadataCheck));
for (int i = 0; i < arraysize(kRootKeys); ++i) {
if ((config_key.Open(kRootKeys[i], policy::kRegistryChromePolicyKey,
KEY_READ) == ERROR_SUCCESS) &&
(config_key.ReadValueDW(settings_value.c_str(),
&value) == ERROR_SUCCESS)) {
break;
}
}
DCHECK(value == SKIP_METADATA_CHECK_NOT_SPECIFIED ||
value == SKIP_METADATA_CHECK_NO ||
value == SKIP_METADATA_CHECK_YES)
<< "invalid skip metadata check setting: " << value;
if (value != SKIP_METADATA_CHECK_NO && value != SKIP_METADATA_CHECK_YES) {
DVLOG(1) << "metadata check not specified via policy";
} else {
*skip_metadata_check = static_cast<SkipMetadataCheck>(value);
DVLOG(1) << "SkipMetadata check as specified via policy: "
<< *skip_metadata_check;
}
}
// static
void PolicySettings::ReadContentTypeSetting(
std::vector<std::wstring>* content_type_list) {
DCHECK(content_type_list);
std::wstring sub_key(policy::kRegistryChromePolicyKey);
sub_key += L"\\";
sub_key += ASCIIToWide(policy::key::kChromeFrameContentTypes);
content_type_list->clear();
for (int i = 0; i < arraysize(kRootKeys) && content_type_list->empty();
++i) {
EnumerateKeyValues(kRootKeys[i], sub_key.c_str(), content_type_list);
}
}
// static
void PolicySettings::ReadStringSetting(const char* value_name,
std::wstring* value) {
DCHECK(value);
value->clear();
base::win::RegKey config_key;
std::wstring value_name_str(ASCIIToWide(value_name));
for (int i = 0; i < arraysize(kRootKeys); ++i) {
if ((config_key.Open(kRootKeys[i], policy::kRegistryChromePolicyKey,
KEY_READ) == ERROR_SUCCESS) &&
(config_key.ReadValue(value_name_str.c_str(),
value) == ERROR_SUCCESS)) {
break;
}
}
}
// static
void PolicySettings::ReadBoolSetting(const char* value_name, bool* value) {
DCHECK(value);
base::win::RegKey config_key;
string16 value_name_str(ASCIIToWide(value_name));
DWORD dword_value = 0;
for (int i = 0; i < arraysize(kRootKeys); ++i) {
if ((config_key.Open(kRootKeys[i], policy::kRegistryChromePolicyKey,
KEY_QUERY_VALUE) == ERROR_SUCCESS) &&
(config_key.ReadValueDW(value_name_str.c_str(),
&dword_value) == ERROR_SUCCESS)) {
*value = (dword_value != 0);
break;
}
}
}
void PolicySettings::RefreshFromRegistry() {
RendererForUrl default_renderer;
SkipMetadataCheck skip_metadata_check;
std::vector<std::wstring> renderer_exclusion_list;
std::vector<std::wstring> content_type_list;
std::wstring application_locale;
CommandLine additional_launch_parameters(CommandLine::NO_PROGRAM);
std::wstring additional_parameters_str;
bool suppress_turndown_prompt = false;
// Read the latest settings from the registry
ReadUrlSettings(&default_renderer, &renderer_exclusion_list);
ReadMetadataCheckSettings(&skip_metadata_check);
ReadContentTypeSetting(&content_type_list);
ReadStringSetting(policy::key::kApplicationLocaleValue, &application_locale);
ReadStringSetting(policy::key::kAdditionalLaunchParameters,
&additional_parameters_str);
if (!additional_parameters_str.empty()) {
additional_parameters_str.insert(0, L"fake.exe ");
additional_launch_parameters.ParseFromString(additional_parameters_str);
}
ReadBoolSetting(policy::key::kSuppressChromeFrameTurndownPrompt,
&suppress_turndown_prompt);
// Nofail swap in the new values. (Note: this is all that need be protected
// under a mutex if/when this becomes thread safe.)
using std::swap;
swap(default_renderer_, default_renderer);
swap(skip_metadata_check_, skip_metadata_check);
swap(renderer_exclusion_list_, renderer_exclusion_list);
swap(content_type_list_, content_type_list);
swap(application_locale_, application_locale);
swap(additional_launch_parameters_, additional_launch_parameters);
swap(suppress_turndown_prompt_, suppress_turndown_prompt);
}
// static
PolicySettings* PolicySettings::GetInstance() {
return Singleton<PolicySettings>::get();
}