12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "win8/test/metro_registration_helper.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <shlobj.h> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector> 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h" 16bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/kill.h" 17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h" 18bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process.h" 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string16.h" 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/win/scoped_co_mem.h" 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/win/scoped_comptr.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_handle.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "win8/test/open_with_dialog_controller.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "win8/test/test_registrar_constants.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kRegistrationTimeoutSeconds = 30; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copied from util_constants.cc to avoid taking a dependency on installer_util. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t kChromeExe[] = L"chrome.exe"; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t kRegistrar[] = L"test_registrar.exe"; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Registers chrome.exe as a potential Win8 default browser. It will then show 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// up in the default browser selection dialog as kDefaultTestExeName. Intended 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// to be used by a test binary in the build output directory and assumes the 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// presence of test_registrar.exe, a viewer process, and all needed DLLs in the 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// same directory as the calling module. 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool RegisterTestDefaultBrowser() { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath dir; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!PathService::Get(base::DIR_EXE, &dir)) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe(dir.Append(kChromeExe)); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath registrar(dir.Append(kRegistrar)); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(chrome_exe) || !base::PathExists(registrar)) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Could not locate " << kChromeExe << " or " << kRegistrar; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Perform the registration by invoking test_registrar.exe. 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandLine register_command(registrar); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) register_command.AppendArg("/RegServer"); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedHandle register_handle; 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (base::LaunchProcess(register_command.GetCommandLineString(), 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::LaunchOptions(), 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ®ister_handle)) { 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int ret = 0; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::WaitForExitCodeWithTimeout( 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) register_handle.Get(), &ret, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromSeconds(kRegistrationTimeoutSeconds))) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret == 0) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Win8 registration using " 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << register_command.GetCommandLineString() 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " failed with error code " << ret; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Win8 registration using " 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << register_command.GetCommandLineString() << " timed out."; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "Failed to launch Win8 registration utility using " 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << register_command.GetCommandLineString(); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returns true if the test viewer's progid is the default handler for 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// |protocol|. 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool IsTestDefaultForProtocol(const wchar_t* protocol) { 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::win::ScopedComPtr<IApplicationAssociationRegistration> registration; 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HRESULT hr = registration.CreateInstance( 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CLSID_ApplicationAssociationRegistration, NULL, CLSCTX_INPROC); 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (FAILED(hr)) { 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(ERROR) << std::hex << hr; 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::win::ScopedCoMem<wchar_t> current_app; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) hr = registration->QueryCurrentDefault(protocol, AT_URLPROTOCOL, 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AL_EFFECTIVE, ¤t_app); 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (FAILED(hr)) { 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(ERROR) << std::hex << hr; 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !base::string16(win8::test::kDefaultTestProgId).compare(current_app); 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace win8 { 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool MakeTestDefaultBrowserSynchronously() { 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static const wchar_t kDefaultBrowserProtocol[] = L"http"; 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!RegisterTestDefaultBrowser()) 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Make sure the registration changes have been acknowledged by the shell 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // before querying for the current default. 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSH, NULL, NULL); 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // OpenWithDialogController will fail if the Test Runner is already default 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // since it will not show up verbatim in the dialog (e.g., in EN-US, it will 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // be prefixed by "Keep using "). 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (IsTestDefaultForProtocol(kDefaultBrowserProtocol)) 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<base::string16> choices; 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) OpenWithDialogController controller; 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HRESULT hr = controller.RunSynchronously( 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NULL, kDefaultBrowserProtocol, win8::test::kDefaultTestExeName, &choices); 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG_IF(ERROR, FAILED(hr)) << std::hex << hr; 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(IsTestDefaultForProtocol(kDefaultBrowserProtocol)); 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return SUCCEEDED(hr); 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace win8 134