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