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 |