// Copyright (c) 2006-2008 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 #include "base/registry.h" #include "Resource.h" // This enum needs to be in sync with the strings below. enum Branch { UNKNOWN_BRANCH = 0, DEV_BRANCH, BETA_BRANCH, }; // This vector of strings needs to be in sync with the Branch enum above. static const wchar_t* const kBranchStrings[] = { L"", L"1.1-dev", L"1.1-beta" }; // This vector of strings needs to be in sync with the Branch enum above. static const wchar_t* const kBranchStringsReadable[] = { L"", L"Dev", L"Beta" }; // The root key for Google Update. static const HKEY kGoogleUpdateRoot = HKEY_CURRENT_USER; // The Google Update key to read to find out which branch you are on. static const wchar_t* const kGoogleUpdateKey = L"Software\\Google\\Update\\ClientState\\" L"{8A69D345-D564-463C-AFF1-A69D9E530F96}"; // The Google Update value that defines which branch you are on. static const wchar_t* const kBranchKey = L"ap"; // The suffix Google Update sometimes adds to the channel name (channel names // are defined in kBranchStrings), indicating that a full install is needed. We // strip this out (if present) for the purpose of determining which channel you // are on. static const wchar_t* const kChannelSuffix = L"-full"; // The icon to use. static HICON dlg_icon = NULL; void SetMainLabel(HWND dialog, Branch branch) { std::wstring main_label = L"You are currently on "; if (branch == DEV_BRANCH || branch == BETA_BRANCH) main_label += std::wstring(L"the ") + kBranchStringsReadable[branch] + std::wstring(L" channel"); else main_label += L"NO UPDATE CHANNEL"; main_label += L". Choose a different channel and click Update, " L"or click Close to stay on this channel."; SetWindowText(GetDlgItem(dialog, IDC_LABEL_MAIN), main_label.c_str()); } void OnInitDialog(HWND dialog) { SendMessage(dialog, WM_SETICON, (WPARAM) false, (LPARAM) dlg_icon); std::wstring branch_string; RegKey google_update(kGoogleUpdateRoot, kGoogleUpdateKey, KEY_READ); if (google_update.Valid() && !google_update.ReadValue(kBranchKey, &branch_string)) { // If the 'ap' value is missing, we create it, unless the key is missing. RegKey write_default(kGoogleUpdateRoot, kGoogleUpdateKey, KEY_WRITE); branch_string = kBranchStrings[BETA_BRANCH]; if (!write_default.WriteValue(kBranchKey, branch_string.c_str())) branch_string = L""; // Error, show disabled UI. } // We look for '1.1-beta' or '1.1-dev', but Google Update might have added // '-full' to the channel name, which we need to strip out to determine what // channel you are on. std::wstring suffix = kChannelSuffix; if (branch_string.length() > suffix.length()) { size_t index = branch_string.rfind(suffix); if (index != std::wstring::npos && index == branch_string.length() - suffix.length()) { branch_string = branch_string.substr(0, index); } } Branch branch = UNKNOWN_BRANCH; if (branch_string == kBranchStrings[DEV_BRANCH]) { branch = DEV_BRANCH; } else if (branch_string == kBranchStrings[BETA_BRANCH]) { branch = BETA_BRANCH; } else { // Hide the controls we can't use. EnableWindow(GetDlgItem(dialog, IDOK), false); EnableWindow(GetDlgItem(dialog, IDC_STABLE), false); EnableWindow(GetDlgItem(dialog, IDC_CUTTING_EDGE), false); MessageBox(dialog, L"KEY NOT FOUND\n\nChrome is not installed, or is not " L"using GoogleUpdate for updates.", L"Chrome Channel Changer", MB_ICONEXCLAMATION | MB_OK); } SetMainLabel(dialog, branch); CheckDlgButton(dialog, IDC_STABLE, branch == BETA_BRANCH ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(dialog, IDC_CUTTING_EDGE, branch == DEV_BRANCH ? BST_CHECKED : BST_UNCHECKED); } INT_PTR OnCtlColorStatic(HWND dialog, WPARAM wparam, LPARAM lparam) { HDC hdc = reinterpret_cast(wparam); HWND control_wnd = reinterpret_cast(lparam); if (GetDlgItem(dialog, IDC_STABLE) == control_wnd || GetDlgItem(dialog, IDC_CUTTING_EDGE) == control_wnd || GetDlgItem(dialog, IDC_LABEL_MAIN) == control_wnd || GetDlgItem(dialog, IDC_SECONDARY_LABEL) == control_wnd) { SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, RGB(0, 0, 0)); return reinterpret_cast(GetSysColorBrush(COLOR_WINDOW)); } return static_cast(FALSE); } void SaveChanges(HWND dialog) { Branch branch = UNKNOWN_BRANCH; if (IsDlgButtonChecked(dialog, IDC_STABLE)) branch = BETA_BRANCH; else if (IsDlgButtonChecked(dialog, IDC_CUTTING_EDGE)) branch = DEV_BRANCH; if (branch != UNKNOWN_BRANCH) { RegKey google_update(kGoogleUpdateRoot, kGoogleUpdateKey, KEY_WRITE); if (!google_update.WriteValue(kBranchKey, kBranchStrings[branch])) { MessageBox(dialog, L"Unable to change value, please make sure you\n" L"have permission to change registry keys under HKLM", L"Unable to update branch info", MB_OK); } else { std::wstring save_msg = L"Your changes have been saved.\nYou are now " L"on the " + std::wstring(kBranchStringsReadable[branch]) + L" branch."; MessageBox(dialog, save_msg.c_str(), L"Changes were saved", MB_OK); SetMainLabel(dialog, branch); } } } INT_PTR CALLBACK DialogWndProc(HWND dialog, UINT message_id, WPARAM wparam, LPARAM lparam) { UNREFERENCED_PARAMETER(lparam); switch (message_id) { case WM_INITDIALOG: OnInitDialog(dialog); return static_cast(TRUE); case WM_CTLCOLORSTATIC: return OnCtlColorStatic(dialog, wparam, lparam); case WM_COMMAND: // If the user presses the OK button. if (LOWORD(wparam) == IDOK) { SaveChanges(dialog); return static_cast(TRUE); } // If the user presses the Cancel button. if (LOWORD(wparam) == IDCANCEL) { ::EndDialog(dialog, LOWORD(wparam)); return static_cast(TRUE); } break; case WM_ERASEBKGND: PAINTSTRUCT paint; HDC hdc = BeginPaint(dialog, &paint); if (!hdc) return static_cast(FALSE); // We didn't handle it. // Fill the background with White. HBRUSH brush = GetStockBrush(WHITE_BRUSH); HGDIOBJ old_brush = SelectObject(hdc, brush); RECT rc; GetClientRect(dialog, &rc); FillRect(hdc, &rc, brush); // Clean up. SelectObject(hdc, old_brush); EndPaint(dialog, &paint); return static_cast(TRUE); } return static_cast(FALSE); } int APIENTRY _tWinMain(HINSTANCE instance, HINSTANCE previous_instance, LPTSTR cmd_line, int cmd_show) { UNREFERENCED_PARAMETER(previous_instance); UNREFERENCED_PARAMETER(cmd_line); UNREFERENCED_PARAMETER(cmd_show); dlg_icon = ::LoadIcon(instance, MAKEINTRESOURCE(IDI_BRANCH_SWITCHER)); ::DialogBox(instance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), GetDesktopWindow(), DialogWndProc); return TRUE; }