Codebase list mozc / upstream/1.15.1857.102 config / config_handler.cc
upstream/1.15.1857.102

Tree @upstream/1.15.1857.102 (Download .tar.gz)

config_handler.cc @upstream/1.15.1857.102

886170b
22ec38e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70ff280
06bbe03
22ec38e
16a92a0
 
22ec38e
70ff280
 
16a92a0
 
22ec38e
16a92a0
70ff280
22ec38e
06bbe03
22ec38e
 
 
 
 
30f5e36
22ec38e
16a92a0
 
 
 
 
22ec38e
 
 
 
 
 
30f5e36
 
 
 
 
 
 
 
 
 
 
 
 
22ec38e
 
 
 
 
70ff280
22ec38e
 
 
 
 
 
06bbe03
 
22ec38e
06bbe03
22ec38e
 
e6050bb
22ec38e
 
 
 
 
06bbe03
22ec38e
 
16a92a0
 
06bbe03
16a92a0
22ec38e
 
 
 
 
 
 
06bbe03
22ec38e
 
 
 
06bbe03
 
 
 
 
 
 
 
 
 
 
22ec38e
 
 
 
 
06bbe03
22ec38e
 
 
06bbe03
22ec38e
06bbe03
 
22ec38e
 
 
06bbe03
22ec38e
 
06bbe03
979ca01
06bbe03
979ca01
06bbe03
979ca01
22ec38e
 
30f5e36
 
 
16a92a0
30f5e36
16a92a0
 
 
 
06bbe03
 
22ec38e
 
 
06bbe03
 
 
 
 
22ec38e
 
 
 
 
 
 
951daf5
22ec38e
06bbe03
951daf5
 
 
 
 
06bbe03
22ec38e
 
 
 
06bbe03
 
 
 
 
 
 
 
 
 
 
 
 
 
22ec38e
 
 
0931069
22ec38e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
06bbe03
22ec38e
e6050bb
 
30f5e36
 
 
16a92a0
30f5e36
 
 
 
 
e6050bb
22ec38e
 
 
 
 
 
30f5e36
22ec38e
 
 
 
06bbe03
 
 
 
30f5e36
06bbe03
 
 
 
22ec38e
 
 
 
30f5e36
06bbe03
 
 
 
22ec38e
 
979ca01
22ec38e
979ca01
 
 
22ec38e
16a92a0
 
22ec38e
16a92a0
 
 
 
 
22ec38e
16a92a0
 
22ec38e
16a92a0
 
 
 
 
 
 
 
06bbe03
30f5e36
 
 
16a92a0
30f5e36
16a92a0
 
22ec38e
 
 
 
 
 
 
 
 
 
 
e6050bb
 
 
 
22ec38e
 
06bbe03
 
 
 
16a92a0
22ec38e
 
70ff280
 
// Copyright 2010-2014, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Handler of mozc configuration.

#include "config/config_handler.h"

#include <algorithm>

#include "base/config_file_stream.h"
#include "base/logging.h"
#include "base/number_util.h"
#include "base/port.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
#include "base/system_util.h"
#include "base/util.h"
#include "base/version.h"
#include "config/config.pb.h"

namespace mozc {
namespace config {
namespace {

const char kFileNamePrefix[] = "user://config";

void AddCharacterFormRule(const char *group,
                          const Config::CharacterForm preedit_form,
                          const Config::CharacterForm conversion_form,
                          Config *config) {
  Config::CharacterFormRule *rule =
      config->add_character_form_rules();
  rule->set_group(group);
  rule->set_preedit_character_form(preedit_form);
  rule->set_conversion_character_form(conversion_form);
}

bool GetPlatformSpecificDefaultEmojiSetting() {
  // Disable Unicode emoji conversion by default on specific platforms.
  bool use_emoji_conversion_default = true;
#if defined(OS_WIN)
  if (!SystemUtil::IsWindows8OrLater()) {
    use_emoji_conversion_default = false;
  }
#elif defined(OS_ANDROID)
  use_emoji_conversion_default = false;
#endif
  return use_emoji_conversion_default;
}

class ConfigHandlerImpl {
 public:
  ConfigHandlerImpl() {
    // <user_profile>/config1.db
    filename_ = kFileNamePrefix;
    filename_ += NumberUtil::SimpleItoa(CONFIG_VERSION);
    filename_ += ".db";
    Reload();
  }
  virtual ~ConfigHandlerImpl() {}
  const Config &GetConfig() const;
  bool GetConfig(Config *config) const;
  const Config &GetStoredConfig() const;
  bool GetStoredConfig(Config *config) const;
  bool SetConfig(const Config &config);
  void SetImposedConfig(const Config &config);
  bool Reload();
  void SetConfigFileName(const string &filename);
  string GetConfigFileName();

