// 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/installer/util/channel_info.h"

#include "base/logging.h"
#include "base/win/registry.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/util_constants.h"

using base::win::RegKey;

namespace {

const wchar_t kModChrome[] = L"-chrome";
const wchar_t kModChromeFrame[] = L"-chromeframe";
// TODO(huangs): Remove by M27.
const wchar_t kModAppHostDeprecated[] = L"-apphost";
const wchar_t kModAppLauncher[] = L"-applauncher";
const wchar_t kModMultiInstall[] = L"-multi";
const wchar_t kModReadyMode[] = L"-readymode";
const wchar_t kModStage[] = L"-stage:";
const wchar_t kSfxFull[] = L"-full";
const wchar_t kSfxMigrating[] = L"-migrating";
const wchar_t kSfxMultiFail[] = L"-multifail";

const wchar_t* const kChannels[] = {
  installer::kChromeChannelBeta,
  installer::kChromeChannelDev,
  installer::kChromeChannelStableExplicit
};

const wchar_t* const kModifiers[] = {
  kModStage,
  kModMultiInstall,
  kModChrome,
  kModChromeFrame,
  kModAppHostDeprecated,  // TODO(huangs): Remove by M27.
  kModAppLauncher,
  kModReadyMode,
  kSfxMultiFail,
  kSfxMigrating,
  kSfxFull,
};

enum ModifierIndex {
  MOD_STAGE,
  MOD_MULTI_INSTALL,
  MOD_CHROME,
  MOD_CHROME_FRAME,
  MOD_APP_HOST_DEPRECATED,  // TODO(huangs): Remove by M27.
  MOD_APP_LAUNCHER,
  MOD_READY_MODE,
  SFX_MULTI_FAIL,
  SFX_MIGRATING,
  SFX_FULL,
  NUM_MODIFIERS
};

COMPILE_ASSERT(NUM_MODIFIERS == arraysize(kModifiers),
    kModifiers_disagrees_with_ModifierIndex_comma_they_must_match_bang);

// Returns true if the modifier is found, in which case |position| holds the
// location at which the modifier was found.  The number of characters in the
// modifier is returned in |length|, if non-NULL.
bool FindModifier(ModifierIndex index,
                  const std::wstring& ap_value,
                  std::wstring::size_type* position,
                  std::wstring::size_type* length) {
  DCHECK(position != NULL);
  std::wstring::size_type mod_position = std::wstring::npos;
  std::wstring::size_type mod_length =
      std::wstring::traits_type::length(kModifiers[index]);
  const bool mod_takes_arg = (kModifiers[index][mod_length - 1] == L':');
  std::wstring::size_type pos = 0;
  do {
    mod_position = ap_value.find(kModifiers[index], pos, mod_length);
    if (mod_position == std::wstring::npos)
      return false;  // Modifier not found.
    pos = mod_position + mod_length;
    // Modifiers that take an argument gobble up to the next separator or to the
    // end.
    if (mod_takes_arg) {
      pos = ap_value.find(L'-', pos);
      if (pos == std::wstring::npos)
        pos = ap_value.size();
      break;
    }
    // Regular modifiers must be followed by '-' or the end of the string.
  } while (pos != ap_value.size() && ap_value[pos] != L'-');
  DCHECK_NE(mod_position, std::wstring::npos);
  *position = mod_position;
  if (length != NULL)
    *length = pos - mod_position;
  return true;
}

bool HasModifier(ModifierIndex index, const std::wstring& ap_value) {
  DCHECK(index >= 0 && index < NUM_MODIFIERS);
  std::wstring::size_type position;
  return FindModifier(index, ap_value, &position, NULL);
}

std::wstring::size_type FindInsertionPoint(ModifierIndex index,
                                           const std::wstring& ap_value) {
  // Return the location of the next modifier.
  std::wstring::size_type result;

  for (int scan = index + 1; scan < NUM_MODIFIERS; ++scan) {
    if (FindModifier(static_cast<ModifierIndex>(scan), ap_value, &result, NULL))
      return result;
  }

  return ap_value.size();
}

// Returns true if |ap_value| is modified.
bool SetModifier(ModifierIndex index, bool set, std::wstring* ap_value) {
  DCHECK(index >= 0 && index < NUM_MODIFIERS);
  DCHECK(ap_value);
  std::wstring::size_type position;
  std::wstring::size_type length;
  bool have_modifier = FindModifier(index, *ap_value, &position, &length);
  if (set) {
    if (!have_modifier) {
      ap_value->insert(FindInsertionPoint(index, *ap_value), kModifiers[index]);
      return true;
    }
  } else {
    if (have_modifier) {
      ap_value->erase(position, length);
      return true;
    }
  }
  return false;
}

}  // namespace

