// 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();
}