 private:
  // copy config to config_ and do some
  // platform dependent hooks/rewrites
  bool SetConfigInternal(const Config &config);
  void UpdateMergedConfig();

  string filename_;
  Config stored_config_;
  Config imposed_config_;
  // equals to config_.MergeFrom(imposed_config_)
  Config merged_config_;
};

ConfigHandlerImpl *GetConfigHandlerImpl() {
  return Singleton<ConfigHandlerImpl>::get();
}

const Config &ConfigHandlerImpl::GetConfig() const {
  return merged_config_;
}

// return current Config
bool ConfigHandlerImpl::GetConfig(Config *config) const {
  config->CopyFrom(merged_config_);
  return true;
}

const Config &ConfigHandlerImpl::GetStoredConfig() const {
  return stored_config_;
}

// return stored Config
bool ConfigHandlerImpl::GetStoredConfig(Config *config) const {
  config->CopyFrom(stored_config_);
  return true;
}

// set config and rewirte internal data
bool ConfigHandlerImpl::SetConfigInternal(const Config &config) {
  stored_config_.CopyFrom(config);

#ifdef NO_LOGGING
  // Delete the optional field from the config.
  stored_config_.clear_verbose_level();
  // Fall back if the default value is not the expected value.
  if (stored_config_.verbose_level() != 0) {
    stored_config_.set_verbose_level(0);
  }
#endif

  Logging::SetConfigVerboseLevel(stored_config_.verbose_level());

  // Initialize platform specific configuration.
  if (stored_config_.session_keymap() == Config::NONE) {
#ifdef OS_MACOSX
    stored_config_.set_session_keymap(Config::KOTOERI);
#else  // OS_MACOSX
    stored_config_.set_session_keymap(Config::MSIME);
#endif  // OS_MACOSX
  }

#if defined(OS_ANDROID) && defined(CHANNEL_DEV)
  stored_config_.mutable_general_config()->set_upload_usage_stats(true);
#endif  // CHANNEL_DEV && OS_ANDROID

  if (GetPlatformSpecificDefaultEmojiSetting() &&
      !stored_config_.has_use_emoji_conversion()) {
    stored_config_.set_use_emoji_conversion(true);
  }

  UpdateMergedConfig();

  return true;
}

void ConfigHandlerImpl::UpdateMergedConfig() {
  merged_config_.CopyFrom(stored_config_);
  merged_config_.MergeFrom(imposed_config_);
}

bool ConfigHandlerImpl::SetConfig(const Config &config) {
  Config output_config;
  output_config.CopyFrom(config);

  ConfigHandler::SetMetaData(&output_config);

  VLOG(1) << "Setting new config: " << filename_;
  ConfigFileStream::AtomicUpdate(filename_, output_config.SerializeAsString());

#ifdef DEBUG
  string debug_content(
      "# This is a text-based config file for debugging.\n"
      "# Nothing happens when you edit this file manually.\n");
  debug_content += output_config.DebugString();
  ConfigFileStream::AtomicUpdate(filename_ + ".txt", debug_content);
#endif  // DEBUG

  return SetConfigInternal(output_config);
}

void ConfigHandlerImpl::SetImposedConfig(const Config &config) {
  VLOG(1) << "Setting new overriding config";
  imposed_config_.CopyFrom(config);

#ifdef DEBUG
  string debug_content(
      "# This is a text-based config file for debugging.\n"
      "# Nothing happens when you edit this file manually.\n");
  debug_content += config.DebugString();
  ConfigFileStream::AtomicUpdate(filename_ + ".overriding.txt", debug_content);
#endif  // DEBUG
  UpdateMergedConfig();
}

// Reload from file
bool ConfigHandlerImpl::Reload() {
  VLOG(1) << "Reloading config file: " << filename_;
  scoped_ptr<istream> is(ConfigFileStream::OpenReadBinary(filename_));
  Config input_proto;
  bool ret_code = true;

  if (is.get() == NULL) {
    LOG(ERROR) << filename_ << " is not found";
    ret_code = false;
  } else if (!input_proto.ParseFromIstream(is.get())) {
    LOG(ERROR) << filename_ << " is broken";
    input_proto.Clear();   // revert to default setting
    ret_code = false;
  }

  // we set default config when file is broekn
  ret_code |= SetConfigInternal(input_proto);

  return ret_code;
}

void ConfigHandlerImpl::SetConfigFileName(const string &filename) {
  VLOG(1) << "set new config file name: " << filename;
  filename_ = filename;
  Reload();
}

string ConfigHandlerImpl::GetConfigFileName() {
#ifdef __native_client__
  // Copies filename_ string here to prevent Copy-On-Write issues in
  // multi-thread environment.
  // See: http://stackoverflow.com/questions/1661154/c-stdstring-in-a-multi-threaded-program/
  // TODO(hsumita): Remove this hack if not necessary.
  return string(filename_.data(), filename_.size());
#else
  return filename_;
#endif  // __native_client__
}
}  // namespace

const Config &ConfigHandler::GetConfig() {
  return GetConfigHandlerImpl()->GetConfig();
}

// Returns current Config
bool ConfigHandler::GetConfig(Config *config) {
  return GetConfigHandlerImpl()->GetConfig(config);
}

const Config &ConfigHandler::GetStoredConfig() {
  return GetConfigHandlerImpl()->GetStoredConfig();
}

// Returns Stored Config
bool ConfigHandler::GetStoredConfig(Config *config) {
  return GetConfigHandlerImpl()->GetStoredConfig(config);
}

bool ConfigHandler::SetConfig(const Config &config) {
  return GetConfigHandlerImpl()->SetConfig(config);
}

// Sets overriding config
void ConfigHandler::SetImposedConfig(const Config &config) {
  GetConfigHandlerImpl()->SetImposedConfig(config);
}

void ConfigHandler::GetDefaultConfig(Config *config) {
  config->Clear();
#ifdef OS_MACOSX
  config->set_session_keymap(Config::KOTOERI);
#else  // OS_MACOSX
  config->set_session_keymap(Config::MSIME);
#endif  // OS_MACOSX

  const Config::CharacterForm kFullWidth = Config::FULL_WIDTH;
  const Config::CharacterForm kLastForm = Config::LAST_FORM;
  // "ア"
  AddCharacterFormRule("\xE3\x82\xA2", kFullWidth, kFullWidth, config);
  AddCharacterFormRule("A", kFullWidth, kLastForm, config);
  AddCharacterFormRule("0", kFullWidth, kLastForm, config);
  AddCharacterFormRule("(){}[]", kFullWidth, kLastForm, config);
  AddCharacterFormRule(".,", kFullWidth, kLastForm, config);
  // "。、",
  AddCharacterFormRule("\xE3\x80\x82\xE3\x80\x81", kFullWidth, kFullWidth,
                       config);
  // "・「」"
  AddCharacterFormRule("\xE3\x83\xBB\xE3\x80\x8C\xE3\x80\x8D",
                       kFullWidth, kFullWidth, config);
  AddCharacterFormRule("\"'", kFullWidth, kLastForm, config);
  AddCharacterFormRule(":;", kFullWidth, kLastForm, config);
  AddCharacterFormRule("#%&@$^_|`\\", kFullWidth, kLastForm, config);
  AddCharacterFormRule("~", kFullWidth, kLastForm, config);
  AddCharacterFormRule("<>=+-/*", kFullWidth, kLastForm, config);
  AddCharacterFormRule("?!", kFullWidth, kLastForm, config);

#if defined(OS_ANDROID) && defined(CHANNEL_DEV)
  config->mutable_general_config()->set_upload_usage_stats(true);
#endif  // OS_ANDROID && CHANNEL_DEV

  if (GetPlatformSpecificDefaultEmojiSetting()) {
    config->set_use_emoji_conversion(true);
  }
}

// Reload from file
bool ConfigHandler::Reload() {
  return GetConfigHandlerImpl()->Reload();
}

void ConfigHandler::SetConfigFileName(const string &filename) {
  GetConfigHandlerImpl()->SetConfigFileName(filename);
}

string ConfigHandler::GetConfigFileName() {
  return GetConfigHandlerImpl()->GetConfigFileName();
}

// static
void ConfigHandler::SetMetaData(Config *config) {
  GeneralConfig *general_config = config->mutable_general_config();
  general_config->set_config_version(CONFIG_VERSION);
  general_config->set_last_modified_time(Util::GetTime());
  general_config->set_last_modified_product_version(Version::GetMozcVersion());
  general_config->set_platform(SystemUtil::GetOSVersionString());
}

}  // namespace config
}  // namespace mozc