Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: chrome/installer/gcapi/gcapi.cc

Issue 8776038: Fix up GCAPI's LaunchGoogleChrome() method. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/installer/gcapi/gcapi.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // NOTE: This code is a legacy utility API for partners to check whether 5 // NOTE: This code is a legacy utility API for partners to check whether
6 // Chrome can be installed and launched. Recent updates are being made 6 // Chrome can be installed and launched. Recent updates are being made
7 // to add new functionality. These updates use code from Chromium, the old 7 // to add new functionality. These updates use code from Chromium, the old
8 // coded against the win32 api directly. If you have an itch to shave a 8 // coded against the win32 api directly. If you have an itch to shave a
9 // yak, feel free to re-write the old code too. 9 // yak, feel free to re-write the old code too.
10 10
11 #include "chrome/installer/gcapi/gcapi.h" 11 #include "chrome/installer/gcapi/gcapi.h"
12 12
13 #include <atlbase.h>
14 #include <atlcom.h>
15 #include <sddl.h> 13 #include <sddl.h>
16 #define STRSAFE_NO_DEPRECATE 14 #define STRSAFE_NO_DEPRECATE
17 #include <strsafe.h> 15 #include <strsafe.h>
18 #include <tlhelp32.h> 16 #include <tlhelp32.h>
19 #include <windows.h> 17 #include <windows.h>
20 18
21 #include <cstdlib> 19 #include <cstdlib>
22 #include <limits> 20 #include <limits>
23 #include <string> 21 #include <string>
24 22
25 #include "base/basictypes.h" 23 #include "base/basictypes.h"
24 #include "base/file_path.h"
25 #include "base/file_util.h"
26 #include "base/string_number_conversions.h" 26 #include "base/string_number_conversions.h"
27 #include "base/time.h" 27 #include "base/time.h"
28 #include "base/win/registry.h" 28 #include "base/win/registry.h"
29 #include "base/win/scoped_com_initializer.h"
30 #include "base/win/scoped_comptr.h"
31 #include "base/win/scoped_handle.h"
29 #include "chrome/installer/util/google_update_constants.h" 32 #include "chrome/installer/util/google_update_constants.h"
33 #include "chrome/installer/util/util_constants.h"
30 34
31 #include "google_update_idl.h" // NOLINT 35 #include "google_update_idl.h" // NOLINT
32 36
37 using base::Time;
38 using base::TimeDelta;
39 using base::win::RegKey;
40 using base::win::ScopedCOMInitializer;
41 using base::win::ScopedComPtr;
42 using base::win::ScopedHandle;
43
33 namespace { 44 namespace {
34 45
35 const wchar_t kChromeRegClientsKey[] = 46 const wchar_t kChromeRegClientsKey[] =
36 L"Software\\Google\\Update\\Clients\\" 47 L"Software\\Google\\Update\\Clients\\"
37 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 48 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
38 const wchar_t kChromeRegClientStateKey[] = 49 const wchar_t kChromeRegClientStateKey[] =
39 L"Software\\Google\\Update\\ClientState\\" 50 L"Software\\Google\\Update\\ClientState\\"
40 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 51 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
41 const wchar_t kChromeRegClientStateMediumKey[] = 52 const wchar_t kChromeRegClientStateMediumKey[] =
42 L"Software\\Google\\Update\\ClientStateMedium\\" 53 L"Software\\Google\\Update\\ClientStateMedium\\"
43 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 54 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
44 55
45 const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine"; 56 const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine";
46 const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine"; 57 const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine";
47 const wchar_t kChromeRegVersion[] = L"pv"; 58 const wchar_t kChromeRegVersion[] = L"pv";
48 const wchar_t kNoChromeOfferUntil[] = 59 const wchar_t kNoChromeOfferUntil[] =
49 L"SOFTWARE\\Google\\No Chrome Offer Until"; 60 L"SOFTWARE\\Google\\No Chrome Offer Until";
50 61
62 const wchar_t kChromeWindowClass[] = L"Chrome_WidgetWin_0";
63
51 // Return the company name specified in the file version info resource. 64 // Return the company name specified in the file version info resource.
52 bool GetCompanyName(const wchar_t* filename, wchar_t* buffer, DWORD out_len) { 65 bool GetCompanyName(const wchar_t* filename, wchar_t* buffer, DWORD out_len) {
53 wchar_t file_version_info[8192]; 66 wchar_t file_version_info[8192];
54 DWORD handle = 0; 67 DWORD handle = 0;
55 DWORD buffer_size = 0; 68 DWORD buffer_size = 0;
56 69
57 buffer_size = ::GetFileVersionInfoSize(filename, &handle); 70 buffer_size = ::GetFileVersionInfoSize(filename, &handle);
58 // Cannot stats the file or our buffer size is too small (very unlikely). 71 // Cannot stats the file or our buffer size is too small (very unlikely).
59 if (buffer_size == 0 || buffer_size > _countof(file_version_info)) 72 if (buffer_size == 0 || buffer_size > _countof(file_version_info))
60 return false; 73 return false;
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 local_reasons |= GCCC_ERROR_ALREADYOFFERED; 345 local_reasons |= GCCC_ERROR_ALREADYOFFERED;
333 346
334 // Done. Copy/return results. 347 // Done. Copy/return results.
335 if (reasons != NULL) 348 if (reasons != NULL)
336 *reasons = local_reasons; 349 *reasons = local_reasons;
337 350
338 return (local_reasons == 0); 351 return (local_reasons == 0);
339 } 352 }
340 353
341 BOOL __stdcall LaunchGoogleChrome() { 354 BOOL __stdcall LaunchGoogleChrome() {
342 wchar_t launch_cmd[MAX_PATH]; 355 // Check to make sure we have a valid Chrome installation.
343 size_t size = _countof(launch_cmd); 356 HKEY install_key = HKEY_LOCAL_MACHINE;
344 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey, 357 if (!IsChromeInstalled(install_key)) {
345 kChromeRegLastLaunchCmd, launch_cmd, &size)) { 358 install_key = HKEY_CURRENT_USER;
346 size = _countof(launch_cmd); 359 if (!IsChromeInstalled(install_key)) {
347 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey,
348 kChromeRegLaunchCmd, launch_cmd, &size)) {
349 return false; 360 return false;
350 } 361 }
351 } 362 }
352 363
353 HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 364 // Now grab the uninstall string from the appropriate ClientState key
354 if (hr != S_OK) { 365 // and use that as the base for a path to chrome.exe.
355 if (hr == S_FALSE) 366 FilePath chrome_exe_path;
356 ::CoUninitialize(); 367 RegKey client_state(install_key, kChromeRegClientStateKey, KEY_QUERY_VALUE);
368 if (client_state.Valid()) {
369 std::wstring uninstall_string;
370 if (client_state.ReadValue(installer::kUninstallStringField,
371 &uninstall_string) == ERROR_SUCCESS) {
372 // The uninstall path contains the path to setup.exe which is two levels
373 // down from chrome.exe. Move up two levels (plus one to drop the file
374 // name) and look for chrome.exe from there.
375 FilePath uninstall_path(uninstall_string);
376 chrome_exe_path = uninstall_path.DirName()
377 .DirName()
378 .DirName()
379 .Append(installer::kChromeExe);
380 if (!file_util::PathExists(chrome_exe_path)) {
381 // By way of mild future proofing, look up one to see if there's a
382 // chrome.exe in the version directory
383 chrome_exe_path =
384 uninstall_path.DirName().DirName().Append(installer::kChromeExe);
385 }
386 }
387 }
388
389 if (!file_util::PathExists(chrome_exe_path)) {
357 return false; 390 return false;
358 } 391 }
359 392
393 ScopedCOMInitializer com_initializer;
360 if (::CoInitializeSecurity(NULL, -1, NULL, NULL, 394 if (::CoInitializeSecurity(NULL, -1, NULL, NULL,
361 RPC_C_AUTHN_LEVEL_PKT_PRIVACY, 395 RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
362 RPC_C_IMP_LEVEL_IDENTIFY, NULL, 396 RPC_C_IMP_LEVEL_IDENTIFY, NULL,
363 EOAC_DYNAMIC_CLOAKING, NULL) != S_OK) { 397 EOAC_DYNAMIC_CLOAKING, NULL) != S_OK) {
364 ::CoUninitialize();
365 return false; 398 return false;
366 } 399 }
367 400
368 bool impersonation_success = false; 401 bool impersonation_success = false;
369 if (IsRunningElevated()) { 402 if (IsRunningElevated()) {
370 wchar_t* curr_proc_sid; 403 wchar_t* curr_proc_sid;
371 if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) { 404 if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) {
372 ::CoUninitialize();
373 return false; 405 return false;
374 } 406 }
375 407
376 DWORD pid = 0; 408 DWORD pid = 0;
377 ::GetWindowThreadProcessId(::GetShellWindow(), &pid); 409 ::GetWindowThreadProcessId(::GetShellWindow(), &pid);
378 if (pid <= 0) { 410 if (pid <= 0) {
379 ::LocalFree(curr_proc_sid); 411 ::LocalFree(curr_proc_sid);
380 ::CoUninitialize();
381 return false; 412 return false;
382 } 413 }
383 414
384 wchar_t* exp_proc_sid; 415 wchar_t* exp_proc_sid;
385 if (GetUserIdForProcess(pid, &exp_proc_sid)) { 416 if (GetUserIdForProcess(pid, &exp_proc_sid)) {
386 if (_wcsicmp(curr_proc_sid, exp_proc_sid) == 0) { 417 if (_wcsicmp(curr_proc_sid, exp_proc_sid) == 0) {
387 HANDLE process_handle = ::OpenProcess( 418 ScopedHandle process_handle(
388 PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, TRUE, pid); 419 ::OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
389 if (process_handle != NULL) { 420 TRUE,
421 pid));
422 if (process_handle.IsValid()) {
390 HANDLE process_token = NULL; 423 HANDLE process_token = NULL;
391 HANDLE user_token = NULL; 424 HANDLE user_token = NULL;
392 if (::OpenProcessToken(process_handle, TOKEN_DUPLICATE | TOKEN_QUERY, 425 if (::OpenProcessToken(process_handle, TOKEN_DUPLICATE | TOKEN_QUERY,
393 &process_token) && 426 &process_token) &&
394 ::DuplicateTokenEx(process_token, 427 ::DuplicateTokenEx(process_token,
395 TOKEN_IMPERSONATE | TOKEN_QUERY | 428 TOKEN_IMPERSONATE | TOKEN_QUERY |
396 TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, 429 TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE,
397 NULL, SecurityImpersonation, 430 NULL, SecurityImpersonation,
398 TokenPrimary, &user_token) && 431 TokenPrimary, &user_token) &&
399 (::ImpersonateLoggedOnUser(user_token) != 0)) { 432 (::ImpersonateLoggedOnUser(user_token) != 0)) {
400 impersonation_success = true; 433 impersonation_success = true;
401 } 434 }
402 if (user_token) 435 if (user_token)
403 ::CloseHandle(user_token); 436 ::CloseHandle(user_token);
404 if (process_token) 437 if (process_token)
405 ::CloseHandle(process_token); 438 ::CloseHandle(process_token);
406 ::CloseHandle(process_handle);
407 } 439 }
408 } 440 }
409 ::LocalFree(exp_proc_sid); 441 ::LocalFree(exp_proc_sid);
410 } 442 }
411 443
412 ::LocalFree(curr_proc_sid); 444 ::LocalFree(curr_proc_sid);
413 if (!impersonation_success) { 445 if (!impersonation_success) {
414 ::CoUninitialize();
415 return false; 446 return false;
416 } 447 }
417 } 448 }
418 449
419 bool ret = false; 450 bool ret = false;
420 CComPtr<IProcessLauncher> ipl; 451 ScopedComPtr<IProcessLauncher> ipl;
421 if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass), NULL, 452 if (SUCCEEDED(ipl.CreateInstance(__uuidof(ProcessLauncherClass),
453 NULL,
422 CLSCTX_LOCAL_SERVER))) { 454 CLSCTX_LOCAL_SERVER))) {
423 if (!FAILED(ipl->LaunchCmdLine(launch_cmd))) 455 if (SUCCEEDED(ipl->LaunchCmdLine(chrome_exe_path.value().c_str())))
424 ret = true; 456 ret = true;
425 ipl.Release(); 457 ipl.Release();
426 } 458 }
427 459
428 if (impersonation_success) 460 if (impersonation_success)
429 ::RevertToSelf(); 461 ::RevertToSelf();
430 ::CoUninitialize();
431 return ret; 462 return ret;
432 } 463 }
433 464
434 BOOL __stdcall LaunchGoogleChromeWithDimensions(int x, 465 BOOL __stdcall LaunchGoogleChromeWithDimensions(int x,
435 int y, 466 int y,
436 int width, 467 int width,
437 int height) { 468 int height,
469 bool in_background) {
438 if (!LaunchGoogleChrome()) 470 if (!LaunchGoogleChrome())
439 return false; 471 return false;
440 472
441 HWND handle = NULL; 473 HWND handle = NULL;
442 int seconds_elapsed = 0; 474 int seconds_elapsed = 0;
443 475
444 // Chrome may have been launched, but the window may not have appeared 476 // Chrome may have been launched, but the window may not have appeared
445 // yet. Wait for it to appear for 10 seconds, but exit if it takes longer 477 // yet. Wait for it to appear for 10 seconds, but exit if it takes longer
446 // than that. 478 // than that.
447 while (!handle && seconds_elapsed < 10) { 479 while (!handle && seconds_elapsed < 10) {
448 handle = FindWindowEx(NULL, handle, L"Chrome_WindowImpl_0", NULL); 480 handle = FindWindowEx(NULL, handle, kChromeWindowClass, NULL);
449 if (!handle) { 481 if (!handle) {
450 Sleep(1000); 482 Sleep(1000);
451 seconds_elapsed++; 483 seconds_elapsed++;
452 } 484 }
453 } 485 }
454 486
455 if (!handle) 487 if (!handle)
456 return false; 488 return false;
457 489
458 // At this point, there are several top-level Chrome windows 490 // At this point, there are several top-level Chrome windows
459 // but we only want the window that has child windows. 491 // but we only want the window that has child windows.
460 492
461 // This loop iterates through all of the top-level Windows named 493 // This loop iterates through all of the top-level Windows named
462 // Chrome_WindowImpl_0, and looks for the first one with any children. 494 // kChromeWindowClass, and looks for the first one with any children.
463 while (handle && !FindWindowEx(handle, NULL, L"Chrome_WindowImpl_0", NULL)) { 495 while (handle && !FindWindowEx(handle, NULL, kChromeWindowClass, NULL)) {
464 // Get the next top-level Chrome window. 496 // Get the next top-level Chrome window.
465 handle = FindWindowEx(NULL, handle, L"Chrome_WindowImpl_0", NULL); 497 handle = FindWindowEx(NULL, handle, kChromeWindowClass, NULL);
466 } 498 }
467 499
500 HWND set_window_hwnd_insert_after = in_background ? HWND_BOTTOM : NULL;
501 DWORD set_window_flags = in_background ? SWP_NOACTIVATE : SWP_NOZORDER;
502
468 return (handle && 503 return (handle &&
469 SetWindowPos(handle, 0, x, y, width, height, SWP_NOZORDER)); 504 SetWindowPos(handle, set_window_hwnd_insert_after, x, y,
505 width, height, set_window_flags));
470 } 506 }
471 507
472 int __stdcall GoogleChromeDaysSinceLastRun() { 508 int __stdcall GoogleChromeDaysSinceLastRun() {
473 using base::win::RegKey;
474 using base::Time;
475 using base::TimeDelta;
476
477 int days_since_last_run = std::numeric_limits<int>::max(); 509 int days_since_last_run = std::numeric_limits<int>::max();
478 510
479 struct { 511 struct {
480 HKEY hive; 512 HKEY hive;
481 const wchar_t* path; 513 const wchar_t* path;
482 } reg_data[] = { 514 } reg_data[] = {
483 { HKEY_LOCAL_MACHINE, kChromeRegClientStateMediumKey }, 515 { HKEY_LOCAL_MACHINE, kChromeRegClientStateMediumKey },
484 { HKEY_CURRENT_USER, kChromeRegClientStateKey } 516 { HKEY_CURRENT_USER, kChromeRegClientStateKey }
485 }; 517 };
486 518
(...skipping 20 matching lines...) Expand all
507 } 539 }
508 } 540 }
509 } 541 }
510 542
511 if (days_since_last_run == std::numeric_limits<int>::max()) { 543 if (days_since_last_run == std::numeric_limits<int>::max()) {
512 days_since_last_run = -1; 544 days_since_last_run = -1;
513 } 545 }
514 546
515 return days_since_last_run; 547 return days_since_last_run;
516 } 548 }
OLDNEW
« no previous file with comments | « chrome/installer/gcapi/gcapi.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698