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/installer/util/channel_info.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_constants.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/util_constants.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::RegKey;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kModChrome[] = L"-chrome";
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kModChromeFrame[] = L"-chromeframe";
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(huangs): Remove by M27.
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t kModAppHostDeprecated[] = L"-apphost";
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kModAppLauncher[] = L"-applauncher";
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kModMultiInstall[] = L"-multi";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kModReadyMode[] = L"-readymode";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kModStage[] = L"-stage:";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSfxFull[] = L"-full";
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const wchar_t kSfxMigrating[] = L"-migrating";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSfxMultiFail[] = L"-multifail";
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t* const kChannels[] = {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  installer::kChromeChannelBeta,
30f7a18f9da2728b9a347823d741465e09fa665da8Torne (Richard Coles)  installer::kChromeChannelDev,
31f7a18f9da2728b9a347823d741465e09fa665da8Torne (Richard Coles)  installer::kChromeChannelStableExplicit
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t* const kModifiers[] = {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kModStage,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kModMultiInstall,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kModChrome,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kModChromeFrame,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kModAppHostDeprecated,  // TODO(huangs): Remove by M27.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kModAppLauncher,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kModReadyMode,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kSfxMultiFail,
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  kSfxMigrating,
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  kSfxFull,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ModifierIndex {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOD_STAGE,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOD_MULTI_INSTALL,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOD_CHROME,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOD_CHROME_FRAME,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOD_APP_HOST_DEPRECATED,  // TODO(huangs): Remove by M27.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOD_APP_LAUNCHER,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOD_READY_MODE,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SFX_MULTI_FAIL,
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SFX_MIGRATING,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SFX_FULL,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NUM_MODIFIERS
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(NUM_MODIFIERS == arraysize(kModifiers),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kModifiers_disagrees_with_ModifierIndex_comma_they_must_match_bang);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the modifier is found, in which case |position| holds the
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// location at which the modifier was found.  The number of characters in the
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modifier is returned in |length|, if non-NULL.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindModifier(ModifierIndex index,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const std::wstring& ap_value,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  std::wstring::size_type* position,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  std::wstring::size_type* length) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(position != NULL);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type mod_position = std::wstring::npos;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type mod_length =
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::wstring::traits_type::length(kModifiers[index]);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool mod_takes_arg = (kModifiers[index][mod_length - 1] == L':');
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type pos = 0;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mod_position = ap_value.find(kModifiers[index], pos, mod_length);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mod_position == std::wstring::npos)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Modifier not found.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos = mod_position + mod_length;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Modifiers that take an argument gobble up to the next separator or to the
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // end.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mod_takes_arg) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos = ap_value.find(L'-', pos);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pos == std::wstring::npos)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pos = ap_value.size();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Regular modifiers must be followed by '-' or the end of the string.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (pos != ap_value.size() && ap_value[pos] != L'-');
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(mod_position, std::wstring::npos);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *position = mod_position;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length != NULL)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *length = pos - mod_position;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasModifier(ModifierIndex index, const std::wstring& ap_value) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index < NUM_MODIFIERS);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type position;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindModifier(index, ap_value, &position, NULL);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring::size_type FindInsertionPoint(ModifierIndex index,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const std::wstring& ap_value) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return the location of the next modifier.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type result;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int scan = index + 1; scan < NUM_MODIFIERS; ++scan) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FindModifier(static_cast<ModifierIndex>(scan), ap_value, &result, NULL))
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ap_value.size();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |ap_value| is modified.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetModifier(ModifierIndex index, bool set, std::wstring* ap_value) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index < NUM_MODIFIERS);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ap_value);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type position;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type length;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool have_modifier = FindModifier(index, *ap_value, &position, &length);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (set) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!have_modifier) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap_value->insert(FindInsertionPoint(index, *ap_value), kModifiers[index]);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (have_modifier) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap_value->erase(position, length);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace installer {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::Initialize(const RegKey& key) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG result = key.ReadValue(google_update::kRegApField, &value_);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND ||
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         result == ERROR_INVALID_HANDLE;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::Write(RegKey* key) const {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(key);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Google Update deletes the value when it is empty, so we may as well, too.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG result = value_.empty() ?
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->DeleteValue(google_update::kRegApField) :
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->WriteValue(google_update::kRegApField, value_.c_str());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != ERROR_SUCCESS) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed writing channel info; result: " << result;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::GetChannelName(std::wstring* channel_name) const {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(channel_name);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value_.empty()) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_name->erase();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (const wchar_t* const* scan = &kChannels[0],
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             *const* end = &kChannels[arraysize(kChannels)]; scan != end;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++scan) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value_.find(*scan) != std::wstring::npos) {
172f7a18f9da2728b9a347823d741465e09fa665da8Torne (Richard Coles)        // Report channels with "stable" in them as stable (empty string).
173f7a18f9da2728b9a347823d741465e09fa665da8Torne (Richard Coles)        if (*scan == installer::kChromeChannelStableExplicit)
174f7a18f9da2728b9a347823d741465e09fa665da8Torne (Richard Coles)          channel_name->erase();
175f7a18f9da2728b9a347823d741465e09fa665da8Torne (Richard Coles)        else
176f7a18f9da2728b9a347823d741465e09fa665da8Torne (Richard Coles)          channel_name->assign(*scan);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There may be modifiers present.  Strip them off and see if we're left
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with the empty string (stable channel).
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring tmp_value = value_;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i != NUM_MODIFIERS; ++i) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetModifier(static_cast<ModifierIndex>(i), false, &tmp_value);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tmp_value.empty()) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_name->erase();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::IsChrome() const {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasModifier(MOD_CHROME, value_);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetChrome(bool value) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SetModifier(MOD_CHROME, value, &value_);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::IsChromeFrame() const {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasModifier(MOD_CHROME_FRAME, value_);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetChromeFrame(bool value) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SetModifier(MOD_CHROME_FRAME, value, &value_);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::IsAppLauncher() const {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasModifier(MOD_APP_LAUNCHER, value_);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetAppLauncher(bool value) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Unconditionally remove -apphost since it has been deprecated.
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool changed_app_host = SetModifier(MOD_APP_HOST_DEPRECATED, false, &value_);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool changed_app_launcher = SetModifier(MOD_APP_LAUNCHER, value, &value_);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return changed_app_host || changed_app_launcher;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::IsMultiInstall() const {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasModifier(MOD_MULTI_INSTALL, value_);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetMultiInstall(bool value) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SetModifier(MOD_MULTI_INSTALL, value, &value_);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::IsReadyMode() const {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasModifier(MOD_READY_MODE, value_);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetReadyMode(bool value) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SetModifier(MOD_READY_MODE, value, &value_);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetStage(const wchar_t* stage) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type position;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type length;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool have_modifier = FindModifier(MOD_STAGE, value_, &position, &length);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stage != NULL && *stage != L'\0') {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring stage_str(kModStage);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stage_str.append(stage);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!have_modifier) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_.insert(FindInsertionPoint(MOD_STAGE, value_), stage_str);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value_.compare(position, length, stage_str) != 0) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_.replace(position, length, stage_str);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (have_modifier) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_.erase(position, length);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring ChannelInfo::GetStage() const {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type position;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type length;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FindModifier(MOD_STAGE, value_, &position, &length)) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Return the portion after the prefix.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring::size_type pfx_length =
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::wstring::traits_type::length(kModStage);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LE(pfx_length, length);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value_.substr(position + pfx_length, length - pfx_length);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::wstring();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::HasFullSuffix() const {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasModifier(SFX_FULL, value_);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetFullSuffix(bool value) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SetModifier(SFX_FULL, value, &value_);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::HasMultiFailSuffix() const {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasModifier(SFX_MULTI_FAIL, value_);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChannelInfo::SetMultiFailSuffix(bool value) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SetModifier(SFX_MULTI_FAIL, value, &value_);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool ChannelInfo::SetMigratingSuffix(bool value) {
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return SetModifier(SFX_MIGRATING, value, &value_);
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool ChannelInfo::HasMigratingSuffix() const {
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return HasModifier(SFX_MIGRATING, value_);
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
300558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochbool ChannelInfo::RemoveAllModifiersAndSuffixes() {
301558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  bool modified = false;
302558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
303558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (int scan = 0; scan < NUM_MODIFIERS; ++scan) {
304558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    ModifierIndex index = static_cast<ModifierIndex>(scan);
305558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    modified = SetModifier(index, false, &value_) || modified;
306558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
307558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
308558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return modified;
309558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
310558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace installer
312