| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/importer/external_process_importer_host.h" |
| |
| #include "base/bind.h" |
| #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| #include "chrome/browser/importer/external_process_importer_client.h" |
| #include "chrome/browser/importer/firefox_profile_lock.h" |
| #include "chrome/browser/importer/importer_lock_dialog.h" |
| #include "chrome/browser/importer/importer_progress_observer.h" |
| #include "chrome/browser/importer/in_process_importer_bridge.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/search_engines/template_url_service_factory.h" |
| #include "components/bookmarks/browser/bookmark_model.h" |
| #include "components/search_engines/template_url_service.h" |
| #include "content/public/browser/browser_thread.h" |
| |
| using bookmarks::BookmarkModel; |
| using content::BrowserThread; |
| |
| ExternalProcessImporterHost::ExternalProcessImporterHost() |
| : headless_(false), |
| parent_window_(NULL), |
| observer_(NULL), |
| profile_(NULL), |
| waiting_for_bookmarkbar_model_(false), |
| installed_bookmark_observer_(false), |
| is_source_readable_(true), |
| client_(NULL), |
| items_(0), |
| cancelled_(false), |
| weak_ptr_factory_(this) { |
| } |
| |
| void ExternalProcessImporterHost::Cancel() { |
| cancelled_ = true; |
| // There is only a |client_| if the import was started. |
| if (client_) |
| client_->Cancel(); |
| NotifyImportEnded(); // Tells the observer that we're done, and deletes us. |
| } |
| |
| void ExternalProcessImporterHost::StartImportSettings( |
| const importer::SourceProfile& source_profile, |
| Profile* target_profile, |
| uint16_t items, |
| ProfileWriter* writer) { |
| // We really only support importing from one host at a time. |
| DCHECK(!profile_); |
| DCHECK(target_profile); |
| |
| profile_ = target_profile; |
| writer_ = writer; |
| source_profile_ = source_profile; |
| items_ = items; |
| |
| if (!CheckForFirefoxLock(source_profile)) { |
| Cancel(); |
| return; |
| } |
| |
| CheckForLoadedModels(items); |
| |
| LaunchImportIfReady(); |
| } |
| |
| void ExternalProcessImporterHost::NotifyImportStarted() { |
| if (observer_) |
| observer_->ImportStarted(); |
| } |
| |
| void ExternalProcessImporterHost::NotifyImportItemStarted( |
| importer::ImportItem item) { |
| if (observer_) |
| observer_->ImportItemStarted(item); |
| } |
| |
| void ExternalProcessImporterHost::NotifyImportItemEnded( |
| importer::ImportItem item) { |
| if (observer_) |
| observer_->ImportItemEnded(item); |
| } |
| |
| void ExternalProcessImporterHost::NotifyImportEnded() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| firefox_lock_.reset(); |
| if (observer_) |
| observer_->ImportEnded(); |
| delete this; |
| } |
| |
| ExternalProcessImporterHost::~ExternalProcessImporterHost() { |
| if (installed_bookmark_observer_) { |
| DCHECK(profile_); |
| BookmarkModelFactory::GetForBrowserContext(profile_)->RemoveObserver(this); |
| } |
| } |
| |
| void ExternalProcessImporterHost::LaunchImportIfReady() { |
| if (waiting_for_bookmarkbar_model_ || template_service_subscription_.get() || |
| !is_source_readable_ || cancelled_) |
| return; |
| |
| // This is the in-process half of the bridge, which catches data from the IPC |
| // pipe and feeds it to the ProfileWriter. The external process half of the |
| // bridge lives in the external process (see ProfileImportThread). |
| // The ExternalProcessImporterClient created in the next line owns the bridge, |
| // and will delete it. |
| InProcessImporterBridge* bridge = |
| new InProcessImporterBridge(writer_.get(), |
| weak_ptr_factory_.GetWeakPtr()); |
| client_ = new ExternalProcessImporterClient( |
| weak_ptr_factory_.GetWeakPtr(), source_profile_, items_, bridge); |
| client_->Start(); |
| } |
| |
| void ExternalProcessImporterHost::BookmarkModelLoaded(BookmarkModel* model, |
| bool ids_reassigned) { |
| DCHECK(model->loaded()); |
| model->RemoveObserver(this); |
| waiting_for_bookmarkbar_model_ = false; |
| installed_bookmark_observer_ = false; |
| |
| LaunchImportIfReady(); |
| } |
| |
| void ExternalProcessImporterHost::BookmarkModelBeingDeleted( |
| BookmarkModel* model) { |
| installed_bookmark_observer_ = false; |
| } |
| |
| void ExternalProcessImporterHost::BookmarkModelChanged() { |
| } |
| |
| void ExternalProcessImporterHost::OnTemplateURLServiceLoaded() { |
| template_service_subscription_.reset(); |
| LaunchImportIfReady(); |
| } |
| |
| void ExternalProcessImporterHost::ShowWarningDialog() { |
| DCHECK(!headless_); |
| importer::ShowImportLockDialog( |
| parent_window_, |
| base::Bind(&ExternalProcessImporterHost::OnImportLockDialogEnd, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void ExternalProcessImporterHost::OnImportLockDialogEnd(bool is_continue) { |
| if (is_continue) { |
| // User chose to continue, then we check the lock again to make |
| // sure that Firefox has been closed. Try to import the settings |
| // if successful. Otherwise, show a warning dialog. |
| firefox_lock_->Lock(); |
| if (firefox_lock_->HasAcquired()) { |
| is_source_readable_ = true; |
| LaunchImportIfReady(); |
| } else { |
| ShowWarningDialog(); |
| } |
| } else { |
| NotifyImportEnded(); |
| } |
| } |
| |
| bool ExternalProcessImporterHost::CheckForFirefoxLock( |
| const importer::SourceProfile& source_profile) { |
| if (source_profile.importer_type != importer::TYPE_FIREFOX) |
| return true; |
| |
| DCHECK(!firefox_lock_.get()); |
| firefox_lock_.reset(new FirefoxProfileLock(source_profile.source_path)); |
| if (firefox_lock_->HasAcquired()) |
| return true; |
| |
| // If fail to acquire the lock, we set the source unreadable and |
| // show a warning dialog, unless running without UI (in which case the import |
| // must be aborted). |
| is_source_readable_ = false; |
| if (headless_) |
| return false; |
| |
| ShowWarningDialog(); |
| return true; |
| } |
| |
| void ExternalProcessImporterHost::CheckForLoadedModels(uint16_t items) { |
| // A target profile must be loaded by StartImportSettings(). |
| DCHECK(profile_); |
| |
| // BookmarkModel should be loaded before adding IE favorites. So we observe |
| // the BookmarkModel if needed, and start the task after it has been loaded. |
| if ((items & importer::FAVORITES) && !writer_->BookmarkModelIsLoaded()) { |
| BookmarkModelFactory::GetForBrowserContext(profile_)->AddObserver(this); |
| waiting_for_bookmarkbar_model_ = true; |
| installed_bookmark_observer_ = true; |
| } |
| |
| // Observes the TemplateURLService if needed to import search engines from the |
| // other browser. We also check to see if we're importing bookmarks because |
| // we can import bookmark keywords from Firefox as search engines. |
| if ((items & importer::SEARCH_ENGINES) || (items & importer::FAVORITES)) { |
| if (!writer_->TemplateURLServiceIsLoaded()) { |
| TemplateURLService* model = |
| TemplateURLServiceFactory::GetForProfile(profile_); |
| template_service_subscription_ = model->RegisterOnLoadedCallback( |
| base::Bind(&ExternalProcessImporterHost::OnTemplateURLServiceLoaded, |
| weak_ptr_factory_.GetWeakPtr())); |
| model->Load(); |
| } |
| } |
| } |