Home | History | Annotate | Download | only in importer
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/importer/external_process_importer_host.h"
      6 
      7 #include "base/bind.h"
      8 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/browser/importer/external_process_importer_client.h"
     11 #include "chrome/browser/importer/firefox_profile_lock.h"
     12 #include "chrome/browser/importer/importer_lock_dialog.h"
     13 #include "chrome/browser/importer/importer_progress_observer.h"
     14 #include "chrome/browser/importer/in_process_importer_bridge.h"
     15 #include "chrome/browser/search_engines/template_url_service.h"
     16 #include "chrome/browser/search_engines/template_url_service_factory.h"
     17 #include "components/bookmarks/browser/bookmark_model.h"
     18 #include "content/public/browser/browser_thread.h"
     19 
     20 using content::BrowserThread;
     21 
     22 ExternalProcessImporterHost::ExternalProcessImporterHost()
     23     : headless_(false),
     24       parent_window_(NULL),
     25       observer_(NULL),
     26       profile_(NULL),
     27       waiting_for_bookmarkbar_model_(false),
     28       installed_bookmark_observer_(false),
     29       is_source_readable_(true),
     30       client_(NULL),
     31       items_(0),
     32       cancelled_(false),
     33       weak_ptr_factory_(this) {
     34 }
     35 
     36 void ExternalProcessImporterHost::Cancel() {
     37   cancelled_ = true;
     38   // There is only a |client_| if the import was started.
     39   if (client_)
     40     client_->Cancel();
     41   NotifyImportEnded();  // Tells the observer that we're done, and deletes us.
     42 }
     43 
     44 void ExternalProcessImporterHost::StartImportSettings(
     45     const importer::SourceProfile& source_profile,
     46     Profile* target_profile,
     47     uint16 items,
     48     ProfileWriter* writer) {
     49   // We really only support importing from one host at a time.
     50   DCHECK(!profile_);
     51   DCHECK(target_profile);
     52 
     53   profile_ = target_profile;
     54   writer_ = writer;
     55   source_profile_ = source_profile;
     56   items_ = items;
     57 
     58   if (!CheckForFirefoxLock(source_profile)) {
     59     Cancel();
     60     return;
     61   }
     62 
     63   CheckForLoadedModels(items);
     64 
     65   LaunchImportIfReady();
     66 }
     67 
     68 void ExternalProcessImporterHost::NotifyImportStarted() {
     69   if (observer_)
     70     observer_->ImportStarted();
     71 }
     72 
     73 void ExternalProcessImporterHost::NotifyImportItemStarted(
     74     importer::ImportItem item) {
     75   if (observer_)
     76     observer_->ImportItemStarted(item);
     77 }
     78 
     79 void ExternalProcessImporterHost::NotifyImportItemEnded(
     80     importer::ImportItem item) {
     81   if (observer_)
     82     observer_->ImportItemEnded(item);
     83 }
     84 
     85 void ExternalProcessImporterHost::NotifyImportEnded() {
     86   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     87   firefox_lock_.reset();
     88   if (observer_)
     89     observer_->ImportEnded();
     90   delete this;
     91 }
     92 
     93 ExternalProcessImporterHost::~ExternalProcessImporterHost() {
     94   if (installed_bookmark_observer_) {
     95     DCHECK(profile_);
     96     BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this);
     97   }
     98 }
     99 
    100 void ExternalProcessImporterHost::LaunchImportIfReady() {
    101   if (waiting_for_bookmarkbar_model_ || template_service_subscription_.get() ||
    102       !is_source_readable_ || cancelled_)
    103     return;
    104 
    105   // This is the in-process half of the bridge, which catches data from the IPC
    106   // pipe and feeds it to the ProfileWriter. The external process half of the
    107   // bridge lives in the external process (see ProfileImportThread).
    108   // The ExternalProcessImporterClient created in the next line owns the bridge,
    109   // and will delete it.
    110   InProcessImporterBridge* bridge =
    111       new InProcessImporterBridge(writer_.get(),
    112                                   weak_ptr_factory_.GetWeakPtr());
    113   client_ = new ExternalProcessImporterClient(
    114       weak_ptr_factory_.GetWeakPtr(), source_profile_, items_, bridge);
    115   client_->Start();
    116 }
    117 
    118 void ExternalProcessImporterHost::BookmarkModelLoaded(BookmarkModel* model,
    119                                                       bool ids_reassigned) {
    120   DCHECK(model->loaded());
    121   model->RemoveObserver(this);
    122   waiting_for_bookmarkbar_model_ = false;
    123   installed_bookmark_observer_ = false;
    124 
    125   LaunchImportIfReady();
    126 }
    127 
    128 void ExternalProcessImporterHost::BookmarkModelBeingDeleted(
    129     BookmarkModel* model) {
    130   installed_bookmark_observer_ = false;
    131 }
    132 
    133 void ExternalProcessImporterHost::BookmarkModelChanged() {
    134 }
    135 
    136 void ExternalProcessImporterHost::OnTemplateURLServiceLoaded() {
    137   template_service_subscription_.reset();
    138   LaunchImportIfReady();
    139 }
    140 
    141 void ExternalProcessImporterHost::ShowWarningDialog() {
    142   DCHECK(!headless_);
    143   importer::ShowImportLockDialog(
    144       parent_window_,
    145       base::Bind(&ExternalProcessImporterHost::OnImportLockDialogEnd,
    146                  weak_ptr_factory_.GetWeakPtr()));
    147 }
    148 
    149 void ExternalProcessImporterHost::OnImportLockDialogEnd(bool is_continue) {
    150   if (is_continue) {
    151     // User chose to continue, then we check the lock again to make
    152     // sure that Firefox has been closed. Try to import the settings
    153     // if successful. Otherwise, show a warning dialog.
    154     firefox_lock_->Lock();
    155     if (firefox_lock_->HasAcquired()) {
    156       is_source_readable_ = true;
    157       LaunchImportIfReady();
    158     } else {
    159       ShowWarningDialog();
    160     }
    161   } else {
    162     NotifyImportEnded();
    163   }
    164 }
    165 
    166 bool ExternalProcessImporterHost::CheckForFirefoxLock(
    167     const importer::SourceProfile& source_profile) {
    168   if (source_profile.importer_type != importer::TYPE_FIREFOX)
    169     return true;
    170 
    171   DCHECK(!firefox_lock_.get());
    172   firefox_lock_.reset(new FirefoxProfileLock(source_profile.source_path));
    173   if (firefox_lock_->HasAcquired())
    174     return true;
    175 
    176   // If fail to acquire the lock, we set the source unreadable and
    177   // show a warning dialog, unless running without UI (in which case the import
    178   // must be aborted).
    179   is_source_readable_ = false;
    180   if (headless_)
    181     return false;
    182 
    183   ShowWarningDialog();
    184   return true;
    185 }
    186 
    187 void ExternalProcessImporterHost::CheckForLoadedModels(uint16 items) {
    188   // A target profile must be loaded by StartImportSettings().
    189   DCHECK(profile_);
    190 
    191   // BookmarkModel should be loaded before adding IE favorites. So we observe
    192   // the BookmarkModel if needed, and start the task after it has been loaded.
    193   if ((items & importer::FAVORITES) && !writer_->BookmarkModelIsLoaded()) {
    194     BookmarkModelFactory::GetForProfile(profile_)->AddObserver(this);
    195     waiting_for_bookmarkbar_model_ = true;
    196     installed_bookmark_observer_ = true;
    197   }
    198 
    199   // Observes the TemplateURLService if needed to import search engines from the
    200   // other browser. We also check to see if we're importing bookmarks because
    201   // we can import bookmark keywords from Firefox as search engines.
    202   if ((items & importer::SEARCH_ENGINES) || (items & importer::FAVORITES)) {
    203     if (!writer_->TemplateURLServiceIsLoaded()) {
    204       TemplateURLService* model =
    205           TemplateURLServiceFactory::GetForProfile(profile_);
    206       template_service_subscription_ = model->RegisterOnLoadedCallback(
    207           base::Bind(&ExternalProcessImporterHost::OnTemplateURLServiceLoaded,
    208                      weak_ptr_factory_.GetWeakPtr()));
    209       model->Load();
    210     }
    211   }
    212 }
    213