| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/cocoa/history_menu_bridge.h" | 5 #include "chrome/browser/ui/cocoa/history_menu_bridge.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 | 58 |
| 59 HistoryMenuBridge::HistoryItem::~HistoryItem() { | 59 HistoryMenuBridge::HistoryItem::~HistoryItem() { |
| 60 } | 60 } |
| 61 | 61 |
| 62 HistoryMenuBridge::HistoryMenuBridge(Profile* profile) | 62 HistoryMenuBridge::HistoryMenuBridge(Profile* profile) |
| 63 : controller_([[HistoryMenuCocoaController alloc] initWithBridge:this]), | 63 : controller_([[HistoryMenuCocoaController alloc] initWithBridge:this]), |
| 64 profile_(profile), | 64 profile_(profile), |
| 65 history_service_(NULL), | 65 history_service_(NULL), |
| 66 tab_restore_service_(NULL), | 66 tab_restore_service_(NULL), |
| 67 create_in_progress_(false), | 67 create_in_progress_(false), |
| 68 need_recreate_(false) { | 68 need_recreate_(false), |
| 69 history_service_observer_(this) { |
| 69 // If we don't have a profile, do not bother initializing our data sources. | 70 // If we don't have a profile, do not bother initializing our data sources. |
| 70 // This shouldn't happen except in unit tests. | 71 // This shouldn't happen except in unit tests. |
| 71 if (profile_) { | 72 if (profile_) { |
| 72 // Check to see if the history service is ready. Because it loads async, it | 73 // Check to see if the history service is ready. Because it loads async, it |
| 73 // may not be ready when the Bridge is created. If this happens, register | 74 // may not be ready when the Bridge is created. If this happens, register |
| 74 // for a notification that tells us the HistoryService is ready. | 75 // for a notification that tells us the HistoryService is ready. |
| 75 HistoryService* hs = HistoryServiceFactory::GetForProfile( | 76 HistoryService* hs = HistoryServiceFactory::GetForProfile( |
| 76 profile_, Profile::EXPLICIT_ACCESS); | 77 profile_, Profile::EXPLICIT_ACCESS); |
| 77 if (hs != NULL && hs->BackendLoaded()) { | 78 if (hs) { |
| 78 history_service_ = hs; | 79 history_service_observer_.Add(hs); |
| 79 Init(); | 80 if (hs->BackendLoaded()) { |
| 81 history_service_ = hs; |
| 82 Init(); |
| 83 } |
| 80 } | 84 } |
| 81 | 85 |
| 82 tab_restore_service_ = TabRestoreServiceFactory::GetForProfile(profile_); | 86 tab_restore_service_ = TabRestoreServiceFactory::GetForProfile(profile_); |
| 83 if (tab_restore_service_) { | 87 if (tab_restore_service_) { |
| 84 tab_restore_service_->AddObserver(this); | 88 tab_restore_service_->AddObserver(this); |
| 85 // If the tab entries are already loaded, invoke the observer method to | 89 // If the tab entries are already loaded, invoke the observer method to |
| 86 // build the "Recently Closed" section. Otherwise it will be when the | 90 // build the "Recently Closed" section. Otherwise it will be when the |
| 87 // backend loads. | 91 // backend loads. |
| 88 if (!tab_restore_service_->IsLoaded()) | 92 if (!tab_restore_service_->IsLoaded()) |
| 89 tab_restore_service_->LoadTabsFromLastSession(); | 93 tab_restore_service_->LoadTabsFromLastSession(); |
| 90 else | 94 else |
| 91 TabRestoreServiceChanged(tab_restore_service_); | 95 TabRestoreServiceChanged(tab_restore_service_); |
| 92 } | 96 } |
| 93 } | 97 } |
| 94 | 98 |
| 95 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 99 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 96 default_favicon_.reset( | 100 default_favicon_.reset( |
| 97 rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).CopyNSImage()); | 101 rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).CopyNSImage()); |
| 98 | 102 |
| 99 // Set the static icons in the menu. | 103 // Set the static icons in the menu. |
| 100 NSMenuItem* item = [HistoryMenu() itemWithTag:IDC_SHOW_HISTORY]; | 104 NSMenuItem* item = [HistoryMenu() itemWithTag:IDC_SHOW_HISTORY]; |
| 101 [item setImage:rb.GetNativeImageNamed(IDR_HISTORY_FAVICON).ToNSImage()]; | 105 [item setImage:rb.GetNativeImageNamed(IDR_HISTORY_FAVICON).ToNSImage()]; |
| 102 | 106 |
| 103 // The service is not ready for use yet, so become notified when it does. | |
| 104 if (!history_service_) { | |
| 105 registrar_.Add( | |
| 106 this, chrome::NOTIFICATION_HISTORY_LOADED, | |
| 107 content::Source<Profile>(profile_)); | |
| 108 } | |
| 109 } | 107 } |
| 110 | 108 |
| 111 // Note that all requests sent to either the history service or the favicon | 109 // Note that all requests sent to either the history service or the favicon |
| 112 // service will be automatically cancelled by their respective Consumers, so | 110 // service will be automatically cancelled by their respective Consumers, so |
| 113 // task cancellation is not done manually here in the dtor. | 111 // task cancellation is not done manually here in the dtor. |
| 114 HistoryMenuBridge::~HistoryMenuBridge() { | 112 HistoryMenuBridge::~HistoryMenuBridge() { |
| 115 // Unregister ourselves as observers and notifications. | 113 // Unregister ourselves as observers and notifications. |
| 116 DCHECK(profile_); | 114 DCHECK(profile_); |
| 117 if (history_service_) { | 115 if (history_service_) { |
| 118 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, | 116 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, |
| 119 content::Source<Profile>(profile_)); | 117 content::Source<Profile>(profile_)); |
| 120 history_service_->RemoveObserver(this); | |
| 121 } else { | |
| 122 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED, | |
| 123 content::Source<Profile>(profile_)); | |
| 124 } | 118 } |
| 125 | 119 |
| 126 if (tab_restore_service_) | 120 if (tab_restore_service_) |
| 127 tab_restore_service_->RemoveObserver(this); | 121 tab_restore_service_->RemoveObserver(this); |
| 128 | 122 |
| 129 // Since the map owns the HistoryItems, delete anything that still exists. | 123 // Since the map owns the HistoryItems, delete anything that still exists. |
| 130 std::map<NSMenuItem*, HistoryItem*>::iterator it = menu_item_map_.begin(); | 124 std::map<NSMenuItem*, HistoryItem*>::iterator it = menu_item_map_.begin(); |
| 131 while (it != menu_item_map_.end()) { | 125 while (it != menu_item_map_.end()) { |
| 132 HistoryItem* item = it->second; | 126 HistoryItem* item = it->second; |
| 133 menu_item_map_.erase(it++); | 127 menu_item_map_.erase(it++); |
| 134 delete item; | 128 delete item; |
| 135 } | 129 } |
| 136 } | 130 } |
| 137 | 131 |
| 138 void HistoryMenuBridge::Observe(int type, | 132 void HistoryMenuBridge::Observe(int type, |
| 139 const content::NotificationSource& source, | 133 const content::NotificationSource& source, |
| 140 const content::NotificationDetails& details) { | 134 const content::NotificationDetails& details) { |
| 141 // A history service is now ready. Check to see if it's the one for the main | 135 // chrome::NOTIFICATION_HISTORY_URLS_DELETED is the only notification we are |
| 142 // profile. If so, perform final initialization. | 136 // registered for. OnHistoryChanged is the generic function called for any |
| 143 if (type == chrome::NOTIFICATION_HISTORY_LOADED) { | 137 // History modifications. |
| 144 HistoryService* hs = HistoryServiceFactory::GetForProfile( | |
| 145 profile_, Profile::EXPLICIT_ACCESS); | |
| 146 if (hs != NULL && hs->BackendLoaded()) { | |
| 147 history_service_ = hs; | |
| 148 Init(); | |
| 149 | |
| 150 // Found our HistoryService, so stop listening for this notification. | |
| 151 registrar_.Remove(this, | |
| 152 chrome::NOTIFICATION_HISTORY_LOADED, | |
| 153 content::Source<Profile>(profile_)); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 // All other notification types that we observe indicate that the history has | |
| 158 // changed. | |
| 159 OnHistoryChanged(); | 138 OnHistoryChanged(); |
| 160 } | 139 } |
| 161 | 140 |
| 162 void HistoryMenuBridge::TabRestoreServiceChanged(TabRestoreService* service) { | 141 void HistoryMenuBridge::TabRestoreServiceChanged(TabRestoreService* service) { |
| 163 const TabRestoreService::Entries& entries = service->entries(); | 142 const TabRestoreService::Entries& entries = service->entries(); |
| 164 | 143 |
| 165 // Clear the history menu before rebuilding. | 144 // Clear the history menu before rebuilding. |
| 166 NSMenu* menu = HistoryMenu(); | 145 NSMenu* menu = HistoryMenu(); |
| 167 ClearMenuSection(menu, kRecentlyClosed); | 146 ClearMenuSection(menu, kRecentlyClosed); |
| 168 | 147 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 const history::RedirectList& redirects, | 255 const history::RedirectList& redirects, |
| 277 base::Time visit_time) { | 256 base::Time visit_time) { |
| 278 OnHistoryChanged(); | 257 OnHistoryChanged(); |
| 279 } | 258 } |
| 280 | 259 |
| 281 void HistoryMenuBridge::OnURLsModified(HistoryService* history_service, | 260 void HistoryMenuBridge::OnURLsModified(HistoryService* history_service, |
| 282 const history::URLRows& changed_urls) { | 261 const history::URLRows& changed_urls) { |
| 283 OnHistoryChanged(); | 262 OnHistoryChanged(); |
| 284 } | 263 } |
| 285 | 264 |
| 265 void HistoryMenuBridge::OnHistoryServiceLoaded( |
| 266 HistoryService* history_service) { |
| 267 history_service_ = history_service; |
| 268 Init(); |
| 269 } |
| 270 |
| 286 HistoryMenuBridge::HistoryItem* HistoryMenuBridge::HistoryItemForMenuItem( | 271 HistoryMenuBridge::HistoryItem* HistoryMenuBridge::HistoryItemForMenuItem( |
| 287 NSMenuItem* item) { | 272 NSMenuItem* item) { |
| 288 std::map<NSMenuItem*, HistoryItem*>::iterator it = menu_item_map_.find(item); | 273 std::map<NSMenuItem*, HistoryItem*>::iterator it = menu_item_map_.find(item); |
| 289 if (it != menu_item_map_.end()) { | 274 if (it != menu_item_map_.end()) { |
| 290 return it->second; | 275 return it->second; |
| 291 } | 276 } |
| 292 return NULL; | 277 return NULL; |
| 293 } | 278 } |
| 294 | 279 |
| 295 HistoryService* HistoryMenuBridge::service() { | 280 HistoryService* HistoryMenuBridge::service() { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 [menu insertItem:item->menu_item.get() atIndex:index]; | 350 [menu insertItem:item->menu_item.get() atIndex:index]; |
| 366 menu_item_map_.insert(std::make_pair(item->menu_item.get(), item)); | 351 menu_item_map_.insert(std::make_pair(item->menu_item.get(), item)); |
| 367 | 352 |
| 368 return item->menu_item.get(); | 353 return item->menu_item.get(); |
| 369 } | 354 } |
| 370 | 355 |
| 371 void HistoryMenuBridge::Init() { | 356 void HistoryMenuBridge::Init() { |
| 372 DCHECK(history_service_); | 357 DCHECK(history_service_); |
| 373 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, | 358 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, |
| 374 content::Source<Profile>(profile_)); | 359 content::Source<Profile>(profile_)); |
| 375 history_service_->AddObserver(this); | |
| 376 } | 360 } |
| 377 | 361 |
| 378 void HistoryMenuBridge::CreateMenu() { | 362 void HistoryMenuBridge::CreateMenu() { |
| 379 // If we're currently running CreateMenu(), wait until it finishes. | 363 // If we're currently running CreateMenu(), wait until it finishes. |
| 380 if (create_in_progress_) | 364 if (create_in_progress_) |
| 381 return; | 365 return; |
| 382 create_in_progress_ = true; | 366 create_in_progress_ = true; |
| 383 need_recreate_ = false; | 367 need_recreate_ = false; |
| 384 | 368 |
| 385 DCHECK(history_service_); | 369 DCHECK(history_service_); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 } | 462 } |
| 479 | 463 |
| 480 void HistoryMenuBridge::CancelFaviconRequest(HistoryItem* item) { | 464 void HistoryMenuBridge::CancelFaviconRequest(HistoryItem* item) { |
| 481 DCHECK(item); | 465 DCHECK(item); |
| 482 if (item->icon_requested) { | 466 if (item->icon_requested) { |
| 483 cancelable_task_tracker_.TryCancel(item->icon_task_id); | 467 cancelable_task_tracker_.TryCancel(item->icon_task_id); |
| 484 item->icon_requested = false; | 468 item->icon_requested = false; |
| 485 item->icon_task_id = base::CancelableTaskTracker::kBadTaskId; | 469 item->icon_task_id = base::CancelableTaskTracker::kBadTaskId; |
| 486 } | 470 } |
| 487 } | 471 } |
| OLD | NEW |