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