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 #include "chrome/browser/ui/views/importer/import_progress_dialog_view.h" 6 7 #include "base/utf_string_conversions.h" 8 #include "chrome/browser/importer/importer_host.h" 9 #include "chrome/browser/importer/importer_observer.h" 10 #include "chrome/browser/importer/importer_progress_dialog.h" 11 #include "grit/chromium_strings.h" 12 #include "grit/generated_resources.h" 13 #include "grit/locale_settings.h" 14 #include "ui/base/l10n/l10n_util.h" 15 #include "views/controls/label.h" 16 #include "views/controls/throbber.h" 17 #include "views/layout/grid_layout.h" 18 #include "views/layout/layout_constants.h" 19 #include "views/window/window.h" 20 21 ImportProgressDialogView::ImportProgressDialogView( 22 HWND parent_window, 23 uint16 items, 24 ImporterHost* importer_host, 25 ImporterObserver* importer_observer, 26 const string16& importer_name, 27 bool bookmarks_import) 28 : state_bookmarks_(new views::CheckmarkThrobber), 29 state_searches_(new views::CheckmarkThrobber), 30 state_passwords_(new views::CheckmarkThrobber), 31 state_history_(new views::CheckmarkThrobber), 32 state_cookies_(new views::CheckmarkThrobber), 33 label_bookmarks_(new views::Label(UTF16ToWide( 34 l10n_util::GetStringUTF16(IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS)))), 35 label_searches_(new views::Label(UTF16ToWide( 36 l10n_util::GetStringUTF16(IDS_IMPORT_PROGRESS_STATUS_SEARCH)))), 37 label_passwords_(new views::Label(UTF16ToWide( 38 l10n_util::GetStringUTF16(IDS_IMPORT_PROGRESS_STATUS_PASSWORDS)))), 39 label_history_(new views::Label(UTF16ToWide( 40 l10n_util::GetStringUTF16(IDS_IMPORT_PROGRESS_STATUS_HISTORY)))), 41 label_cookies_(new views::Label(UTF16ToWide( 42 l10n_util::GetStringUTF16(IDS_IMPORT_PROGRESS_STATUS_COOKIES)))), 43 parent_window_(parent_window), 44 items_(items), 45 importer_host_(importer_host), 46 importer_observer_(importer_observer), 47 importing_(true), 48 bookmarks_import_(bookmarks_import) { 49 std::wstring info_text = bookmarks_import ? 50 UTF16ToWide(l10n_util::GetStringUTF16(IDS_IMPORT_BOOKMARKS)) : 51 UTF16ToWide(l10n_util::GetStringFUTF16( 52 IDS_IMPORT_PROGRESS_INFO, importer_name)); 53 label_info_ = new views::Label(info_text); 54 importer_host_->SetObserver(this); 55 label_info_->SetMultiLine(true); 56 label_info_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 57 label_bookmarks_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 58 label_searches_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 59 label_passwords_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 60 label_history_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 61 label_cookies_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 62 63 // These are scoped pointers, so we don't need the parent to delete them. 64 state_bookmarks_->set_parent_owned(false); 65 state_searches_->set_parent_owned(false); 66 state_passwords_->set_parent_owned(false); 67 state_history_->set_parent_owned(false); 68 state_cookies_->set_parent_owned(false); 69 label_bookmarks_->set_parent_owned(false); 70 label_searches_->set_parent_owned(false); 71 label_passwords_->set_parent_owned(false); 72 label_history_->set_parent_owned(false); 73 label_cookies_->set_parent_owned(false); 74 } 75 76 ImportProgressDialogView::~ImportProgressDialogView() { 77 RemoveChildView(state_bookmarks_.get()); 78 RemoveChildView(state_searches_.get()); 79 RemoveChildView(state_passwords_.get()); 80 RemoveChildView(state_history_.get()); 81 RemoveChildView(state_cookies_.get()); 82 RemoveChildView(label_bookmarks_.get()); 83 RemoveChildView(label_searches_.get()); 84 RemoveChildView(label_passwords_.get()); 85 RemoveChildView(label_history_.get()); 86 RemoveChildView(label_cookies_.get()); 87 88 if (importing_) { 89 // We're being deleted while importing, clean up state so that the importer 90 // doesn't have a reference to us and cancel the import. We can get here 91 // if our parent window is closed, which closes our window and deletes us. 92 importing_ = false; 93 importer_host_->SetObserver(NULL); 94 importer_host_->Cancel(); 95 if (importer_observer_) 96 importer_observer_->ImportCompleted(); 97 } 98 } 99 100 gfx::Size ImportProgressDialogView::GetPreferredSize() { 101 return gfx::Size(views::Window::GetLocalizedContentsSize( 102 IDS_IMPORTPROGRESS_DIALOG_WIDTH_CHARS, 103 IDS_IMPORTPROGRESS_DIALOG_HEIGHT_LINES)); 104 } 105 106 void ImportProgressDialogView::ViewHierarchyChanged(bool is_add, 107 views::View* parent, 108 views::View* child) { 109 if (is_add && child == this) 110 InitControlLayout(); 111 } 112 113 int ImportProgressDialogView::GetDialogButtons() const { 114 return MessageBoxFlags::DIALOGBUTTON_CANCEL; 115 } 116 117 std::wstring ImportProgressDialogView::GetDialogButtonLabel( 118 MessageBoxFlags::DialogButton button) const { 119 DCHECK(button == MessageBoxFlags::DIALOGBUTTON_CANCEL); 120 return UTF16ToWide( 121 l10n_util::GetStringUTF16(IDS_IMPORT_PROGRESS_STATUS_CANCEL)); 122 } 123 124 bool ImportProgressDialogView::IsModal() const { 125 return parent_window_ != NULL; 126 } 127 128 std::wstring ImportProgressDialogView::GetWindowTitle() const { 129 return UTF16ToWide(l10n_util::GetStringUTF16(IDS_IMPORT_PROGRESS_TITLE)); 130 } 131 132 bool ImportProgressDialogView::Cancel() { 133 // When the user cancels the import, we need to tell the importer_host to stop 134 // importing and return false so that the window lives long enough to receive 135 // ImportEnded, which will close the window. Closing the window results in 136 // another call to this function and at that point we must return true to 137 // allow the window to close. 138 if (!importing_) 139 return true; // We have received ImportEnded, so we can close. 140 141 // Cancel the import and wait for further instructions. 142 importer_host_->Cancel(); 143 return false; 144 } 145 146 views::View* ImportProgressDialogView::GetContentsView() { 147 return this; 148 } 149 150 void ImportProgressDialogView::InitControlLayout() { 151 using views::GridLayout; 152 using views::ColumnSet; 153 154 GridLayout* layout = GridLayout::CreatePanel(this); 155 SetLayoutManager(layout); 156 157 gfx::Size ps = state_history_->GetPreferredSize(); 158 159 const int single_column_view_set_id = 0; 160 ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id); 161 if (bookmarks_import_) { 162 column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 163 GridLayout::FIXED, ps.width(), 0); 164 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); 165 } 166 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, 167 GridLayout::USE_PREF, 0, 0); 168 const int double_column_view_set_id = 1; 169 column_set = layout->AddColumnSet(double_column_view_set_id); 170 column_set->AddPaddingColumn( 171 0, views::kUnrelatedControlLargeHorizontalSpacing); 172 column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 173 GridLayout::FIXED, ps.width(), 0); 174 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); 175 column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1, 176 GridLayout::USE_PREF, 0, 0); 177 column_set->AddPaddingColumn( 178 0, views::kUnrelatedControlLargeHorizontalSpacing); 179 180 layout->StartRow(0, single_column_view_set_id); 181 if (bookmarks_import_) 182 layout->AddView(state_bookmarks_.get()); 183 layout->AddView(label_info_); 184 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 185 186 if (items_ & importer::HISTORY) { 187 layout->StartRow(0, double_column_view_set_id); 188 layout->AddView(state_history_.get()); 189 layout->AddView(label_history_.get()); 190 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 191 } 192 if (items_ & importer::FAVORITES && !bookmarks_import_) { 193 layout->StartRow(0, double_column_view_set_id); 194 layout->AddView(state_bookmarks_.get()); 195 layout->AddView(label_bookmarks_.get()); 196 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 197 } 198 if (items_ & importer::SEARCH_ENGINES) { 199 layout->StartRow(0, double_column_view_set_id); 200 layout->AddView(state_searches_.get()); 201 layout->AddView(label_searches_.get()); 202 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 203 } 204 if (items_ & importer::PASSWORDS) { 205 layout->StartRow(0, double_column_view_set_id); 206 layout->AddView(state_passwords_.get()); 207 layout->AddView(label_passwords_.get()); 208 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 209 } 210 if (items_ & importer::COOKIES) { 211 layout->StartRow(0, double_column_view_set_id); 212 layout->AddView(state_cookies_.get()); 213 layout->AddView(label_cookies_.get()); 214 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 215 } 216 } 217 218 void ImportProgressDialogView::ImportStarted() { 219 importing_ = true; 220 } 221 222 void ImportProgressDialogView::ImportItemStarted(importer::ImportItem item) { 223 DCHECK(items_ & item); 224 switch (item) { 225 case importer::FAVORITES: 226 state_bookmarks_->Start(); 227 break; 228 case importer::SEARCH_ENGINES: 229 state_searches_->Start(); 230 break; 231 case importer::PASSWORDS: 232 state_passwords_->Start(); 233 break; 234 case importer::HISTORY: 235 state_history_->Start(); 236 break; 237 case importer::COOKIES: 238 state_cookies_->Start(); 239 break; 240 } 241 } 242 243 void ImportProgressDialogView::ImportItemEnded(importer::ImportItem item) { 244 DCHECK(items_ & item); 245 switch (item) { 246 case importer::FAVORITES: 247 state_bookmarks_->Stop(); 248 state_bookmarks_->SetChecked(true); 249 break; 250 case importer::SEARCH_ENGINES: 251 state_searches_->Stop(); 252 state_searches_->SetChecked(true); 253 break; 254 case importer::PASSWORDS: 255 state_passwords_->Stop(); 256 state_passwords_->SetChecked(true); 257 break; 258 case importer::HISTORY: 259 state_history_->Stop(); 260 state_history_->SetChecked(true); 261 break; 262 case importer::COOKIES: 263 state_cookies_->Stop(); 264 state_cookies_->SetChecked(true); 265 break; 266 } 267 } 268 269 void ImportProgressDialogView::ImportEnded() { 270 // This can happen because: 271 // - the import completed successfully. 272 // - the import was canceled by the user. 273 // - the user chose to skip the import because they didn't want to shut down 274 // Firefox. 275 // In every case, we need to close the UI now. 276 importing_ = false; 277 importer_host_->SetObserver(NULL); 278 window()->CloseWindow(); 279 if (importer_observer_) 280 importer_observer_->ImportCompleted(); 281 } 282 283 namespace importer { 284 285 void ShowImportProgressDialog(HWND parent_window, 286 uint16 items, 287 ImporterHost* importer_host, 288 ImporterObserver* importer_observer, 289 const SourceProfile& source_profile, 290 Profile* target_profile, 291 bool first_run) { 292 DCHECK(items != 0); 293 ImportProgressDialogView* progress_view = new ImportProgressDialogView( 294 parent_window, 295 items, 296 importer_host, 297 importer_observer, 298 source_profile.importer_name, 299 source_profile.importer_type == importer::BOOKMARKS_HTML); 300 301 views::Window* window = views::Window::CreateChromeWindow( 302 parent_window, gfx::Rect(), progress_view); 303 304 if (!importer_host->is_headless() && !first_run) 305 window->Show(); 306 307 importer_host->StartImportSettings( 308 source_profile, target_profile, items, new ProfileWriter(target_profile), 309 first_run); 310 } 311 312 } // namespace importer 313