Home | History | Annotate | Download | only in app
      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
      3 // found in the LICENSE file.
      4 
      5 #include <windows.h>
      6 #include <tchar.h>
      7 
      8 #include <string>
      9 
     10 #include "base/at_exit.h"
     11 #include "base/command_line.h"
     12 #include "base/files/file_path.h"
     13 #include "base/lazy_instance.h"
     14 #include "chrome/app/chrome_breakpad_client.h"
     15 #include "chrome/app/breakpad_win.h"
     16 #include "chrome/app/client_util.h"
     17 #include "chrome/app/metro_driver_win.h"
     18 #include "chrome/browser/chrome_process_finder_win.h"
     19 #include "chrome/browser/policy/policy_path_parser.h"
     20 #include "chrome/common/chrome_paths_internal.h"
     21 #include "chrome/common/chrome_switches.h"
     22 #include "components/breakpad/breakpad_client.h"
     23 #include "content/public/app/startup_helper_win.h"
     24 #include "content/public/common/result_codes.h"
     25 #include "sandbox/win/src/sandbox_factory.h"
     26 
     27 namespace {
     28 
     29 base::LazyInstance<chrome::ChromeBreakpadClient>::Leaky
     30     g_chrome_breakpad_client = LAZY_INSTANCE_INITIALIZER;
     31 
     32 int RunChrome(HINSTANCE instance) {
     33   breakpad::SetBreakpadClient(g_chrome_breakpad_client.Pointer());
     34 
     35   bool exit_now = true;
     36   // We restarted because of a previous crash. Ask user if we should relaunch.
     37   if (ShowRestartDialogIfCrashed(&exit_now)) {
     38     if (exit_now)
     39       return content::RESULT_CODE_NORMAL_EXIT;
     40   }
     41 
     42   // Initialize the sandbox services.
     43   sandbox::SandboxInterfaceInfo sandbox_info = {0};
     44   content::InitializeSandboxInfo(&sandbox_info);
     45 
     46   // Load and launch the chrome dll. *Everything* happens inside.
     47   MainDllLoader* loader = MakeMainDllLoader();
     48   int rc = loader->Launch(instance, &sandbox_info);
     49   loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded();
     50   delete loader;
     51   return rc;
     52 }
     53 
     54 // List of switches that it's safe to rendezvous early with. Fast start should
     55 // not be done if a command line contains a switch not in this set.
     56 // Note this is currently stored as a list of two because it's probably faster
     57 // to iterate over this small array than building a map for constant time
     58 // lookups.
     59 const char* const kFastStartSwitches[] = {
     60   switches::kProfileDirectory,
     61   switches::kShowAppList,
     62 };
     63 
     64 bool IsFastStartSwitch(const std::string& command_line_switch) {
     65   for (size_t i = 0; i < arraysize(kFastStartSwitches); ++i) {
     66     if (command_line_switch == kFastStartSwitches[i])
     67       return true;
     68   }
     69   return false;
     70 }
     71 
     72 bool ContainsNonFastStartFlag(const CommandLine& command_line) {
     73   const CommandLine::SwitchMap& switches = command_line.GetSwitches();
     74   if (switches.size() > arraysize(kFastStartSwitches))
     75     return true;
     76   for (CommandLine::SwitchMap::const_iterator it = switches.begin();
     77        it != switches.end(); ++it) {
     78     if (!IsFastStartSwitch(it->first))
     79       return true;
     80   }
     81   return false;
     82 }
     83 
     84 bool AttemptFastNotify(const CommandLine& command_line) {
     85   if (ContainsNonFastStartFlag(command_line))
     86     return false;
     87 
     88   base::FilePath user_data_dir;
     89   if (!chrome::GetDefaultUserDataDirectory(&user_data_dir))
     90     return false;
     91   policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
     92 
     93   HWND chrome = chrome::FindRunningChromeWindow(user_data_dir);
     94   if (!chrome)
     95     return false;
     96   return chrome::AttemptToNotifyRunningChrome(chrome, true) ==
     97       chrome::NOTIFY_SUCCESS;
     98 }
     99 
    100 }  // namespace
    101 
    102 int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) {
    103   // Initialize the commandline singleton from the environment.
    104   CommandLine::Init(0, NULL);
    105   // The exit manager is in charge of calling the dtors of singletons.
    106   base::AtExitManager exit_manager;
    107 
    108   if (AttemptFastNotify(*CommandLine::ForCurrentProcess()))
    109     return 0;
    110 
    111   MetroDriver metro_driver;
    112   if (metro_driver.in_metro_mode())
    113     return metro_driver.RunInMetro(instance, &RunChrome);
    114   // Not in metro mode, proceed as normal.
    115   return RunChrome(instance);
    116 }
    117