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/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
8 #include "base/values.h" | 9 #include "base/values.h" |
9 #include "chrome/browser/chrome_notification_types.h" | 10 #include "chrome/browser/chrome_notification_types.h" |
10 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" | 11 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
11 #include "chrome/browser/extensions/api/tabs/tabs_windows_api.h" | 12 #include "chrome/browser/extensions/api/tabs/tabs_windows_api.h" |
12 #include "chrome/browser/extensions/api/tabs/windows_event_router.h" | 13 #include "chrome/browser/extensions/api/tabs/windows_event_router.h" |
13 #include "chrome/browser/extensions/extension_tab_util.h" | 14 #include "chrome/browser/extensions/extension_tab_util.h" |
14 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
15 #include "chrome/browser/ui/browser.h" | 16 #include "chrome/browser/ui/browser.h" |
16 #include "chrome/browser/ui/browser_iterator.h" | 17 #include "chrome/browser/ui/browser_iterator.h" |
17 #include "chrome/browser/ui/browser_list.h" | 18 #include "chrome/browser/ui/browser_list.h" |
18 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 19 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
20 #include "chrome/browser/ui/tabs/tab_utils.h" | |
21 #include "chrome/common/chrome_switches.h" | |
19 #include "chrome/common/extensions/extension_constants.h" | 22 #include "chrome/common/extensions/extension_constants.h" |
20 #include "content/public/browser/favicon_status.h" | 23 #include "content/public/browser/favicon_status.h" |
21 #include "content/public/browser/navigation_controller.h" | 24 #include "content/public/browser/navigation_controller.h" |
22 #include "content/public/browser/navigation_entry.h" | 25 #include "content/public/browser/navigation_entry.h" |
23 #include "content/public/browser/notification_service.h" | 26 #include "content/public/browser/notification_service.h" |
24 #include "content/public/browser/notification_types.h" | 27 #include "content/public/browser/notification_types.h" |
25 #include "content/public/browser/web_contents.h" | 28 #include "content/public/browser/web_contents.h" |
26 | 29 |
27 using base::DictionaryValue; | 30 using base::DictionaryValue; |
28 using base::ListValue; | 31 using base::ListValue; |
(...skipping 22 matching lines...) Expand all Loading... | |
51 properties_value); | 54 properties_value); |
52 event_args->Set(1, properties_value); | 55 event_args->Set(1, properties_value); |
53 | 56 |
54 // Overwrite the third arg with our tab value as seen by this extension. | 57 // Overwrite the third arg with our tab value as seen by this extension. |
55 event_args->Set(2, ExtensionTabUtil::CreateTabValue(contents, extension)); | 58 event_args->Set(2, ExtensionTabUtil::CreateTabValue(contents, extension)); |
56 return true; | 59 return true; |
57 } | 60 } |
58 | 61 |
59 } // namespace | 62 } // namespace |
60 | 63 |
61 TabsEventRouter::TabEntry::TabEntry() : complete_waiting_on_load_(false), | 64 TabsEventRouter::TabEntry::TabEntry() |
62 url_() { | 65 : contents_(NULL), |
66 complete_waiting_on_load_(false), | |
67 was_audible_(false), | |
68 was_muted_(false) { | |
63 } | 69 } |
64 | 70 |
65 base::DictionaryValue* TabsEventRouter::TabEntry::UpdateLoadState( | 71 TabsEventRouter::TabEntry::TabEntry(content::WebContents* contents) |
66 const WebContents* contents) { | 72 : contents_(contents), |
73 complete_waiting_on_load_(false), | |
74 was_audible_(contents->WasRecentlyAudible()), | |
75 was_muted_(contents->IsAudioMuted()) { | |
76 } | |
77 | |
78 scoped_ptr<base::DictionaryValue> TabsEventRouter::TabEntry::UpdateLoadState() { | |
67 // The tab may go in & out of loading (for instance if iframes navigate). | 79 // The tab may go in & out of loading (for instance if iframes navigate). |
68 // We only want to respond to the first change from loading to !loading after | 80 // We only want to respond to the first change from loading to !loading after |
69 // the NAV_ENTRY_COMMITTED was fired. | 81 // the NAV_ENTRY_COMMITTED was fired. |
70 if (!complete_waiting_on_load_ || contents->IsLoading()) | 82 scoped_ptr<base::DictionaryValue> changed_properties( |
71 return NULL; | 83 new base::DictionaryValue()); |
84 if (!complete_waiting_on_load_ || contents_->IsLoading()) { | |
85 return changed_properties.Pass(); | |
86 } | |
72 | 87 |
73 // Send "complete" state change. | 88 // Send "complete" state change. |
74 complete_waiting_on_load_ = false; | 89 complete_waiting_on_load_ = false; |
75 base::DictionaryValue* changed_properties = new base::DictionaryValue(); | |
76 changed_properties->SetString(tabs_constants::kStatusKey, | 90 changed_properties->SetString(tabs_constants::kStatusKey, |
77 tabs_constants::kStatusValueComplete); | 91 tabs_constants::kStatusValueComplete); |
78 return changed_properties; | 92 return changed_properties.Pass(); |
79 } | 93 } |
80 | 94 |
81 base::DictionaryValue* TabsEventRouter::TabEntry::DidNavigate( | 95 scoped_ptr<base::DictionaryValue> TabsEventRouter::TabEntry::DidNavigate() { |
82 const WebContents* contents) { | |
83 // Send "loading" state change. | 96 // Send "loading" state change. |
84 complete_waiting_on_load_ = true; | 97 complete_waiting_on_load_ = true; |
85 base::DictionaryValue* changed_properties = new base::DictionaryValue(); | 98 scoped_ptr<base::DictionaryValue> changed_properties( |
99 new base::DictionaryValue()); | |
86 changed_properties->SetString(tabs_constants::kStatusKey, | 100 changed_properties->SetString(tabs_constants::kStatusKey, |
87 tabs_constants::kStatusValueLoading); | 101 tabs_constants::kStatusValueLoading); |
88 | 102 |
89 if (contents->GetURL() != url_) { | 103 if (contents_->GetURL() != url_) { |
90 url_ = contents->GetURL(); | 104 url_ = contents_->GetURL(); |
91 changed_properties->SetString(tabs_constants::kUrlKey, url_.spec()); | 105 changed_properties->SetString(tabs_constants::kUrlKey, url_.spec()); |
92 } | 106 } |
93 | 107 |
94 return changed_properties; | 108 return changed_properties.Pass(); |
109 } | |
110 | |
111 bool TabsEventRouter::TabEntry::SetAudible(bool new_val) { | |
112 if (was_audible_ == new_val) | |
113 return false; | |
114 was_audible_ = new_val; | |
115 return true; | |
116 } | |
117 | |
118 bool TabsEventRouter::TabEntry::SetMuted(bool new_val) { | |
119 if (was_muted_ == new_val) | |
120 return false; | |
121 was_muted_ = new_val; | |
122 return true; | |
95 } | 123 } |
96 | 124 |
97 TabsEventRouter::TabsEventRouter(Profile* profile) : profile_(profile) { | 125 TabsEventRouter::TabsEventRouter(Profile* profile) : profile_(profile) { |
98 DCHECK(!profile->IsOffTheRecord()); | 126 DCHECK(!profile->IsOffTheRecord()); |
99 | 127 |
100 BrowserList::AddObserver(this); | 128 BrowserList::AddObserver(this); |
101 | 129 |
102 // Init() can happen after the browser is running, so catch up with any | 130 // Init() can happen after the browser is running, so catch up with any |
103 // windows that already exist. | 131 // windows that already exist. |
104 for (chrome::BrowserIterator it; !it.done(); it.Next()) { | 132 for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
105 RegisterForBrowserNotifications(*it); | 133 RegisterForBrowserNotifications(*it); |
106 | 134 |
107 // Also catch up our internal bookkeeping of tab entries. | 135 // Also catch up our internal bookkeeping of tab entries. |
108 Browser* browser = *it; | 136 Browser* browser = *it; |
109 if (browser->tab_strip_model()) { | 137 if (browser->tab_strip_model()) { |
110 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { | 138 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { |
111 WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(i); | 139 WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(i); |
112 int tab_id = ExtensionTabUtil::GetTabId(contents); | 140 int tab_id = ExtensionTabUtil::GetTabId(contents); |
113 tab_entries_[tab_id] = TabEntry(); | 141 tab_entries_[tab_id] = TabEntry(contents); |
114 } | 142 } |
115 } | 143 } |
116 } | 144 } |
117 } | 145 } |
118 | 146 |
119 TabsEventRouter::~TabsEventRouter() { | 147 TabsEventRouter::~TabsEventRouter() { |
120 BrowserList::RemoveObserver(this); | 148 BrowserList::RemoveObserver(this); |
121 } | 149 } |
122 | 150 |
123 void TabsEventRouter::OnBrowserAdded(Browser* browser) { | 151 void TabsEventRouter::OnBrowserAdded(Browser* browser) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 | 236 |
209 RegisterForTabNotifications(contents); | 237 RegisterForTabNotifications(contents); |
210 } | 238 } |
211 | 239 |
212 void TabsEventRouter::TabInsertedAt(WebContents* contents, | 240 void TabsEventRouter::TabInsertedAt(WebContents* contents, |
213 int index, | 241 int index, |
214 bool active) { | 242 bool active) { |
215 // If tab is new, send created event. | 243 // If tab is new, send created event. |
216 int tab_id = ExtensionTabUtil::GetTabId(contents); | 244 int tab_id = ExtensionTabUtil::GetTabId(contents); |
217 if (!GetTabEntry(contents)) { | 245 if (!GetTabEntry(contents)) { |
218 tab_entries_[tab_id] = TabEntry(); | 246 tab_entries_[tab_id] = TabEntry(contents); |
219 | 247 |
220 TabCreatedAt(contents, index, active); | 248 TabCreatedAt(contents, index, active); |
221 return; | 249 return; |
222 } | 250 } |
223 | 251 |
224 scoped_ptr<base::ListValue> args(new base::ListValue); | 252 scoped_ptr<base::ListValue> args(new base::ListValue); |
225 args->Append(new FundamentalValue(tab_id)); | 253 args->Append(new FundamentalValue(tab_id)); |
226 | 254 |
227 base::DictionaryValue* object_args = new base::DictionaryValue(); | 255 base::DictionaryValue* object_args = new base::DictionaryValue(); |
228 object_args->Set(tabs_constants::kNewWindowIdKey, | 256 object_args->Set(tabs_constants::kNewWindowIdKey, |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 new FundamentalValue(to_index)); | 411 new FundamentalValue(to_index)); |
384 args->Append(object_args); | 412 args->Append(object_args); |
385 | 413 |
386 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); | 414 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); |
387 DispatchEvent(profile, | 415 DispatchEvent(profile, |
388 tabs::OnMoved::kEventName, | 416 tabs::OnMoved::kEventName, |
389 args.Pass(), | 417 args.Pass(), |
390 EventRouter::USER_GESTURE_UNKNOWN); | 418 EventRouter::USER_GESTURE_UNKNOWN); |
391 } | 419 } |
392 | 420 |
393 void TabsEventRouter::TabUpdated(WebContents* contents, bool did_navigate) { | 421 void TabsEventRouter::TabUpdated( |
394 TabEntry* entry = GetTabEntry(contents); | 422 TabsEventRouter::TabEntry* entry, |
395 scoped_ptr<base::DictionaryValue> changed_properties; | 423 scoped_ptr<base::DictionaryValue> changed_properties) { |
424 CHECK(entry->web_contents()); | |
396 | 425 |
397 CHECK(entry); | 426 const char* muteSwitch = switches::kEnableTabAudioMuting; |
not at google - send to devlin
2015/06/01 20:33:56
I don't think this alias is necessary, though for
Jared Sohn
2015/06/02 08:54:38
Oversight; removed.
On 2015/06/01 at 20:33:56, ka
| |
427 if (base::CommandLine::ForCurrentProcess()->HasSwitch(muteSwitch)) { | |
428 bool audible = entry->web_contents()->WasRecentlyAudible(); | |
429 if (entry->SetAudible(audible)) { | |
430 changed_properties->SetBoolean(tabs_constants::kAudibleKey, audible); | |
431 } | |
398 | 432 |
399 if (did_navigate) | 433 bool muted = entry->web_contents()->IsAudioMuted(); |
400 changed_properties.reset(entry->DidNavigate(contents)); | 434 if (entry->SetMuted(muted)) { |
401 else | 435 changed_properties->SetBoolean(tabs_constants::kMutedKey, muted); |
402 changed_properties.reset(entry->UpdateLoadState(contents)); | 436 changed_properties->SetString( |
437 tabs_constants::kMutedCauseKey, | |
438 chrome::GetTabAudioMutedCause(entry->web_contents())); | |
439 } | |
440 } | |
403 | 441 |
404 if (changed_properties) | 442 if (!changed_properties->empty()) { |
405 DispatchTabUpdatedEvent(contents, changed_properties.Pass()); | 443 DispatchTabUpdatedEvent(entry->web_contents(), changed_properties.Pass()); |
444 } | |
406 } | 445 } |
407 | 446 |
408 void TabsEventRouter::FaviconUrlUpdated(WebContents* contents) { | 447 void TabsEventRouter::FaviconUrlUpdated(WebContents* contents) { |
409 content::NavigationEntry* entry = | 448 content::NavigationEntry* entry = |
410 contents->GetController().GetVisibleEntry(); | 449 contents->GetController().GetVisibleEntry(); |
411 if (!entry || !entry->GetFavicon().valid) | 450 if (!entry || !entry->GetFavicon().valid) |
412 return; | 451 return; |
413 scoped_ptr<base::DictionaryValue> changed_properties( | 452 scoped_ptr<base::DictionaryValue> changed_properties( |
414 new base::DictionaryValue); | 453 new base::DictionaryValue); |
415 changed_properties->SetString( | 454 changed_properties->SetString( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 return NULL; | 525 return NULL; |
487 return &i->second; | 526 return &i->second; |
488 } | 527 } |
489 | 528 |
490 void TabsEventRouter::Observe(int type, | 529 void TabsEventRouter::Observe(int type, |
491 const content::NotificationSource& source, | 530 const content::NotificationSource& source, |
492 const content::NotificationDetails& details) { | 531 const content::NotificationDetails& details) { |
493 if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { | 532 if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { |
494 NavigationController* source_controller = | 533 NavigationController* source_controller = |
495 content::Source<NavigationController>(source).ptr(); | 534 content::Source<NavigationController>(source).ptr(); |
496 TabUpdated(source_controller->GetWebContents(), true); | 535 TabEntry* entry = GetTabEntry(source_controller->GetWebContents()); |
536 CHECK(entry); | |
537 TabUpdated(entry, entry->DidNavigate()); | |
497 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { | 538 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
498 // Tab was destroyed after being detached (without being re-attached). | 539 // Tab was destroyed after being detached (without being re-attached). |
499 WebContents* contents = content::Source<WebContents>(source).ptr(); | 540 WebContents* contents = content::Source<WebContents>(source).ptr(); |
500 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 541 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
501 content::Source<NavigationController>(&contents->GetController())); | 542 content::Source<NavigationController>(&contents->GetController())); |
502 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 543 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
503 content::Source<WebContents>(contents)); | 544 content::Source<WebContents>(contents)); |
504 registrar_.Remove(this, chrome::NOTIFICATION_FAVICON_UPDATED, | 545 registrar_.Remove(this, chrome::NOTIFICATION_FAVICON_UPDATED, |
505 content::Source<WebContents>(contents)); | 546 content::Source<WebContents>(contents)); |
506 } else if (type == chrome::NOTIFICATION_FAVICON_UPDATED) { | 547 } else if (type == chrome::NOTIFICATION_FAVICON_UPDATED) { |
507 bool icon_url_changed = *content::Details<bool>(details).ptr(); | 548 bool icon_url_changed = *content::Details<bool>(details).ptr(); |
508 if (icon_url_changed) | 549 if (icon_url_changed) |
509 FaviconUrlUpdated(content::Source<WebContents>(source).ptr()); | 550 FaviconUrlUpdated(content::Source<WebContents>(source).ptr()); |
510 } else { | 551 } else { |
511 NOTREACHED(); | 552 NOTREACHED(); |
512 } | 553 } |
513 } | 554 } |
514 | 555 |
515 void TabsEventRouter::TabChangedAt(WebContents* contents, | 556 void TabsEventRouter::TabChangedAt(WebContents* contents, |
516 int index, | 557 int index, |
517 TabChangeType change_type) { | 558 TabChangeType change_type) { |
518 TabUpdated(contents, false); | 559 TabEntry* entry = GetTabEntry(contents); |
560 CHECK(entry); | |
561 TabUpdated(entry, entry->UpdateLoadState()); | |
519 } | 562 } |
520 | 563 |
521 void TabsEventRouter::TabReplacedAt(TabStripModel* tab_strip_model, | 564 void TabsEventRouter::TabReplacedAt(TabStripModel* tab_strip_model, |
522 WebContents* old_contents, | 565 WebContents* old_contents, |
523 WebContents* new_contents, | 566 WebContents* new_contents, |
524 int index) { | 567 int index) { |
525 // Notify listeners that the next tabs closing or being added are due to | 568 // Notify listeners that the next tabs closing or being added are due to |
526 // WebContents being swapped. | 569 // WebContents being swapped. |
527 const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents); | 570 const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents); |
528 const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents); | 571 const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents); |
529 scoped_ptr<base::ListValue> args(new base::ListValue); | 572 scoped_ptr<base::ListValue> args(new base::ListValue); |
530 args->Append(new FundamentalValue(new_tab_id)); | 573 args->Append(new FundamentalValue(new_tab_id)); |
531 args->Append(new FundamentalValue(old_tab_id)); | 574 args->Append(new FundamentalValue(old_tab_id)); |
532 | 575 |
533 DispatchEvent(Profile::FromBrowserContext(new_contents->GetBrowserContext()), | 576 DispatchEvent(Profile::FromBrowserContext(new_contents->GetBrowserContext()), |
534 tabs::OnReplaced::kEventName, | 577 tabs::OnReplaced::kEventName, |
535 args.Pass(), | 578 args.Pass(), |
536 EventRouter::USER_GESTURE_UNKNOWN); | 579 EventRouter::USER_GESTURE_UNKNOWN); |
537 | 580 |
538 // Update tab_entries_. | 581 // Update tab_entries_. |
539 const int removed_count = tab_entries_.erase(old_tab_id); | 582 const int removed_count = tab_entries_.erase(old_tab_id); |
540 DCHECK_GT(removed_count, 0); | 583 DCHECK_GT(removed_count, 0); |
541 UnregisterForTabNotifications(old_contents); | 584 UnregisterForTabNotifications(old_contents); |
542 | 585 |
543 if (!GetTabEntry(new_contents)) { | 586 if (!GetTabEntry(new_contents)) { |
544 tab_entries_[new_tab_id] = TabEntry(); | 587 tab_entries_[new_tab_id] = TabEntry(new_contents); |
545 RegisterForTabNotifications(new_contents); | 588 RegisterForTabNotifications(new_contents); |
546 } | 589 } |
547 } | 590 } |
548 | 591 |
549 void TabsEventRouter::TabPinnedStateChanged(WebContents* contents, int index) { | 592 void TabsEventRouter::TabPinnedStateChanged(WebContents* contents, int index) { |
550 TabStripModel* tab_strip = NULL; | 593 TabStripModel* tab_strip = NULL; |
551 int tab_index; | 594 int tab_index; |
552 | 595 |
553 if (ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index)) { | 596 if (ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index)) { |
554 scoped_ptr<base::DictionaryValue> changed_properties( | 597 scoped_ptr<base::DictionaryValue> changed_properties( |
(...skipping 24 matching lines...) Expand all Loading... | |
579 // Dispatch the |onZoomChange| event. | 622 // Dispatch the |onZoomChange| event. |
580 Profile* profile = Profile::FromBrowserContext( | 623 Profile* profile = Profile::FromBrowserContext( |
581 data.web_contents->GetBrowserContext()); | 624 data.web_contents->GetBrowserContext()); |
582 DispatchEvent(profile, | 625 DispatchEvent(profile, |
583 tabs::OnZoomChange::kEventName, | 626 tabs::OnZoomChange::kEventName, |
584 api::tabs::OnZoomChange::Create(zoom_change_info), | 627 api::tabs::OnZoomChange::Create(zoom_change_info), |
585 EventRouter::USER_GESTURE_UNKNOWN); | 628 EventRouter::USER_GESTURE_UNKNOWN); |
586 } | 629 } |
587 | 630 |
588 } // namespace extensions | 631 } // namespace extensions |
OLD | NEW |