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