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

Side by Side Diff: chrome/browser/process_singleton_win.cc

Issue 1581473002: Remove base/win/metro.{cc|h} and some associated code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixes Created 4 years, 11 months 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "chrome/browser/process_singleton.h" 5 #include "chrome/browser/process_singleton.h"
6 6
7 #include <shellapi.h> 7 #include <shellapi.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include "base/base_paths.h" 10 #include "base/base_paths.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/process/process.h" 15 #include "base/process/process.h"
16 #include "base/process/process_info.h" 16 #include "base/process/process_info.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h" 20 #include "base/time/time.h"
21 #include "base/win/metro.h"
22 #include "base/win/registry.h" 21 #include "base/win/registry.h"
23 #include "base/win/scoped_handle.h" 22 #include "base/win/scoped_handle.h"
24 #include "base/win/windows_version.h" 23 #include "base/win/windows_version.h"
25 #include "chrome/browser/browser_process.h" 24 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/browser_process_platform_part.h" 25 #include "chrome/browser/browser_process_platform_part.h"
27 #include "chrome/browser/chrome_process_finder_win.h" 26 #include "chrome/browser/chrome_process_finder_win.h"
28 #include "chrome/browser/metro_utils/metro_chrome_win.h"
29 #include "chrome/browser/shell_integration.h" 27 #include "chrome/browser/shell_integration.h"
30 #include "chrome/browser/ui/simple_message_box.h" 28 #include "chrome/browser/ui/simple_message_box.h"
31 #include "chrome/common/chrome_constants.h" 29 #include "chrome/common/chrome_constants.h"
32 #include "chrome/common/chrome_paths.h" 30 #include "chrome/common/chrome_paths.h"
33 #include "chrome/common/chrome_paths_internal.h" 31 #include "chrome/common/chrome_paths_internal.h"
34 #include "chrome/common/chrome_switches.h" 32 #include "chrome/common/chrome_switches.h"
35 #include "chrome/grit/chromium_strings.h" 33 #include "chrome/grit/chromium_strings.h"
36 #include "chrome/installer/util/wmi.h" 34 #include "chrome/installer/util/wmi.h"
37 #include "content/public/common/result_codes.h" 35 #include "content/public/common/result_codes.h"
38 #include "net/base/escape.h" 36 #include "net/base/escape.h"
39 #include "ui/base/l10n/l10n_util.h" 37 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/gfx/win/hwnd_util.h" 38 #include "ui/gfx/win/hwnd_util.h"
41 39
42 namespace { 40 namespace {
43 41
44 const char kLockfile[] = "lockfile"; 42 const char kLockfile[] = "lockfile";
45 43
46 const int kMetroChromeActivationTimeoutMs = 3000;
47
48 // A helper class that acquires the given |mutex| while the AutoLockMutex is in 44 // A helper class that acquires the given |mutex| while the AutoLockMutex is in
49 // scope. 45 // scope.
50 class AutoLockMutex { 46 class AutoLockMutex {
51 public: 47 public:
52 explicit AutoLockMutex(HANDLE mutex) : mutex_(mutex) { 48 explicit AutoLockMutex(HANDLE mutex) : mutex_(mutex) {
53 DWORD result = ::WaitForSingleObject(mutex_, INFINITE); 49 DWORD result = ::WaitForSingleObject(mutex_, INFINITE);
54 DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result; 50 DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result;
55 } 51 }
56 52
57 ~AutoLockMutex() { 53 ~AutoLockMutex() {
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 *base::CommandLine::ForCurrentProcess()); 307 *base::CommandLine::ForCurrentProcess());
312 } 308 }
313 return result; 309 return result;
314 } 310 }
315 311
316 // Look for a Chrome instance that uses the same profile directory. If there 312 // Look for a Chrome instance that uses the same profile directory. If there
317 // isn't one, create a message window with its title set to the profile 313 // isn't one, create a message window with its title set to the profile
318 // directory path. 314 // directory path.
319 bool ProcessSingleton::Create() { 315 bool ProcessSingleton::Create() {
320 static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!"; 316 static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!";
321 static const wchar_t kMetroActivationEventName[] =
322 L"Local\\ChromeProcessSingletonStartupMetroActivation!";
323 317
324 remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); 318 remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_);
325 if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) { 319 if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) {
326 // Make sure we will be the one and only process creating the window. 320 // Make sure we will be the one and only process creating the window.
327 // We use a named Mutex since we are protecting against multi-process 321 // We use a named Mutex since we are protecting against multi-process
328 // access. As documented, it's clearer to NOT request ownership on creation 322 // access. As documented, it's clearer to NOT request ownership on creation
329 // since it isn't guaranteed we will get it. It is better to create it 323 // since it isn't guaranteed we will get it. It is better to create it
330 // without ownership and explicitly get the ownership afterward. 324 // without ownership and explicitly get the ownership afterward.
331 base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName)); 325 base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName));
332 if (!only_me.IsValid()) { 326 if (!only_me.IsValid()) {
333 DPLOG(FATAL) << "CreateMutex failed"; 327 DPLOG(FATAL) << "CreateMutex failed";
334 return false; 328 return false;
335 } 329 }
336 330
337 AutoLockMutex auto_lock_only_me(only_me.Get()); 331 AutoLockMutex auto_lock_only_me(only_me.Get());
338 332
339 // We now own the mutex so we are the only process that can create the 333 // We now own the mutex so we are the only process that can create the
340 // window at this time, but we must still check if someone created it 334 // window at this time, but we must still check if someone created it
341 // between the time where we looked for it above and the time the mutex 335 // between the time where we looked for it above and the time the mutex
342 // was given to us. 336 // was given to us.
343 remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); 337 remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_);
344 338
345
346 // In Win8+, a new Chrome process launched in Desktop mode may need to be
347 // transmuted into Metro Chrome (see ShouldLaunchInWindows8ImmersiveMode for
348 // heuristics). To accomplish this, the current Chrome activates Metro
349 // Chrome, releases the startup mutex, and waits for metro Chrome to take
350 // the singleton. From that point onward, the command line for this Chrome
351 // process will be sent to Metro Chrome by the usual channels.
352 if (!remote_window_ && base::win::GetVersion() >= base::win::VERSION_WIN8 &&
353 !base::win::IsMetroProcess()) {
354 // |metro_activation_event| is created right before activating a Metro
355 // Chrome (note that there can only be one Metro Chrome process; by OS
356 // design); all following Desktop processes will then wait for this event
357 // to be signaled by Metro Chrome which will do so as soon as it grabs
358 // this singleton (should any of the waiting processes timeout waiting for
359 // the signal they will try to grab the singleton for themselves which
360 // will result in a forced Desktop Chrome launch in the worst case).
361 base::win::ScopedHandle metro_activation_event(
362 ::OpenEvent(SYNCHRONIZE, FALSE, kMetroActivationEventName));
363 if (!metro_activation_event.IsValid() &&
364 ShouldLaunchInWindows8ImmersiveMode(user_data_dir_)) {
365 // No Metro activation is under way, but the desire is to launch in
366 // Metro mode: activate and rendez-vous with the activated process.
367 metro_activation_event.Set(
368 ::CreateEvent(NULL, TRUE, FALSE, kMetroActivationEventName));
369 if (!chrome::ActivateMetroChrome()) {
370 // Failed to launch immersive Chrome, default to launching on Desktop.
371 LOG(ERROR) << "Failed to launch immersive chrome";
372 metro_activation_event.Close();
373 }
374 }
375
376 if (metro_activation_event.IsValid()) {
377 // Release |only_me| (to let Metro Chrome grab this singleton) and wait
378 // until the event is signaled (i.e. Metro Chrome was successfully
379 // activated). Ignore timeout waiting for |metro_activation_event|.
380 {
381 AutoUnlockMutex auto_unlock_only_me(only_me.Get());
382
383 DWORD result = ::WaitForSingleObject(metro_activation_event.Get(),
384 kMetroChromeActivationTimeoutMs);
385 DPCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT)
386 << "Result = " << result;
387 }
388
389 // Check if this singleton was successfully grabbed by another process
390 // (hopefully Metro Chrome). Failing to do so, this process will grab
391 // the singleton and launch in Desktop mode.
392 remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_);
393 }
394 }
395
396 if (!remote_window_) { 339 if (!remote_window_) {
397 // We have to make sure there is no Chrome instance running on another 340 // We have to make sure there is no Chrome instance running on another
398 // machine that uses the same profile. 341 // machine that uses the same profile.
399 base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile); 342 base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile);
400 lock_file_ = ::CreateFile(lock_file_path.value().c_str(), 343 lock_file_ = ::CreateFile(lock_file_path.value().c_str(),
401 GENERIC_WRITE, 344 GENERIC_WRITE,
402 FILE_SHARE_READ, 345 FILE_SHARE_READ,
403 NULL, 346 NULL,
404 CREATE_ALWAYS, 347 CREATE_ALWAYS,
405 FILE_ATTRIBUTE_NORMAL | 348 FILE_ATTRIBUTE_NORMAL |
406 FILE_FLAG_DELETE_ON_CLOSE, 349 FILE_FLAG_DELETE_ON_CLOSE,
407 NULL); 350 NULL);
408 DWORD error = ::GetLastError(); 351 DWORD error = ::GetLastError();
409 LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE && 352 LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE &&
410 error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable."; 353 error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable.";
411 LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE) 354 LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE)
412 << "Lock file can not be created! Error code: " << error; 355 << "Lock file can not be created! Error code: " << error;
413 356
414 if (lock_file_ != INVALID_HANDLE_VALUE) { 357 if (lock_file_ != INVALID_HANDLE_VALUE) {
415 // Set the window's title to the path of our user data directory so 358 // Set the window's title to the path of our user data directory so
416 // other Chrome instances can decide if they should forward to us. 359 // other Chrome instances can decide if they should forward to us.
417 bool result = window_.CreateNamed( 360 bool result = window_.CreateNamed(
418 base::Bind(&ProcessLaunchNotification, notification_callback_), 361 base::Bind(&ProcessLaunchNotification, notification_callback_),
419 user_data_dir_.value()); 362 user_data_dir_.value());
420 CHECK(result && window_.hwnd()); 363 CHECK(result && window_.hwnd());
421 } 364 }
422
423 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
424 // Make sure no one is still waiting on Metro activation whether it
425 // succeeded (i.e., this is the Metro process) or failed.
426 base::win::ScopedHandle metro_activation_event(
427 ::OpenEvent(EVENT_MODIFY_STATE, FALSE, kMetroActivationEventName));
428 if (metro_activation_event.IsValid())
429 ::SetEvent(metro_activation_event.Get());
430 }
431 } 365 }
432 } 366 }
433 367
434 return window_.hwnd() != NULL; 368 return window_.hwnd() != NULL;
435 } 369 }
436 370
437 void ProcessSingleton::Cleanup() { 371 void ProcessSingleton::Cleanup() {
438 } 372 }
439 373
440 void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting( 374 void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting(
441 const ShouldKillRemoteProcessCallback& display_dialog_callback) { 375 const ShouldKillRemoteProcessCallback& display_dialog_callback) {
442 should_kill_remote_process_callback_ = display_dialog_callback; 376 should_kill_remote_process_callback_ = display_dialog_callback;
443 } 377 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698