| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/extensions/api/tabs/tabs_event_router.h" | 5 #include "chrome/browser/extensions/api/tabs/tabs_event_router.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
| 9 #include "base/values.h" | 9 #include "base/values.h" |
| 10 #include "chrome/browser/chrome_notification_types.h" | 10 #include "chrome/browser/chrome_notification_types.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 | 57 |
| 58 // Overwrite the third arg with our tab value as seen by this extension. | 58 // Overwrite the third arg with our tab value as seen by this extension. |
| 59 event_args->Set(2, ExtensionTabUtil::CreateTabValue(contents, extension)); | 59 event_args->Set(2, ExtensionTabUtil::CreateTabValue(contents, extension)); |
| 60 return true; | 60 return true; |
| 61 } | 61 } |
| 62 | 62 |
| 63 } // namespace | 63 } // namespace |
| 64 | 64 |
| 65 TabsEventRouter::TabEntry::TabEntry(content::WebContents* contents) | 65 TabsEventRouter::TabEntry::TabEntry(content::WebContents* contents) |
| 66 : contents_(contents), | 66 : contents_(contents), |
| 67 complete_waiting_on_load_(false), | |
| 68 was_audible_(contents->WasRecentlyAudible()), | 67 was_audible_(contents->WasRecentlyAudible()), |
| 69 was_muted_(contents->IsAudioMuted()) { | 68 was_muted_(contents->IsAudioMuted()) { |
| 70 } | 69 } |
| 71 | 70 |
| 72 scoped_ptr<base::DictionaryValue> TabsEventRouter::TabEntry::UpdateLoadState() { | 71 scoped_ptr<base::DictionaryValue> TabsEventRouter::TabEntry::Update() { |
| 73 // The tab may go in & out of loading (for instance if iframes navigate). | |
| 74 // We only want to respond to the first change from loading to !loading after | |
| 75 // the NAV_ENTRY_COMMITTED was fired. | |
| 76 scoped_ptr<base::DictionaryValue> changed_properties( | 72 scoped_ptr<base::DictionaryValue> changed_properties( |
| 77 new base::DictionaryValue()); | 73 new base::DictionaryValue()); |
| 78 if (!complete_waiting_on_load_ || contents_->IsLoading()) { | 74 if (status_ != "loading" && contents_->IsLoading() && |
| 79 return changed_properties.Pass(); | 75 contents_->GetLastCommittedURL() != url_) { |
| 76 changed_properties->SetString(tabs_constants::kStatusKey, |
| 77 tabs_constants::kStatusValueLoading); |
| 78 status_ = "loading"; |
| 79 } else if (status_ == "loading" && !contents_->IsLoading()) { |
| 80 changed_properties->SetString(tabs_constants::kStatusKey, |
| 81 tabs_constants::kStatusValueComplete); |
| 82 status_ = "complete"; |
| 80 } | 83 } |
| 81 | 84 |
| 82 // Send "complete" state change. | 85 if (contents_->GetLastCommittedURL() != url_) { |
| 83 complete_waiting_on_load_ = false; | 86 url_ = contents_->GetLastCommittedURL(); |
| 84 changed_properties->SetString(tabs_constants::kStatusKey, | 87 changed_properties->SetString(tabs_constants::kUrlKey, url_.spec()); |
| 85 tabs_constants::kStatusValueComplete); | 88 } |
| 86 return changed_properties.Pass(); | 89 return changed_properties.Pass(); |
| 87 } | 90 } |
| 88 | 91 |
| 89 scoped_ptr<base::DictionaryValue> TabsEventRouter::TabEntry::DidNavigate() { | |
| 90 // Send "loading" state change. | |
| 91 complete_waiting_on_load_ = true; | |
| 92 scoped_ptr<base::DictionaryValue> changed_properties( | |
| 93 new base::DictionaryValue()); | |
| 94 changed_properties->SetString(tabs_constants::kStatusKey, | |
| 95 tabs_constants::kStatusValueLoading); | |
| 96 | |
| 97 if (contents_->GetURL() != url_) { | |
| 98 url_ = contents_->GetURL(); | |
| 99 changed_properties->SetString(tabs_constants::kUrlKey, url_.spec()); | |
| 100 } | |
| 101 | |
| 102 return changed_properties.Pass(); | |
| 103 } | |
| 104 | |
| 105 bool TabsEventRouter::TabEntry::SetAudible(bool new_val) { | 92 bool TabsEventRouter::TabEntry::SetAudible(bool new_val) { |
| 106 if (was_audible_ == new_val) | 93 if (was_audible_ == new_val) |
| 107 return false; | 94 return false; |
| 108 was_audible_ = new_val; | 95 was_audible_ = new_val; |
| 109 return true; | 96 return true; |
| 110 } | 97 } |
| 111 | 98 |
| 112 bool TabsEventRouter::TabEntry::SetMuted(bool new_val) { | 99 bool TabsEventRouter::TabEntry::SetMuted(bool new_val) { |
| 113 if (was_muted_ == new_val) | 100 if (was_muted_ == new_val) |
| 114 return false; | 101 return false; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 // Start listening to TabStripModel events for this browser. | 140 // Start listening to TabStripModel events for this browser. |
| 154 TabStripModel* tab_strip = browser->tab_strip_model(); | 141 TabStripModel* tab_strip = browser->tab_strip_model(); |
| 155 tab_strip->AddObserver(this); | 142 tab_strip->AddObserver(this); |
| 156 | 143 |
| 157 for (int i = 0; i < tab_strip->count(); ++i) { | 144 for (int i = 0; i < tab_strip->count(); ++i) { |
| 158 RegisterForTabNotifications(tab_strip->GetWebContentsAt(i)); | 145 RegisterForTabNotifications(tab_strip->GetWebContentsAt(i)); |
| 159 } | 146 } |
| 160 } | 147 } |
| 161 | 148 |
| 162 void TabsEventRouter::RegisterForTabNotifications(WebContents* contents) { | 149 void TabsEventRouter::RegisterForTabNotifications(WebContents* contents) { |
| 150 // TODO(limasdf): Attach WebContentsObservers to |contents| rather than |
| 151 // registering for notifications. |
| 163 registrar_.Add( | 152 registrar_.Add( |
| 164 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 153 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 165 content::Source<NavigationController>(&contents->GetController())); | 154 content::Source<NavigationController>(&contents->GetController())); |
| 166 | 155 |
| 167 // Observing NOTIFICATION_WEB_CONTENTS_DESTROYED is necessary because it's | 156 // Observing NOTIFICATION_WEB_CONTENTS_DESTROYED is necessary because it's |
| 168 // possible for tabs to be created, detached and then destroyed without | 157 // possible for tabs to be created, detached and then destroyed without |
| 169 // ever having been re-attached and closed. This happens in the case of | 158 // ever having been re-attached and closed. This happens in the case of |
| 170 // a devtools WebContents that is opened in window, docked, then closed. | 159 // a devtools WebContents that is opened in window, docked, then closed. |
| 171 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 160 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 172 content::Source<WebContents>(contents)); | 161 content::Source<WebContents>(contents)); |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 | 488 |
| 500 TabEntryMap::iterator i = tab_entries_.find(tab_id); | 489 TabEntryMap::iterator i = tab_entries_.find(tab_id); |
| 501 if (tab_entries_.end() == i) | 490 if (tab_entries_.end() == i) |
| 502 return linked_ptr<TabEntry>(NULL); | 491 return linked_ptr<TabEntry>(NULL); |
| 503 return i->second; | 492 return i->second; |
| 504 } | 493 } |
| 505 | 494 |
| 506 void TabsEventRouter::Observe(int type, | 495 void TabsEventRouter::Observe(int type, |
| 507 const content::NotificationSource& source, | 496 const content::NotificationSource& source, |
| 508 const content::NotificationDetails& details) { | 497 const content::NotificationDetails& details) { |
| 509 if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { | 498 switch (type) { |
| 499 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
| 510 NavigationController* source_controller = | 500 NavigationController* source_controller = |
| 511 content::Source<NavigationController>(source).ptr(); | 501 content::Source<NavigationController>(source).ptr(); |
| 512 linked_ptr<TabEntry> entry = | 502 linked_ptr<TabEntry> entry = |
| 513 GetTabEntry(source_controller->GetWebContents()); | 503 GetTabEntry(source_controller->GetWebContents()); |
| 514 CHECK(entry.get()); | 504 CHECK(entry.get()); |
| 515 TabUpdated(entry, (entry.get())->DidNavigate()); | 505 TabUpdated(entry, (entry.get())->Update()); |
| 516 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { | 506 } |
| 507 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
| 517 // Tab was destroyed after being detached (without being re-attached). | 508 // Tab was destroyed after being detached (without being re-attached). |
| 518 WebContents* contents = content::Source<WebContents>(source).ptr(); | 509 WebContents* contents = content::Source<WebContents>(source).ptr(); |
| 519 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 510 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 520 content::Source<NavigationController>(&contents->GetController())); | 511 content::Source<NavigationController>(&contents->GetController())); |
| 521 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 512 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 522 content::Source<WebContents>(contents)); | 513 content::Source<WebContents>(contents)); |
| 523 favicon_scoped_observer_.Remove( | 514 favicon_scoped_observer_.Remove( |
| 524 favicon::ContentFaviconDriver::FromWebContents(contents)); | 515 favicon::ContentFaviconDriver::FromWebContents(contents)); |
| 525 } else { | 516 } |
| 526 NOTREACHED(); | 517 default: |
| 518 NOTREACHED(); |
| 527 } | 519 } |
| 528 } | 520 } |
| 529 | 521 |
| 530 void TabsEventRouter::TabChangedAt(WebContents* contents, | 522 void TabsEventRouter::TabChangedAt(WebContents* contents, |
| 531 int index, | 523 int index, |
| 532 TabChangeType change_type) { | 524 TabChangeType change_type) { |
| 533 linked_ptr<TabEntry> entry = GetTabEntry(contents); | 525 linked_ptr<TabEntry> entry = GetTabEntry(contents); |
| 534 CHECK(entry.get()); | 526 CHECK(entry.get()); |
| 535 TabUpdated(entry, (entry.get())->UpdateLoadState()); | 527 TabUpdated(entry, (entry.get())->Update()); |
| 536 } | 528 } |
| 537 | 529 |
| 538 void TabsEventRouter::TabReplacedAt(TabStripModel* tab_strip_model, | 530 void TabsEventRouter::TabReplacedAt(TabStripModel* tab_strip_model, |
| 539 WebContents* old_contents, | 531 WebContents* old_contents, |
| 540 WebContents* new_contents, | 532 WebContents* new_contents, |
| 541 int index) { | 533 int index) { |
| 542 // Notify listeners that the next tabs closing or being added are due to | 534 // Notify listeners that the next tabs closing or being added are due to |
| 543 // WebContents being swapped. | 535 // WebContents being swapped. |
| 544 const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents); | 536 const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents); |
| 545 const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents); | 537 const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 void TabsEventRouter::OnFaviconUpdated(favicon::FaviconDriver* favicon_driver, | 599 void TabsEventRouter::OnFaviconUpdated(favicon::FaviconDriver* favicon_driver, |
| 608 bool icon_url_changed) { | 600 bool icon_url_changed) { |
| 609 if (icon_url_changed) { | 601 if (icon_url_changed) { |
| 610 favicon::ContentFaviconDriver* content_favicon_driver = | 602 favicon::ContentFaviconDriver* content_favicon_driver = |
| 611 static_cast<favicon::ContentFaviconDriver*>(favicon_driver); | 603 static_cast<favicon::ContentFaviconDriver*>(favicon_driver); |
| 612 FaviconUrlUpdated(content_favicon_driver->web_contents()); | 604 FaviconUrlUpdated(content_favicon_driver->web_contents()); |
| 613 } | 605 } |
| 614 } | 606 } |
| 615 | 607 |
| 616 } // namespace extensions | 608 } // namespace extensions |
| OLD | NEW |