browser_window_property_manager_browsertest_win.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <string> 6 7#include <shlobj.h> // Must be before propkey. 8#include <propkey.h> 9#include <shellapi.h> 10 11#include "base/command_line.h" 12#include "base/strings/string16.h" 13#include "base/strings/utf_string_conversions.h" 14#include "base/win/scoped_comptr.h" 15#include "base/win/scoped_propvariant.h" 16#include "base/win/windows_version.h" 17#include "chrome/browser/browser_process.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/profiles/profile_info_cache.h" 20#include "chrome/browser/profiles/profile_manager.h" 21#include "chrome/browser/profiles/profile_shortcut_manager_win.h" 22#include "chrome/browser/profiles/profiles_state.h" 23#include "chrome/browser/ui/browser.h" 24#include "chrome/browser/ui/browser_window.h" 25#include "chrome/common/chrome_switches.h" 26#include "chrome/installer/util/browser_distribution.h" 27#include "chrome/test/base/in_process_browser_test.h" 28#include "chrome/test/base/test_switches.h" 29#include "content/public/test/test_utils.h" 30#include "ui/views/win/hwnd_util.h" 31 32namespace { 33 34// An observer that resumes test code after a new profile is initialized by 35// quitting the message loop it's blocked on. 36void UnblockOnProfileCreation(Profile* profile, 37 Profile::CreateStatus status) { 38 if (status == Profile::CREATE_STATUS_INITIALIZED) 39 base::MessageLoop::current()->Quit(); 40} 41 42// Checks that the relaunch name, relaunch command and app icon for the given 43// |browser| are correct. 44void ValidateBrowserWindowProperties( 45 const Browser* browser, 46 const base::string16& expected_profile_name) { 47 HWND hwnd = views::HWNDForNativeWindow(browser->window()->GetNativeWindow()); 48 49 base::win::ScopedComPtr<IPropertyStore> pps; 50 HRESULT result = SHGetPropertyStoreForWindow(hwnd, IID_IPropertyStore, 51 pps.ReceiveVoid()); 52 EXPECT_TRUE(SUCCEEDED(result)); 53 54 base::win::ScopedPropVariant prop_var; 55 // The relaunch name should be of the form "Chromium" if there is only 1 56 // profile and "First User - Chromium" if there are more. The expected value 57 // is given by |expected_profile_name|. 58 EXPECT_EQ(S_OK, pps->GetValue(PKEY_AppUserModel_RelaunchDisplayNameResource, 59 prop_var.Receive())); 60 EXPECT_EQ(VT_LPWSTR, prop_var.get().vt); 61 EXPECT_EQ( 62 base::FilePath(profiles::internal::GetShortcutFilenameForProfile( 63 expected_profile_name, 64 BrowserDistribution::GetDistribution())).RemoveExtension().value(), 65 prop_var.get().pwszVal); 66 prop_var.Reset(); 67 68 // The relaunch command should specify the profile. 69 EXPECT_EQ(S_OK, pps->GetValue(PKEY_AppUserModel_RelaunchCommand, 70 prop_var.Receive())); 71 EXPECT_EQ(VT_LPWSTR, prop_var.get().vt); 72 CommandLine cmd_line(CommandLine::FromString(prop_var.get().pwszVal)); 73 EXPECT_EQ(browser->profile()->GetPath().BaseName().value(), 74 cmd_line.GetSwitchValueNative(switches::kProfileDirectory)); 75 prop_var.Reset(); 76 77 // The app icon should be set to the profile icon. 78 EXPECT_EQ(S_OK, pps->GetValue(PKEY_AppUserModel_RelaunchIconResource, 79 prop_var.Receive())); 80 EXPECT_EQ(VT_LPWSTR, prop_var.get().vt); 81 EXPECT_EQ(profiles::internal::GetProfileIconPath( 82 browser->profile()->GetPath()).value(), 83 prop_var.get().pwszVal); 84 prop_var.Reset(); 85 base::MessageLoop::current()->Quit(); 86} 87 88void PostValidationTaskToUIThread(const base::Closure& validation_task) { 89 content::BrowserThread::PostTask( 90 content::BrowserThread::UI, FROM_HERE, validation_task); 91} 92 93// Posts a validation task to the FILE thread which bounces back to the UI 94// thread and then does validation. This is necessary because the icon profile 95// pref only gets set at the end of icon creation (which happens on the FILE 96// thread) and is set on the UI thread. 97void WaitAndValidateBrowserWindowProperties( 98 const base::Closure& validation_task) { 99 content::BrowserThread::PostTask( 100 content::BrowserThread::FILE, 101 FROM_HERE, 102 base::Bind(&PostValidationTaskToUIThread, validation_task)); 103 content::RunMessageLoop(); 104} 105 106} // namespace 107 108// Tests that require the profile shortcut manager to be instantiated despite 109// having --user-data-dir specified. 110class BrowserTestWithProfileShortcutManager : public InProcessBrowserTest { 111 public: 112 BrowserTestWithProfileShortcutManager() {} 113 114 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 115 command_line->AppendSwitch(switches::kEnableProfileShortcutManager); 116 } 117 118 private: 119 DISALLOW_COPY_AND_ASSIGN(BrowserTestWithProfileShortcutManager); 120}; 121 122// Check that the window properties on Windows are properly set. 123IN_PROC_BROWSER_TEST_F(BrowserTestWithProfileShortcutManager, 124 WindowProperties) { 125#if defined(USE_ASH) 126 // Disable this test in Metro+Ash where Windows window properties aren't used. 127 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 128 return; 129#endif 130 131 // This test checks HWND properties that are only available on Win7+. 132 if (base::win::GetVersion() < base::win::VERSION_WIN7) 133 return; 134 135 // Single profile case. The profile name should not be shown. 136 WaitAndValidateBrowserWindowProperties(base::Bind( 137 &ValidateBrowserWindowProperties, browser(), base::string16())); 138 139 // If multiprofile mode is not enabled, we can't test the behavior when there 140 // are multiple profiles. 141 if (!profiles::IsMultipleProfilesEnabled()) 142 return; 143 144 // Two profile case. Both profile names should be shown. 145 ProfileManager* profile_manager = g_browser_process->profile_manager(); 146 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 147 148 base::FilePath path_profile2 = 149 profile_manager->GenerateNextProfileDirectoryPath(); 150 profile_manager->CreateProfileAsync(path_profile2, 151 base::Bind(&UnblockOnProfileCreation), 152 base::string16(), base::string16(), 153 std::string()); 154 155 // Spin to allow profile creation to take place, loop is terminated 156 // by UnblockOnProfileCreation when the profile is created. 157 content::RunMessageLoop(); 158 159 // The default profile's name should be part of the relaunch name. 160 WaitAndValidateBrowserWindowProperties( 161 base::Bind(&ValidateBrowserWindowProperties, 162 browser(), 163 base::UTF8ToUTF16(browser()->profile()->GetProfileName()))); 164 165 // The second profile's name should be part of the relaunch name. 166 Browser* profile2_browser = 167 CreateBrowser(profile_manager->GetProfileByPath(path_profile2)); 168 size_t profile2_index = cache.GetIndexOfProfileWithPath(path_profile2); 169 WaitAndValidateBrowserWindowProperties( 170 base::Bind(&ValidateBrowserWindowProperties, 171 profile2_browser, 172 cache.GetNameOfProfileAtIndex(profile2_index))); 173} 174