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