importer.h revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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#ifndef CHROME_BROWSER_IMPORTER_IMPORTER_H_ 6#define CHROME_BROWSER_IMPORTER_IMPORTER_H_ 7#pragma once 8 9#include <string> 10#include <vector> 11 12#include "build/build_config.h" 13 14#include "base/basictypes.h" 15#include "base/ref_counted.h" 16#include "base/scoped_ptr.h" 17#include "chrome/browser/bookmarks/bookmark_model_observer.h" 18#include "chrome/browser/importer/importer_data_types.h" 19#include "chrome/browser/importer/importer_list.h" 20#include "chrome/browser/importer/profile_writer.h" 21#include "chrome/browser/profile_import_process_host.h" 22#include "chrome/common/notification_observer.h" 23#include "chrome/common/notification_registrar.h" 24#include "ui/gfx/native_widget_types.h" 25 26using importer::ImportItem; 27using importer::ProfileInfo; 28 29class ExternalProcessImporterClient; 30class ImporterBridge; 31class InProcessImporterBridge; 32class GURL; 33class Profile; 34class Task; 35class TemplateURL; 36 37struct IE7PasswordInfo; 38 39namespace history { 40struct ImportedFavIconUsage; 41class URLRow; 42} 43 44namespace webkit_glue { 45struct PasswordForm; 46} 47 48class FirefoxProfileLock; 49class Importer; 50 51// This class hosts the importers. It enumerates profiles from other 52// browsers dynamically, and controls the process of importing. When 53// the import process is done, ImporterHost deletes itself. 54class ImporterHost : public base::RefCountedThreadSafe<ImporterHost>, 55 public BookmarkModelObserver, 56 public NotificationObserver { 57 public: 58 // An interface which an object can implement to be notified of events during 59 // the import process. 60 class Observer { 61 public: 62 // Invoked when data for the specified item is about to be collected. 63 virtual void ImportItemStarted(importer::ImportItem item) = 0; 64 65 // Invoked when data for the specified item has been collected from the 66 // source profile and is now ready for further processing. 67 virtual void ImportItemEnded(importer::ImportItem item) = 0; 68 69 // Invoked when the import begins. 70 virtual void ImportStarted() = 0; 71 72 // Invoked when the source profile has been imported. 73 virtual void ImportEnded() = 0; 74 75 protected: 76 virtual ~Observer() {} 77 }; 78 79 ImporterHost(); 80 81 // BookmarkModelObserver implementation. 82 virtual void Loaded(BookmarkModel* model); 83 virtual void BookmarkNodeMoved(BookmarkModel* model, 84 const BookmarkNode* old_parent, 85 int old_index, 86 const BookmarkNode* new_parent, 87 int new_index) {} 88 virtual void BookmarkNodeAdded(BookmarkModel* model, 89 const BookmarkNode* parent, 90 int index) {} 91 virtual void BookmarkNodeRemoved(BookmarkModel* model, 92 const BookmarkNode* parent, 93 int old_index, 94 const BookmarkNode* node) {} 95 virtual void BookmarkNodeChanged(BookmarkModel* model, 96 const BookmarkNode* node) {} 97 virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, 98 const BookmarkNode* node) {} 99 virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, 100 const BookmarkNode* node) {} 101 virtual void BookmarkModelBeingDeleted(BookmarkModel* model); 102 103 // NotificationObserver implementation. Called when TemplateURLModel has been 104 // loaded. 105 virtual void Observe(NotificationType type, 106 const NotificationSource& source, 107 const NotificationDetails& details); 108 109 // ShowWarningDialog() asks user to close the application that is owning the 110 // lock. They can retry or skip the importing process. 111 void ShowWarningDialog(); 112 113 // OnLockViewEnd() is called when user end the dialog by clicking a push 114 // button. |is_continue| is true when user clicked the "Continue" button. 115 void OnLockViewEnd(bool is_continue); 116 117 // Starts the process of importing the settings and data depending on what 118 // the user selected. 119 // |profile_info| -- browser profile to import. 120 // |target_profile| -- profile to import into. 121 // |items| -- specifies which data to import (mask of ImportItems). 122 // |writer| -- called to actually write data back to the profile. 123 // |first_run| -- true if this method is being called during first run. 124 virtual void StartImportSettings(const importer::ProfileInfo& profile_info, 125 Profile* target_profile, 126 uint16 items, 127 ProfileWriter* writer, 128 bool first_run); 129 130 // Cancel import. 131 virtual void Cancel(); 132 133 // When in headless mode, the importer will not show the warning dialog and 134 // the outcome is as if the user had canceled the import operation. 135 void set_headless() { 136 headless_ = true; 137 } 138 139 bool is_headless() const { 140 return headless_; 141 } 142 143 void set_parent_window(gfx::NativeWindow parent_window) { 144 parent_window_ = parent_window; 145 } 146 147 void SetObserver(Observer* observer); 148 149 // A series of functions invoked at the start, during and end of the end 150 // of the import process. The middle functions are notifications that the 151 // harvesting of a particular source of data (specified by |item|) is under 152 // way. 153 virtual void ImportStarted(); 154 virtual void ImportItemStarted(importer::ImportItem item); 155 virtual void ImportItemEnded(importer::ImportItem item); 156 virtual void ImportEnded(); 157 158 protected: 159 friend class base::RefCountedThreadSafe<ImporterHost>; 160 161 ~ImporterHost(); 162 163 // Returns true if importer should import to bookmark bar. 164 bool ShouldImportToBookmarkBar(bool first_run); 165 166 // Make sure that Firefox isn't running, if import browser is Firefox. Show 167 // the user a dialog to notify that they need to close FF to continue. 168 // |profile_info| holds the browser type and source path. 169 // |items| is a mask of all ImportItems that are to be imported. 170 // |first_run| is true if this method is being called during first run. 171 void CheckForFirefoxLock(const importer::ProfileInfo& profile_info, 172 uint16 items, bool first_run); 173 174 // Make sure BookmarkModel and TemplateURLModel are loaded before import 175 // process starts, if bookmarks and / or search engines are among the items 176 // which are to be imported. 177 void CheckForLoadedModels(uint16 items); 178 179 // Profile we're importing from. 180 Profile* profile_; 181 182 Observer* observer_; 183 184 // TODO(mirandac): task_ and importer_ should be private. Can't just put 185 // them there without changing the order of construct/destruct, so do this 186 // after main CL has been committed. 187 // The task is the process of importing settings from other browsers. 188 Task* task_; 189 190 // The importer used in the task; 191 Importer* importer_; 192 193 // Writes data from the importer back to the profile. 194 scoped_refptr<ProfileWriter> writer_; 195 196 // True if we're waiting for the model to finish loading. 197 bool waiting_for_bookmarkbar_model_; 198 199 // Have we installed a listener on the bookmark model? 200 bool installed_bookmark_observer_; 201 202 // True if source profile is readable. 203 bool is_source_readable_; 204 205 // True if UI is not to be shown. 206 bool headless_; 207 208 // Receives notification when the TemplateURLModel has loaded. 209 NotificationRegistrar registrar_; 210 211 // Parent Window to use when showing any modal dialog boxes. 212 gfx::NativeWindow parent_window_; 213 214 // Firefox profile lock. 215 scoped_ptr<FirefoxProfileLock> firefox_lock_; 216 217 private: 218 // Launches the thread that starts the import task, unless bookmark or 219 // template model are not yet loaded. If load is not detected, this method 220 // will be called when the loading observer sees that model loading is 221 // complete. 222 virtual void InvokeTaskIfDone(); 223 224 DISALLOW_COPY_AND_ASSIGN(ImporterHost); 225}; 226 227// This class manages the import process. It creates the in-process half of the 228// importer bridge and the external process importer client. 229class ExternalProcessImporterHost : public ImporterHost { 230 public: 231 ExternalProcessImporterHost(); 232 233 // Called when the BookmarkModel has finished loading. Calls InvokeTaskIfDone 234 // to start importing. 235 virtual void Loaded(BookmarkModel* model); 236 237 // Methods inherited from ImporterHost. 238 virtual void StartImportSettings(const importer::ProfileInfo& profile_info, 239 Profile* target_profile, 240 uint16 items, 241 ProfileWriter* writer, 242 bool first_run); 243 244 virtual void Cancel(); 245 246 protected: 247 // Launches the ExternalProcessImporterClient unless bookmark or template 248 // model are not yet loaded. If load is not detected, this method will be 249 // called when the loading observer sees that model loading is complete. 250 virtual void InvokeTaskIfDone(); 251 252 private: 253 // Used to pass notifications from the browser side to the external process. 254 ExternalProcessImporterClient* client_; 255 256 // Data for the external importer: ------------------------------------------ 257 // Information about a profile needed for importing. 258 const importer::ProfileInfo* profile_info_; 259 260 // Mask of items to be imported (see importer::ImportItem). 261 uint16 items_; 262 263 // Whether to import bookmarks to the bookmark bar. 264 bool import_to_bookmark_bar_; 265 266 // True if the import process has been cancelled. 267 bool cancelled_; 268 269 // True if the import process has been launched. This prevents race 270 // conditions on import cancel. 271 bool import_process_launched_; 272 273 // End of external importer data -------------------------------------------- 274 275 DISALLOW_COPY_AND_ASSIGN(ExternalProcessImporterHost); 276}; 277 278// This class is the client for the ProfileImportProcessHost. It collects 279// notifications from this process host and feeds data back to the importer 280// host, who actually does the writing. 281class ExternalProcessImporterClient 282 : public ProfileImportProcessHost::ImportProcessClient { 283 public: 284 ExternalProcessImporterClient(ExternalProcessImporterHost* importer_host, 285 const importer::ProfileInfo& profile_info, 286 int items, 287 InProcessImporterBridge* bridge, 288 bool import_to_bookmark_bar); 289 290 ~ExternalProcessImporterClient(); 291 292 // Launches the task to start the external process. 293 virtual void Start(); 294 295 // Creates a new ProfileImportProcessHost, which launches the import process. 296 virtual void StartProcessOnIOThread(ResourceDispatcherHost* rdh, 297 BrowserThread::ID thread_id); 298 299 // Called by the ExternalProcessImporterHost on import cancel. 300 virtual void Cancel(); 301 302 // Cancel import process on IO thread. 303 void CancelImportProcessOnIOThread(); 304 305 // Report item completely downloaded on IO thread. 306 void NotifyItemFinishedOnIOThread(importer::ImportItem import_item); 307 308 // Cancel import on process crash. 309 virtual void OnProcessCrashed(int exit_code); 310 311 // Notifies the importerhost that import has finished, and calls Release(). 312 void Cleanup(); 313 314 // ProfileImportProcessHost messages ---------------------------------------- 315 // The following methods are called by ProfileImportProcessHost when the 316 // corresponding message has been received from the import process. 317 virtual void OnImportStart(); 318 virtual void OnImportFinished(bool succeeded, std::string error_msg); 319 virtual void OnImportItemStart(int item_data); 320 virtual void OnImportItemFinished(int item_data); 321 322 // Called on first message received when importing history; gives total 323 // number of rows to be imported. 324 virtual void OnHistoryImportStart(size_t total_history_rows_count); 325 326 // Called when a group of URLRows has been received. 327 // The source is passed with history::VisitSource type. 328 virtual void OnHistoryImportGroup( 329 const std::vector<history::URLRow> &history_rows_group, 330 int visit_source); 331 332 // Called when the home page has been received. 333 virtual void OnHomePageImportReady(const GURL& home_page); 334 335 // First message received when importing bookmarks. 336 // |first_folder_name| can be NULL. 337 // |options| is described in ProfileWriter::BookmarkOptions. 338 // |total_bookmarks_count| is the total number of bookmarks to be imported. 339 virtual void OnBookmarksImportStart( 340 const std::wstring first_folder_name, 341 int options, size_t total_bookmarks_count); 342 343 // Called when a group of bookmarks has been received. 344 virtual void OnBookmarksImportGroup( 345 const std::vector<ProfileWriter::BookmarkEntry>& bookmarks_group); 346 347 // First message received when importing favicons. |total_fav_icons_size| 348 // gives the total number of fav icons to be imported. 349 virtual void OnFavIconsImportStart(size_t total_fav_icons_count); 350 351 // Called when a group of favicons has been received. 352 virtual void OnFavIconsImportGroup( 353 const std::vector<history::ImportedFavIconUsage>& fav_icons_group); 354 355 // Called when the passwordform has been received. 356 virtual void OnPasswordFormImportReady( 357 const webkit_glue::PasswordForm& form); 358 359 // Called when search engines have been received. 360 virtual void OnKeywordsImportReady( 361 const std::vector<TemplateURL>& template_urls, 362 int default_keyword_index, bool unique_on_host_and_path); 363 364 // End ProfileImportProcessHost messages ------------------------------------ 365 366 private: 367 // These variables store data being collected from the importer until the 368 // entire group has been collected and is ready to be written to the profile. 369 std::vector<history::URLRow> history_rows_; 370 std::vector<ProfileWriter::BookmarkEntry> bookmarks_; 371 std::vector<history::ImportedFavIconUsage> fav_icons_; 372 373 // Usually some variation on IDS_BOOKMARK_GROUP_...; the name of the folder 374 // under which imported bookmarks will be placed. 375 std::wstring bookmarks_first_folder_name_; 376 377 // Determines how bookmarks should be added (ProfileWriter::BookmarkOptions). 378 int bookmarks_options_; 379 380 // Total number of bookmarks to import. 381 size_t total_bookmarks_count_; 382 383 // Total number of history items to import. 384 size_t total_history_rows_count_; 385 386 // Total number of fav icons to import. 387 size_t total_fav_icons_count_; 388 389 // Notifications received from the ProfileImportProcessHost are passed back 390 // to process_importer_host_, which calls the ProfileWriter to record the 391 // import data. When the import process is done, process_importer_host_ 392 // deletes itself. 393 ExternalProcessImporterHost* process_importer_host_; 394 395 // Handles sending messages to the external process. Deletes itself when 396 // the external process dies (see ChildProcessHost::OnChildDied). 397 ProfileImportProcessHost* profile_import_process_host_; 398 399 // Data to be passed from the importer host to the external importer. 400 const importer::ProfileInfo& profile_info_; 401 int items_; 402 bool import_to_bookmark_bar_; 403 404 // Takes import data coming over IPC and delivers it to be written by the 405 // ProfileWriter. Released by ExternalProcessImporterClient in its 406 // destructor. 407 InProcessImporterBridge* bridge_; 408 409 // True if import process has been cancelled. 410 bool cancelled_; 411 412 DISALLOW_COPY_AND_ASSIGN(ExternalProcessImporterClient); 413}; 414 415// The base class of all importers. 416class Importer : public base::RefCountedThreadSafe<Importer> { 417 public: 418 // All importers should implement this method by adding their 419 // import logic. And it will be run in file thread by ImporterHost. 420 // 421 // Since we do async import, the importer should invoke 422 // ImporterHost::Finished() to notify its host that import 423 // stuff have been finished. 424 virtual void StartImport(const importer::ProfileInfo& profile_info, 425 uint16 items, 426 ImporterBridge* bridge) = 0; 427 428 // Cancels the import process. 429 virtual void Cancel(); 430 431 void set_import_to_bookmark_bar(bool import_to_bookmark_bar) { 432 import_to_bookmark_bar_ = import_to_bookmark_bar; 433 } 434 435 void set_bookmark_bar_disabled(bool bookmark_bar_disabled) { 436 bookmark_bar_disabled_ = bookmark_bar_disabled; 437 } 438 439 bool bookmark_bar_disabled() { 440 return bookmark_bar_disabled_; 441 } 442 443 bool cancelled() const { return cancelled_; } 444 445 protected: 446 friend class base::RefCountedThreadSafe<Importer>; 447 448 Importer(); 449 virtual ~Importer(); 450 451 // Given raw image data, decodes the icon, re-sampling to the correct size as 452 // necessary, and re-encodes as PNG data in the given output vector. Returns 453 // true on success. 454 static bool ReencodeFavicon(const unsigned char* src_data, size_t src_len, 455 std::vector<unsigned char>* png_data); 456 457 bool import_to_bookmark_bar() const { return import_to_bookmark_bar_; } 458 459 scoped_refptr<ImporterBridge> bridge_; 460 461 private: 462 // True if the caller cancels the import process. 463 bool cancelled_; 464 465 // True if the importer is created in the first run UI. 466 bool import_to_bookmark_bar_; 467 468 // Whether bookmark bar is disabled (not shown) for importer. This is set 469 // true during first run to prevent out of process bookmark importer from 470 // updating bookmark bar settings. 471 bool bookmark_bar_disabled_; 472 473 DISALLOW_COPY_AND_ASSIGN(Importer); 474}; 475 476// An interface an object that calls StartImportingWithUI can call to be 477// notified about the state of the import operation. 478class ImportObserver { 479 public: 480 virtual ~ImportObserver() {} 481 // The import operation was canceled by the user. 482 // TODO (4164): this is never invoked, either rip it out or invoke it. 483 virtual void ImportCanceled() = 0; 484 485 // The import operation was completed successfully. 486 virtual void ImportComplete() = 0; 487}; 488 489 490// Shows a UI for importing and begins importing the specified items from 491// source_profile to target_profile. observer is notified when the process is 492// complete, can be NULL. parent is the window to parent the UI to, can be NULL 493// if there's nothing to parent to. first_run is true if it's invoked in the 494// first run UI. 495void StartImportingWithUI(gfx::NativeWindow parent_window, 496 uint16 items, 497 ImporterHost* coordinator, 498 const importer::ProfileInfo& source_profile, 499 Profile* target_profile, 500 ImportObserver* observer, 501 bool first_run); 502 503#endif // CHROME_BROWSER_IMPORTER_IMPORTER_H_ 504