Home | History | Annotate | Download | only in importer
      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 "chrome/browser/importer/importer_host.h"
      6 
      7 #include "base/utf_string_conversions.h"
      8 #include "chrome/browser/bookmarks/bookmark_model.h"
      9 #include "chrome/browser/browser_process.h"
     10 #include "chrome/browser/importer/firefox_profile_lock.h"
     11 #include "chrome/browser/importer/importer.h"
     12 #include "chrome/browser/importer/importer_lock_dialog.h"
     13 #include "chrome/browser/importer/importer_progress_observer.h"
     14 #include "chrome/browser/importer/importer_type.h"
     15 #include "chrome/browser/importer/in_process_importer_bridge.h"
     16 #include "chrome/browser/importer/toolbar_importer_utils.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/browser/search_engines/template_url.h"
     19 #include "chrome/browser/search_engines/template_url_model.h"
     20 #include "chrome/browser/ui/browser_list.h"
     21 #include "content/browser/browser_thread.h"
     22 #include "content/common/notification_source.h"
     23 #include "grit/generated_resources.h"
     24 #include "ui/base/l10n/l10n_util.h"
     25 
     26 #if defined(OS_WIN)
     27 // TODO(port): Port this file.
     28 #include "ui/base/message_box_win.h"
     29 #endif
     30 
     31 ImporterHost::ImporterHost()
     32     : profile_(NULL),
     33       task_(NULL),
     34       importer_(NULL),
     35       waiting_for_bookmarkbar_model_(false),
     36       installed_bookmark_observer_(false),
     37       is_source_readable_(true),
     38       headless_(false),
     39       parent_window_(NULL),
     40       observer_(NULL) {
     41 }
     42 
     43 void ImporterHost::ShowWarningDialog() {
     44   if (headless_)
     45     OnImportLockDialogEnd(false);
     46   else
     47     importer::ShowImportLockDialog(parent_window_, this);
     48 }
     49 
     50 void ImporterHost::OnImportLockDialogEnd(bool is_continue) {
     51   if (is_continue) {
     52     // User chose to continue, then we check the lock again to make
     53     // sure that Firefox has been closed. Try to import the settings
     54     // if successful. Otherwise, show a warning dialog.
     55     firefox_lock_->Lock();
     56     if (firefox_lock_->HasAcquired()) {
     57       is_source_readable_ = true;
     58       InvokeTaskIfDone();
     59     } else {
     60       ShowWarningDialog();
     61     }
     62   } else {
     63     // User chose to skip the import process. We should delete
     64     // the task and notify the ImporterHost to finish.
     65     delete task_;
     66     task_ = NULL;
     67     importer_ = NULL;
     68     NotifyImportEnded();
     69   }
     70 }
     71 
     72 void ImporterHost::SetObserver(importer::ImporterProgressObserver* observer) {
     73   observer_ = observer;
     74 }
     75 
     76 void ImporterHost::NotifyImportStarted() {
     77   if (observer_)
     78     observer_->ImportStarted();
     79 }
     80 
     81 void ImporterHost::NotifyImportItemStarted(importer::ImportItem item) {
     82   if (observer_)
     83     observer_->ImportItemStarted(item);
     84 }
     85 
     86 void ImporterHost::NotifyImportItemEnded(importer::ImportItem item) {
     87   if (observer_)
     88     observer_->ImportItemEnded(item);
     89 }
     90 
     91 void ImporterHost::NotifyImportEnded() {
     92   firefox_lock_.reset();  // Release the Firefox profile lock.
     93   if (observer_)
     94     observer_->ImportEnded();
     95   Release();
     96 }
     97 
     98 void ImporterHost::StartImportSettings(
     99     const importer::SourceProfile& source_profile,
    100     Profile* target_profile,
    101     uint16 items,
    102     ProfileWriter* writer,
    103     bool first_run) {
    104   // We really only support importing from one host at a time.
    105   DCHECK(!profile_);
    106 
    107   profile_ = target_profile;
    108   // Preserves the observer and creates a task, since we do async import so that
    109   // it doesn't block the UI. When the import is complete, observer will be
    110   // notified.
    111   writer_ = writer;
    112   importer_ = importer::CreateImporterByType(source_profile.importer_type);
    113   // If we fail to create the Importer, exit, as we cannot do anything.
    114   if (!importer_) {
    115     NotifyImportEnded();
    116     return;
    117   }
    118 
    119   importer_->AddRef();
    120   importer_->set_import_to_bookmark_bar(ShouldImportToBookmarkBar(first_run));
    121   importer_->set_bookmark_bar_disabled(first_run);
    122 
    123   scoped_refptr<InProcessImporterBridge> bridge(
    124       new InProcessImporterBridge(writer_.get(), this));
    125   task_ = NewRunnableMethod(
    126       importer_, &Importer::StartImport, source_profile, items, bridge);
    127 
    128   CheckForFirefoxLock(source_profile, items, first_run);
    129 
    130 #if defined(OS_WIN)
    131   // For google toolbar import, we need the user to log in and store their GAIA
    132   // credentials.
    133   if (source_profile.importer_type == importer::GOOGLE_TOOLBAR5) {
    134     if (!toolbar_importer_utils::IsGoogleGAIACookieInstalled()) {
    135       ui::MessageBox(
    136           NULL,
    137           UTF16ToWide(l10n_util::GetStringUTF16(
    138               IDS_IMPORTER_GOOGLE_LOGIN_TEXT)).c_str(),
    139           L"",
    140           MB_OK | MB_TOPMOST);
    141 
    142       GURL url("https://www.google.com/accounts/ServiceLogin");
    143       BrowserList::GetLastActive()->AddSelectedTabWithURL(
    144           url, PageTransition::TYPED);
    145 
    146       MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
    147           this, &ImporterHost::OnImportLockDialogEnd, false));
    148 
    149       is_source_readable_ = false;
    150     }
    151   }
    152 #endif
    153 
    154   CheckForLoadedModels(items);
    155   AddRef();
    156   InvokeTaskIfDone();
    157 }
    158 
    159 void ImporterHost::Cancel() {
    160   if (importer_)
    161     importer_->Cancel();
    162 }
    163 
    164 ImporterHost::~ImporterHost() {
    165   if (NULL != importer_)
    166     importer_->Release();
    167 
    168   if (installed_bookmark_observer_) {
    169     DCHECK(profile_);  // Only way for waiting_for_bookmarkbar_model_ to be true
    170                        // is if we have a profile.
    171     profile_->GetBookmarkModel()->RemoveObserver(this);
    172   }
    173 }
    174 
    175 bool ImporterHost::ShouldImportToBookmarkBar(bool first_run) {
    176   bool import_to_bookmark_bar = first_run;
    177   if (profile_ && profile_->GetBookmarkModel()->IsLoaded()) {
    178     import_to_bookmark_bar = (!profile_->GetBookmarkModel()->HasBookmarks());
    179   }
    180   return import_to_bookmark_bar;
    181 }
    182 
    183 void ImporterHost::CheckForFirefoxLock(
    184     const importer::SourceProfile& source_profile,
    185     uint16 items,
    186     bool first_run) {
    187   if (source_profile.importer_type == importer::FIREFOX2 ||
    188       source_profile.importer_type == importer::FIREFOX3) {
    189     DCHECK(!firefox_lock_.get());
    190     firefox_lock_.reset(new FirefoxProfileLock(source_profile.source_path));
    191     if (!firefox_lock_->HasAcquired()) {
    192       // If fail to acquire the lock, we set the source unreadable and
    193       // show a warning dialog, unless running without UI.
    194       is_source_readable_ = false;
    195       ShowWarningDialog();
    196     }
    197   }
    198 }
    199 
    200 void ImporterHost::CheckForLoadedModels(uint16 items) {
    201   // BookmarkModel should be loaded before adding IE favorites. So we observe
    202   // the BookmarkModel if needed, and start the task after it has been loaded.
    203   if ((items & importer::FAVORITES) && !writer_->BookmarkModelIsLoaded()) {
    204     profile_->GetBookmarkModel()->AddObserver(this);
    205     waiting_for_bookmarkbar_model_ = true;
    206     installed_bookmark_observer_ = true;
    207   }
    208 
    209   // Observes the TemplateURLModel if needed to import search engines from the
    210   // other browser. We also check to see if we're importing bookmarks because
    211   // we can import bookmark keywords from Firefox as search engines.
    212   if ((items & importer::SEARCH_ENGINES) || (items & importer::FAVORITES)) {
    213     if (!writer_->TemplateURLModelIsLoaded()) {
    214       TemplateURLModel* model = profile_->GetTemplateURLModel();
    215       registrar_.Add(this, NotificationType::TEMPLATE_URL_MODEL_LOADED,
    216                      Source<TemplateURLModel>(model));
    217       model->Load();
    218     }
    219   }
    220 }
    221 
    222 void ImporterHost::InvokeTaskIfDone() {
    223   if (waiting_for_bookmarkbar_model_ || !registrar_.IsEmpty() ||
    224       !is_source_readable_)
    225     return;
    226   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, task_);
    227 }
    228 
    229 void ImporterHost::Loaded(BookmarkModel* model) {
    230   DCHECK(model->IsLoaded());
    231   model->RemoveObserver(this);
    232   waiting_for_bookmarkbar_model_ = false;
    233   installed_bookmark_observer_ = false;
    234 
    235   importer_->set_import_to_bookmark_bar(!model->HasBookmarks());
    236   InvokeTaskIfDone();
    237 }
    238 
    239 void ImporterHost::BookmarkModelBeingDeleted(BookmarkModel* model) {
    240   installed_bookmark_observer_ = false;
    241 }
    242 
    243 void ImporterHost::BookmarkModelChanged() {
    244 }
    245 
    246 void ImporterHost::Observe(NotificationType type,
    247                            const NotificationSource& source,
    248                            const NotificationDetails& details) {
    249   DCHECK(type == NotificationType::TEMPLATE_URL_MODEL_LOADED);
    250   registrar_.RemoveAll();
    251   InvokeTaskIfDone();
    252 }
    253