namespace installer {

bool ChannelInfo::Initialize(const RegKey& key) {
  LONG result = key.ReadValue(google_update::kRegApField, &value_);
  return result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND ||
         result == ERROR_INVALID_HANDLE;
}

bool ChannelInfo::Write(RegKey* key) const {
  DCHECK(key);
  // Google Update deletes the value when it is empty, so we may as well, too.
  LONG result = value_.empty() ?
      key->DeleteValue(google_update::kRegApField) :
      key->WriteValue(google_update::kRegApField, value_.c_str());
  if (result != ERROR_SUCCESS) {
    LOG(ERROR) << "Failed writing channel info; result: " << result;
    return false;
  }
  return true;
}

bool ChannelInfo::GetChannelName(std::wstring* channel_name) const {
  DCHECK(channel_name);
  if (value_.empty()) {
    channel_name->erase();
    return true;
  } else {
    for (const wchar_t* const* scan = &kChannels[0],
             *const* end = &kChannels[arraysize(kChannels)]; scan != end;
         ++scan) {
      if (value_.find(*scan) != std::wstring::npos) {
        // Report channels with "stable" in them as stable (empty string).
        if (*scan == installer::kChromeChannelStableExplicit)
          channel_name->erase();
        else
          channel_name->assign(*scan);
        return true;
      }
    }
    // There may be modifiers present.  Strip them off and see if we're left
    // with the empty string (stable channel).
    std::wstring tmp_value = value_;
    for (int i = 0; i != NUM_MODIFIERS; ++i) {
      SetModifier(static_cast<ModifierIndex>(i), false, &tmp_value);
    }
    if (tmp_value.empty()) {
      channel_name->erase();
      return true;
    }
  }

  return false;
}

bool ChannelInfo::IsChrome() const {
  return HasModifier(MOD_CHROME, value_);
}

bool ChannelInfo::SetChrome(bool value) {
  return SetModifier(MOD_CHROME, value, &value_);
}

bool ChannelInfo::IsChromeFrame() const {
  return HasModifier(MOD_CHROME_FRAME, value_);
}

bool ChannelInfo::SetChromeFrame(bool value) {
  return SetModifier(MOD_CHROME_FRAME, value, &value_);
}

bool ChannelInfo::IsAppLauncher() const {
  return HasModifier(MOD_APP_LAUNCHER, value_);
}

bool ChannelInfo::SetAppLauncher(bool value) {
  // Unconditionally remove -apphost since it has been deprecated.
  bool changed_app_host = SetModifier(MOD_APP_HOST_DEPRECATED, false, &value_);
  bool changed_app_launcher = SetModifier(MOD_APP_LAUNCHER, value, &value_);
  return changed_app_host || changed_app_launcher;
}

bool ChannelInfo::IsMultiInstall() const {
  return HasModifier(MOD_MULTI_INSTALL, value_);
}

bool ChannelInfo::SetMultiInstall(bool value) {
  return SetModifier(MOD_MULTI_INSTALL, value, &value_);
}

bool ChannelInfo::IsReadyMode() const {
  return HasModifier(MOD_READY_MODE, value_);
}

bool ChannelInfo::SetReadyMode(bool value) {
  return SetModifier(MOD_READY_MODE, value, &value_);
}

bool ChannelInfo::SetStage(const wchar_t* stage) {
  std::wstring::size_type position;
  std::wstring::size_type length;
  bool have_modifier = FindModifier(MOD_STAGE, value_, &position, &length);
  if (stage != NULL && *stage != L'\0') {
    std::wstring stage_str(kModStage);
    stage_str.append(stage);
    if (!have_modifier) {
      value_.insert(FindInsertionPoint(MOD_STAGE, value_), stage_str);
      return true;
    }
    if (value_.compare(position, length, stage_str) != 0) {
      value_.replace(position, length, stage_str);
      return true;
    }
  } else {
    if (have_modifier) {
      value_.erase(position, length);
      return true;
    }
  }
  return false;
}

std::wstring ChannelInfo::GetStage() const {
  std::wstring::size_type position;
  std::wstring::size_type length;

  if (FindModifier(MOD_STAGE, value_, &position, &length)) {
    // Return the portion after the prefix.
    std::wstring::size_type pfx_length =
        std::wstring::traits_type::length(kModStage);
    DCHECK_LE(pfx_length, length);
    return value_.substr(position + pfx_length, length - pfx_length);
  }
  return std::wstring();
}

bool ChannelInfo::HasFullSuffix() const {
  return HasModifier(SFX_FULL, value_);
}

bool ChannelInfo::SetFullSuffix(bool value) {
  return SetModifier(SFX_FULL, value, &value_);
}

bool ChannelInfo::HasMultiFailSuffix() const {
  return HasModifier(SFX_MULTI_FAIL, value_);
}

bool ChannelInfo::SetMultiFailSuffix(bool value) {
  return SetModifier(SFX_MULTI_FAIL, value, &value_);
}

bool ChannelInfo::SetMigratingSuffix(bool value) {
  return SetModifier(SFX_MIGRATING, value, &value_);
}

bool ChannelInfo::HasMigratingSuffix() const {
  return HasModifier(SFX_MIGRATING, value_);
}

bool ChannelInfo::RemoveAllModifiersAndSuffixes() {
  bool modified = false;

  for (int scan = 0; scan < NUM_MODIFIERS; ++scan) {
    ModifierIndex index = static_cast<ModifierIndex>(scan);
    modified = SetModifier(index, false, &value_) || modified;
  }

  return modified;
}

}  // namespace installer
