| OLD | NEW | 
|    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/first_run/first_run.h" |    5 #include "chrome/browser/first_run/first_run.h" | 
|    6  |    6  | 
|    7 #include <windows.h> |  | 
|    8 #include <shellapi.h> |    7 #include <shellapi.h> | 
|    9 #include <shlobj.h> |  | 
|   10  |    8  | 
 |    9 #include "base/base_paths.h" | 
|   11 #include "base/callback.h" |   10 #include "base/callback.h" | 
|   12 #include "base/environment.h" |  | 
|   13 #include "base/file_util.h" |   11 #include "base/file_util.h" | 
|   14 #include "base/files/file_path.h" |   12 #include "base/files/file_path.h" | 
|   15 #include "base/path_service.h" |   13 #include "base/path_service.h" | 
|   16 #include "base/prefs/pref_service.h" |   14 #include "base/prefs/pref_service.h" | 
 |   15 #include "base/process.h" | 
|   17 #include "base/process_util.h" |   16 #include "base/process_util.h" | 
|   18 #include "base/stringprintf.h" |  | 
|   19 #include "base/strings/string_number_conversions.h" |  | 
|   20 #include "base/strings/string_split.h" |  | 
|   21 #include "base/threading/sequenced_worker_pool.h" |   17 #include "base/threading/sequenced_worker_pool.h" | 
|   22 #include "base/time.h" |   18 #include "base/time.h" | 
|   23 #include "base/utf_string_conversions.h" |  | 
|   24 #include "base/win/metro.h" |   19 #include "base/win/metro.h" | 
|   25 #include "base/win/object_watcher.h" |  | 
|   26 #include "base/win/windows_version.h" |  | 
|   27 #include "chrome/browser/browser_process.h" |  | 
|   28 #include "chrome/browser/first_run/first_run_internal.h" |   20 #include "chrome/browser/first_run/first_run_internal.h" | 
|   29 #include "chrome/browser/importer/importer_host.h" |  | 
|   30 #include "chrome/browser/importer/importer_list.h" |  | 
|   31 #include "chrome/browser/process_singleton.h" |  | 
|   32 #include "chrome/browser/profiles/profile.h" |  | 
|   33 #include "chrome/browser/shell_integration.h" |  | 
|   34 #include "chrome/common/chrome_constants.h" |   21 #include "chrome/common/chrome_constants.h" | 
|   35 #include "chrome/common/chrome_paths.h" |   22 #include "chrome/common/chrome_paths.h" | 
|   36 #include "chrome/common/chrome_result_codes.h" |  | 
|   37 #include "chrome/common/chrome_switches.h" |   23 #include "chrome/common/chrome_switches.h" | 
|   38 #include "chrome/common/pref_names.h" |  | 
|   39 #include "chrome/common/worker_thread_ticker.h" |  | 
|   40 #include "chrome/installer/util/browser_distribution.h" |  | 
|   41 #include "chrome/installer/util/google_update_settings.h" |   24 #include "chrome/installer/util/google_update_settings.h" | 
|   42 #include "chrome/installer/util/install_util.h" |   25 #include "chrome/installer/util/install_util.h" | 
|   43 #include "chrome/installer/util/master_preferences.h" |   26 #include "chrome/installer/util/master_preferences.h" | 
|   44 #include "chrome/installer/util/master_preferences_constants.h" |   27 #include "chrome/installer/util/master_preferences_constants.h" | 
|   45 #include "chrome/installer/util/shell_util.h" |  | 
|   46 #include "chrome/installer/util/util_constants.h" |   28 #include "chrome/installer/util/util_constants.h" | 
|   47 #include "content/public/browser/browser_thread.h" |   29 #include "content/public/browser/browser_thread.h" | 
|   48 #include "content/public/browser/notification_service.h" |  | 
|   49 #include "content/public/browser/user_metrics.h" |  | 
|   50 #include "google_update/google_update_idl.h" |   30 #include "google_update/google_update_idl.h" | 
|   51 #include "grit/chromium_strings.h" |  | 
|   52 #include "grit/generated_resources.h" |  | 
|   53 #include "grit/locale_settings.h" |   31 #include "grit/locale_settings.h" | 
|   54 #include "grit/theme_resources.h" |  | 
|   55 #include "ui/base/l10n/l10n_util.h" |   32 #include "ui/base/l10n/l10n_util.h" | 
|   56 #include "ui/base/layout.h" |  | 
|   57 #include "ui/base/ui_base_switches.h" |  | 
|   58 #include "ui/base/win/shell.h" |   33 #include "ui/base/win/shell.h" | 
|   59  |   34  | 
|   60 namespace { |   35 namespace { | 
|   61  |   36  | 
|   62 // Launches the setup exe with the given parameter/value on the command-line. |   37 // Launches the setup exe with the given parameter/value on the command-line. | 
|   63 // For non-metro Windows, it waits for its termination, returns its exit code |   38 // For non-metro Windows, it waits for its termination, returns its exit code | 
|   64 // in |*ret_code|, and returns true if the exit code is valid. |   39 // in |*ret_code|, and returns true if the exit code is valid. | 
|   65 // For metro Windows, it launches setup via ShellExecuteEx and returns in order |   40 // For metro Windows, it launches setup via ShellExecuteEx and returns in order | 
|   66 // to bounce the user back to the desktop, then returns immediately. |   41 // to bounce the user back to the desktop, then returns immediately. | 
|   67 bool LaunchSetupForEula(const base::FilePath::StringType& value, |   42 bool LaunchSetupForEula(const base::FilePath::StringType& value, | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  165 // accepted. |  140 // accepted. | 
|  166 bool CreateEULASentinel() { |  141 bool CreateEULASentinel() { | 
|  167   base::FilePath eula_sentinel; |  142   base::FilePath eula_sentinel; | 
|  168   if (!GetEULASentinelFilePath(&eula_sentinel)) |  143   if (!GetEULASentinelFilePath(&eula_sentinel)) | 
|  169     return false; |  144     return false; | 
|  170  |  145  | 
|  171   return (file_util::CreateDirectory(eula_sentinel.DirName()) && |  146   return (file_util::CreateDirectory(eula_sentinel.DirName()) && | 
|  172           file_util::WriteFile(eula_sentinel, "", 0) != -1); |  147           file_util::WriteFile(eula_sentinel, "", 0) != -1); | 
|  173 } |  148 } | 
|  174  |  149  | 
|  175 // This class is used by first_run::ImportSettings to determine when the import |  | 
|  176 // process has ended and what was the result of the operation as reported by |  | 
|  177 // the process exit code. This class executes in the context of the main chrome |  | 
|  178 // process. |  | 
|  179 class ImportProcessRunner : public base::win::ObjectWatcher::Delegate { |  | 
|  180  public: |  | 
|  181   // The constructor takes the importer process to watch and then it does a |  | 
|  182   // message loop blocking wait until the process ends. This object now owns |  | 
|  183   // the import_process handle. |  | 
|  184   explicit ImportProcessRunner(base::ProcessHandle import_process) |  | 
|  185       : import_process_(import_process), |  | 
|  186         exit_code_(content::RESULT_CODE_NORMAL_EXIT) { |  | 
|  187     watcher_.StartWatching(import_process, this); |  | 
|  188     MessageLoop::current()->Run(); |  | 
|  189   } |  | 
|  190   virtual ~ImportProcessRunner() { |  | 
|  191     ::CloseHandle(import_process_); |  | 
|  192   } |  | 
|  193   // Returns the child process exit code. There are 2 expected values: |  | 
|  194   // NORMAL_EXIT, or IMPORTER_HUNG. |  | 
|  195   int exit_code() const { return exit_code_; } |  | 
|  196  |  | 
|  197   // The child process has terminated. Find the exit code and quit the loop. |  | 
|  198   virtual void OnObjectSignaled(HANDLE object) OVERRIDE { |  | 
|  199     DCHECK(object == import_process_); |  | 
|  200     if (!::GetExitCodeProcess(import_process_, &exit_code_)) { |  | 
|  201       NOTREACHED(); |  | 
|  202     } |  | 
|  203     MessageLoop::current()->Quit(); |  | 
|  204   } |  | 
|  205  |  | 
|  206  private: |  | 
|  207   base::win::ObjectWatcher watcher_; |  | 
|  208   base::ProcessHandle import_process_; |  | 
|  209   DWORD exit_code_; |  | 
|  210 }; |  | 
|  211  |  | 
|  212 // Check every 3 seconds if the importer UI has hung. |  | 
|  213 const int kPollHangFrequency = 3000; |  | 
|  214  |  | 
|  215 // This class specializes on finding hung 'owned' windows. Unfortunately, the |  | 
|  216 // HungWindowDetector class cannot be used here because it assumes child |  | 
|  217 // windows and not owned top-level windows. |  | 
|  218 // This code is executed in the context of the main browser process and will |  | 
|  219 // terminate the importer process if it is hung. |  | 
|  220 class HungImporterMonitor : public WorkerThreadTicker::Callback { |  | 
|  221  public: |  | 
|  222   // The ctor takes the owner popup window and the process handle of the |  | 
|  223   // process to kill in case the popup or its owned active popup become |  | 
|  224   // unresponsive. |  | 
|  225   HungImporterMonitor(HWND owner_window, base::ProcessHandle import_process) |  | 
|  226       : owner_window_(owner_window), |  | 
|  227         import_process_(import_process), |  | 
|  228         ticker_(kPollHangFrequency) { |  | 
|  229     ticker_.RegisterTickHandler(this); |  | 
|  230     ticker_.Start(); |  | 
|  231   } |  | 
|  232   virtual ~HungImporterMonitor() { |  | 
|  233     ticker_.Stop(); |  | 
|  234     ticker_.UnregisterTickHandler(this); |  | 
|  235   } |  | 
|  236  |  | 
|  237  private: |  | 
|  238   virtual void OnTick() OVERRIDE { |  | 
|  239     if (!import_process_) |  | 
|  240       return; |  | 
|  241     // We find the top active popup that we own, this will be either the |  | 
|  242     // owner_window_ itself or the dialog window of the other process. In |  | 
|  243     // both cases it is worth hung testing because both windows share the |  | 
|  244     // same message queue and at some point the other window could be gone |  | 
|  245     // while the other process still not pumping messages. |  | 
|  246     HWND active_window = ::GetLastActivePopup(owner_window_); |  | 
|  247     if (::IsHungAppWindow(active_window) || ::IsHungAppWindow(owner_window_)) { |  | 
|  248       ::TerminateProcess(import_process_, chrome::RESULT_CODE_IMPORTER_HUNG); |  | 
|  249       import_process_ = NULL; |  | 
|  250     } |  | 
|  251   } |  | 
|  252  |  | 
|  253   HWND owner_window_; |  | 
|  254   base::ProcessHandle import_process_; |  | 
|  255   WorkerThreadTicker ticker_; |  | 
|  256   DISALLOW_COPY_AND_ASSIGN(HungImporterMonitor); |  | 
|  257 }; |  | 
|  258  |  | 
|  259 std::string EncodeImportParams(int importer_type, |  | 
|  260                                int options, |  | 
|  261                                bool skip_first_run_ui) { |  | 
|  262   return base::StringPrintf("%d@%d@%d", importer_type, options, |  | 
|  263                             skip_first_run_ui ? 1 : 0); |  | 
|  264 } |  | 
|  265  |  | 
|  266 bool DecodeImportParams(const std::string& encoded, |  | 
|  267                         int* importer_type, |  | 
|  268                         int* options, |  | 
|  269                         bool* skip_first_run_ui) { |  | 
|  270   std::vector<std::string> parts; |  | 
|  271   base::SplitString(encoded, '@', &parts); |  | 
|  272   int skip_first_run_ui_int; |  | 
|  273   if ((parts.size() != 3) || !base::StringToInt(parts[0], importer_type) || |  | 
|  274       !base::StringToInt(parts[1], options) || |  | 
|  275       !base::StringToInt(parts[2], &skip_first_run_ui_int)) |  | 
|  276     return false; |  | 
|  277   *skip_first_run_ui = !!skip_first_run_ui_int; |  | 
|  278   return true; |  | 
|  279 } |  | 
|  280  |  | 
|  281 #if !defined(USE_AURA) |  | 
|  282 // Imports browser items in this process. The browser and the items to |  | 
|  283 // import are encoded in the command line. |  | 
|  284 int ImportFromBrowser(Profile* profile, |  | 
|  285                       const CommandLine& cmdline) { |  | 
|  286   std::string import_info = cmdline.GetSwitchValueASCII(switches::kImport); |  | 
|  287   if (import_info.empty()) { |  | 
|  288     NOTREACHED(); |  | 
|  289     return false; |  | 
|  290   } |  | 
|  291   int importer_type = 0; |  | 
|  292   int items_to_import = 0; |  | 
|  293   bool skip_first_run_ui = false; |  | 
|  294   if (!DecodeImportParams(import_info, &importer_type, &items_to_import, |  | 
|  295                           &skip_first_run_ui)) { |  | 
|  296     NOTREACHED(); |  | 
|  297     return false; |  | 
|  298   } |  | 
|  299  |  | 
|  300   // Deletes itself. |  | 
|  301   ImporterHost* importer_host = new ImporterHost; |  | 
|  302  |  | 
|  303   scoped_refptr<ImporterList> importer_list(new ImporterList(NULL)); |  | 
|  304   importer_list->DetectSourceProfilesHack(); |  | 
|  305  |  | 
|  306   // If |skip_first_run_ui|, we run in headless mode.  This means that if |  | 
|  307   // there is user action required the import is automatically canceled. |  | 
|  308   if (skip_first_run_ui) |  | 
|  309     importer_host->set_headless(); |  | 
|  310  |  | 
|  311   first_run::internal::ImportEndedObserver observer; |  | 
|  312   importer_host->SetObserver(&observer); |  | 
|  313   importer_host->StartImportSettings( |  | 
|  314       importer_list->GetSourceProfileForImporterType(importer_type), profile, |  | 
|  315       static_cast<uint16>(items_to_import), new ProfileWriter(profile)); |  | 
|  316   // If the import process has not errored out, block on it. |  | 
|  317   if (!observer.ended()) { |  | 
|  318     observer.set_should_quit_message_loop(); |  | 
|  319     MessageLoop::current()->Run(); |  | 
|  320   } |  | 
|  321   // TODO(gab): This method will be go away as part of http://crbug.com/219419/, |  | 
|  322   // so it is fine to hardcode |RESULT_CODE_NORMAL_EXIT| here for now. |  | 
|  323   return content::RESULT_CODE_NORMAL_EXIT; |  | 
|  324 } |  | 
|  325 #endif  // !defined(USE_AURA) |  | 
|  326  |  | 
|  327 bool ImportSettingsWin(Profile* profile, |  | 
|  328                        int importer_type, |  | 
|  329                        int items_to_import, |  | 
|  330                        const base::FilePath& import_bookmarks_path, |  | 
|  331                        bool skip_first_run_ui) { |  | 
|  332   if (!items_to_import && import_bookmarks_path.empty()) { |  | 
|  333     return true; |  | 
|  334   } |  | 
|  335  |  | 
|  336   const CommandLine& cmdline = *CommandLine::ForCurrentProcess(); |  | 
|  337   base::FilePath chrome_exe(cmdline.GetProgram()); |  | 
|  338   // |chrome_exe| cannot be a relative path as chrome.exe already changed its |  | 
|  339   // CWD in LoadChromeWithDirectory(), making the relative path used on the |  | 
|  340   // command-line invalid. The base name is sufficient given chrome.exe is in |  | 
|  341   // the CWD. |  | 
|  342   if (!chrome_exe.IsAbsolute()) |  | 
|  343     chrome_exe = chrome_exe.BaseName(); |  | 
|  344   CommandLine import_cmd(chrome_exe); |  | 
|  345  |  | 
|  346   const char* kSwitchNames[] = { |  | 
|  347     switches::kUserDataDir, |  | 
|  348     switches::kChromeFrame, |  | 
|  349     switches::kCountry, |  | 
|  350   }; |  | 
|  351   import_cmd.CopySwitchesFrom(cmdline, kSwitchNames, arraysize(kSwitchNames)); |  | 
|  352  |  | 
|  353   // Allow tests to introduce additional switches. |  | 
|  354   import_cmd.AppendArguments(first_run::GetExtraArgumentsForImportProcess(), |  | 
|  355                              false); |  | 
|  356  |  | 
|  357   // Since ImportSettings is called before the local state is stored on disk |  | 
|  358   // we pass the language as an argument.  GetApplicationLocale checks the |  | 
|  359   // current command line as fallback. |  | 
|  360   import_cmd.AppendSwitchASCII(switches::kLang, |  | 
|  361                                g_browser_process->GetApplicationLocale()); |  | 
|  362  |  | 
|  363   if (items_to_import) { |  | 
|  364     import_cmd.AppendSwitchASCII(switches::kImport, |  | 
|  365         EncodeImportParams(importer_type, items_to_import, skip_first_run_ui)); |  | 
|  366   } |  | 
|  367  |  | 
|  368   if (!import_bookmarks_path.empty()) { |  | 
|  369     import_cmd.AppendSwitchPath(switches::kImportFromFile, |  | 
|  370                                 import_bookmarks_path); |  | 
|  371   } |  | 
|  372  |  | 
|  373   // The importer doesn't need to do any background networking tasks so disable |  | 
|  374   // them. |  | 
|  375   import_cmd.CommandLine::AppendSwitch(switches::kDisableBackgroundNetworking); |  | 
|  376  |  | 
|  377   // Time to launch the process that is going to do the import. |  | 
|  378   base::ProcessHandle import_process; |  | 
|  379   if (!base::LaunchProcess(import_cmd, base::LaunchOptions(), &import_process)) |  | 
|  380     return false; |  | 
|  381  |  | 
|  382   // We block inside the import_runner ctor, pumping messages until the |  | 
|  383   // importer process ends. This can happen either by completing the import |  | 
|  384   // or by hang_monitor killing it. |  | 
|  385   ImportProcessRunner import_runner(import_process); |  | 
|  386  |  | 
|  387   // Import process finished. Reload the prefs, because importer may set |  | 
|  388   // the pref value. |  | 
|  389   if (profile) |  | 
|  390     profile->GetPrefs()->ReloadPersistentPrefs(); |  | 
|  391  |  | 
|  392   return (import_runner.exit_code() == content::RESULT_CODE_NORMAL_EXIT); |  | 
|  393 } |  | 
|  394  |  | 
|  395 }  // namespace |  150 }  // namespace | 
|  396  |  151  | 
|  397 namespace first_run { |  152 namespace first_run { | 
|  398 namespace internal { |  153 namespace internal { | 
|  399  |  154  | 
|  400 void DoPostImportPlatformSpecificTasks(Profile* /* profile */) { |  155 void DoPostImportPlatformSpecificTasks(Profile* /* profile */) { | 
|  401   // Trigger the Active Setup command for system-level Chromes to finish |  156   // Trigger the Active Setup command for system-level Chromes to finish | 
|  402   // configuring this user's install (e.g. per-user shortcuts). |  157   // configuring this user's install (e.g. per-user shortcuts). | 
|  403   // Delay the task slightly to give Chrome launch I/O priority while also |  158   // Delay the task slightly to give Chrome launch I/O priority while also | 
|  404   // making sure shortcuts are created promptly to avoid annoying the user by |  159   // making sure shortcuts are created promptly to avoid annoying the user by | 
|  405   // re-creating shortcuts he previously deleted. |  160   // re-creating shortcuts he previously deleted. | 
|  406   static const int64 kTiggerActiveSetupDelaySeconds = 5; |  161   static const int64 kTiggerActiveSetupDelaySeconds = 5; | 
|  407   base::FilePath chrome_exe; |  162   base::FilePath chrome_exe; | 
|  408   if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { |  163   if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | 
|  409     NOTREACHED(); |  164     NOTREACHED(); | 
|  410   } else if (!InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) { |  165   } else if (!InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) { | 
|  411     content::BrowserThread::GetBlockingPool()->PostDelayedTask( |  166     content::BrowserThread::GetBlockingPool()->PostDelayedTask( | 
|  412         FROM_HERE, |  167         FROM_HERE, | 
|  413         base::Bind(&InstallUtil::TriggerActiveSetupCommand), |  168         base::Bind(&InstallUtil::TriggerActiveSetupCommand), | 
|  414         base::TimeDelta::FromSeconds(kTiggerActiveSetupDelaySeconds)); |  169         base::TimeDelta::FromSeconds(kTiggerActiveSetupDelaySeconds)); | 
|  415   } |  170   } | 
|  416 } |  171 } | 
|  417  |  172  | 
|  418 bool ImportSettings(Profile* profile, |  | 
|  419                     ImporterHost* importer_host, |  | 
|  420                     scoped_refptr<ImporterList> importer_list, |  | 
|  421                     int items_to_import) { |  | 
|  422   return ImportSettingsWin( |  | 
|  423       profile, |  | 
|  424       importer_list->GetSourceProfileAt(0).importer_type, |  | 
|  425       items_to_import, |  | 
|  426       base::FilePath(), |  | 
|  427       false); |  | 
|  428 } |  | 
|  429  |  | 
|  430 bool GetFirstRunSentinelFilePath(base::FilePath* path) { |  173 bool GetFirstRunSentinelFilePath(base::FilePath* path) { | 
|  431   return GetSentinelFilePath(chrome::kFirstRunSentinel, path); |  174   return GetSentinelFilePath(chrome::kFirstRunSentinel, path); | 
|  432 } |  175 } | 
|  433  |  176  | 
|  434 void SetImportPreferencesAndLaunchImport( |  | 
|  435     MasterPrefs* out_prefs, |  | 
|  436     installer::MasterPreferences* install_prefs) { |  | 
|  437   std::string import_bookmarks_path; |  | 
|  438   install_prefs->GetString( |  | 
|  439       installer::master_preferences::kDistroImportBookmarksFromFilePref, |  | 
|  440       &import_bookmarks_path); |  | 
|  441  |  | 
|  442   if (!IsOrganicFirstRun()) { |  | 
|  443     // If search engines aren't explicitly imported, don't import. |  | 
|  444     if (!(out_prefs->do_import_items & importer::SEARCH_ENGINES)) { |  | 
|  445       out_prefs->dont_import_items |= importer::SEARCH_ENGINES; |  | 
|  446     } |  | 
|  447     // If home page isn't explicitly imported, don't import. |  | 
|  448     if (!(out_prefs->do_import_items & importer::HOME_PAGE)) { |  | 
|  449       out_prefs->dont_import_items |= importer::HOME_PAGE; |  | 
|  450     } |  | 
|  451     // If history isn't explicitly forbidden, do import. |  | 
|  452     if (!(out_prefs->dont_import_items & importer::HISTORY)) { |  | 
|  453       out_prefs->do_import_items |= importer::HISTORY; |  | 
|  454     } |  | 
|  455   } |  | 
|  456  |  | 
|  457   if (out_prefs->do_import_items || !import_bookmarks_path.empty()) { |  | 
|  458     // There is something to import from the default browser. This launches |  | 
|  459     // the importer process and blocks until done or until it fails. |  | 
|  460     scoped_refptr<ImporterList> importer_list(new ImporterList(NULL)); |  | 
|  461     importer_list->DetectSourceProfilesHack(); |  | 
|  462     if (!ImportSettingsWin( |  | 
|  463         NULL, importer_list->GetSourceProfileAt(0).importer_type, |  | 
|  464         out_prefs->do_import_items, base::FilePath::FromWStringHack(UTF8ToWide( |  | 
|  465                                         import_bookmarks_path)), true)) { |  | 
|  466       LOG(WARNING) << "silent import failed"; |  | 
|  467     } |  | 
|  468   } |  | 
|  469 } |  | 
|  470  |  | 
|  471 bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { |  177 bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { | 
|  472   if (IsEULANotAccepted(install_prefs)) { |  178   if (IsEULANotAccepted(install_prefs)) { | 
|  473     // Show the post-installation EULA. This is done by setup.exe and the |  179     // Show the post-installation EULA. This is done by setup.exe and the | 
|  474     // result determines if we continue or not. We wait here until the user |  180     // result determines if we continue or not. We wait here until the user | 
|  475     // dismisses the dialog. |  181     // dismisses the dialog. | 
|  476  |  182  | 
|  477     // The actual eula text is in a resource in chrome. We extract it to |  183     // The actual eula text is in a resource in chrome. We extract it to | 
|  478     // a text file so setup.exe can use it as an inner frame. |  184     // a text file so setup.exe can use it as an inner frame. | 
|  479     base::FilePath inner_html; |  185     base::FilePath inner_html; | 
|  480     if (WriteEULAtoTempFile(&inner_html)) { |  186     if (WriteEULAtoTempFile(&inner_html)) { | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|  502 base::FilePath MasterPrefsPath() { |  208 base::FilePath MasterPrefsPath() { | 
|  503   // The standard location of the master prefs is next to the chrome binary. |  209   // The standard location of the master prefs is next to the chrome binary. | 
|  504   base::FilePath master_prefs; |  210   base::FilePath master_prefs; | 
|  505   if (!PathService::Get(base::DIR_EXE, &master_prefs)) |  211   if (!PathService::Get(base::DIR_EXE, &master_prefs)) | 
|  506     return base::FilePath(); |  212     return base::FilePath(); | 
|  507   return master_prefs.AppendASCII(installer::kDefaultMasterPrefs); |  213   return master_prefs.AppendASCII(installer::kDefaultMasterPrefs); | 
|  508 } |  214 } | 
|  509  |  215  | 
|  510 }  // namespace internal |  216 }  // namespace internal | 
|  511 }  // namespace first_run |  217 }  // namespace first_run | 
|  512  |  | 
|  513 namespace first_run { |  | 
|  514  |  | 
|  515 int ImportNow(Profile* profile, const CommandLine& cmdline) { |  | 
|  516   int return_code = internal::ImportBookmarkFromFileIfNeeded(profile, cmdline); |  | 
|  517 #if !defined(USE_AURA) |  | 
|  518   if (cmdline.HasSwitch(switches::kImport)) { |  | 
|  519     return_code = ImportFromBrowser(profile, cmdline); |  | 
|  520   } |  | 
|  521 #endif |  | 
|  522   return return_code; |  | 
|  523 } |  | 
|  524  |  | 
|  525 }  // namespace first_run |  | 
| OLD | NEW |