Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: chrome/browser/media/router/media_router_mojo_impl.cc

Issue 1419853003: [Media Router] Connection reattempt logic and bound pending request queue size. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/media/router/media_router_mojo_impl.h" 5 #include "chrome/browser/media/router/media_router_mojo_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/guid.h" 8 #include "base/guid.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_vector.h" 10 #include "base/memory/scoped_vector.h"
(...skipping 13 matching lines...) Expand all
24 DVLOG(level) << "MR #" << instance_id_ << ": " 24 DVLOG(level) << "MR #" << instance_id_ << ": "
25 25
26 #define DLOG_WITH_INSTANCE(level) DLOG(level) << "MR #" << instance_id_ << ": " 26 #define DLOG_WITH_INSTANCE(level) DLOG(level) << "MR #" << instance_id_ << ": "
27 27
28 namespace media_router { 28 namespace media_router {
29 29
30 using SinkAvailability = interfaces::MediaRouter::SinkAvailability; 30 using SinkAvailability = interfaces::MediaRouter::SinkAvailability;
31 31
32 namespace { 32 namespace {
33 33
34 // TODO(imcheng): We should handle failure in this case. One way is to invoke
35 // all pending requests with failure. (crbug.com/490787)
36 void EventPageWakeComplete(bool success) {
37 if (!success)
38 LOG(ERROR) << "An error encountered while waking the event page.";
39 }
40
41 scoped_ptr<content::PresentationSessionMessage> 34 scoped_ptr<content::PresentationSessionMessage>
42 ConvertToPresentationSessionMessage(interfaces::RouteMessagePtr input) { 35 ConvertToPresentationSessionMessage(interfaces::RouteMessagePtr input) {
43 DCHECK(!input.is_null()); 36 DCHECK(!input.is_null());
44 scoped_ptr<content::PresentationSessionMessage> output; 37 scoped_ptr<content::PresentationSessionMessage> output;
45 switch (input->type) { 38 switch (input->type) {
46 case interfaces::RouteMessage::Type::TYPE_TEXT: { 39 case interfaces::RouteMessage::Type::TYPE_TEXT: {
47 DCHECK(!input->message.is_null()); 40 DCHECK(!input->message.is_null());
48 DCHECK(input->data.is_null()); 41 DCHECK(input->data.is_null());
49 output.reset(new content::PresentationSessionMessage( 42 output.reset(new content::PresentationSessionMessage(
50 content::PresentationMessageType::TEXT)); 43 content::PresentationMessageType::TEXT));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 router_->UpdateHasLocalRoute(has_local_route); 90 router_->UpdateHasLocalRoute(has_local_route);
98 } 91 }
99 92
100 // TODO(mfoltz): Flip the default sink availability to UNAVAILABLE, once the 93 // TODO(mfoltz): Flip the default sink availability to UNAVAILABLE, once the
101 // MRPM sends initial availability status. 94 // MRPM sends initial availability status.
102 MediaRouterMojoImpl::MediaRouterMojoImpl( 95 MediaRouterMojoImpl::MediaRouterMojoImpl(
103 extensions::EventPageTracker* event_page_tracker) 96 extensions::EventPageTracker* event_page_tracker)
104 : event_page_tracker_(event_page_tracker), 97 : event_page_tracker_(event_page_tracker),
105 instance_id_(base::GenerateGUID()), 98 instance_id_(base::GenerateGUID()),
106 has_local_route_(false), 99 has_local_route_(false),
107 availability_(interfaces::MediaRouter::SINK_AVAILABILITY_AVAILABLE) { 100 availability_(interfaces::MediaRouter::SINK_AVAILABILITY_AVAILABLE),
101 wakeup_attempt_count_(0),
102 weak_factory_(this) {
108 DCHECK(event_page_tracker_); 103 DCHECK(event_page_tracker_);
109 } 104 }
110 105
111 MediaRouterMojoImpl::~MediaRouterMojoImpl() { 106 MediaRouterMojoImpl::~MediaRouterMojoImpl() {
112 DCHECK(thread_checker_.CalledOnValidThread()); 107 DCHECK(thread_checker_.CalledOnValidThread());
113 108
114 // Make sure |routes_observer_| is destroyed first, because it triggers 109 // Make sure |routes_observer_| is destroyed first, because it triggers
115 // additional cleanup logic in this class that depends on other fields. 110 // additional cleanup logic in this class that depends on other fields.
116 routes_observer_.reset(); 111 routes_observer_.reset();
117 } 112 }
(...skipping 16 matching lines...) Expand all
134 DCHECK(thread_checker_.CalledOnValidThread()); 129 DCHECK(thread_checker_.CalledOnValidThread());
135 130
136 binding_.reset( 131 binding_.reset(
137 new mojo::Binding<interfaces::MediaRouter>(this, request.Pass())); 132 new mojo::Binding<interfaces::MediaRouter>(this, request.Pass()));
138 binding_->set_connection_error_handler(base::Bind( 133 binding_->set_connection_error_handler(base::Bind(
139 &MediaRouterMojoImpl::OnConnectionError, base::Unretained(this))); 134 &MediaRouterMojoImpl::OnConnectionError, base::Unretained(this)));
140 135
141 media_route_provider_extension_id_ = extension_id; 136 media_route_provider_extension_id_ = extension_id;
142 } 137 }
143 138
144 // TODO(imcheng): If this occurs while there are pending requests, we should
145 // probably invoke them with failure. (crbug.com/490787)
146 void MediaRouterMojoImpl::OnConnectionError() { 139 void MediaRouterMojoImpl::OnConnectionError() {
147 DCHECK(thread_checker_.CalledOnValidThread()); 140 DCHECK(thread_checker_.CalledOnValidThread());
148 141
149 media_route_provider_.reset(); 142 media_route_provider_.reset();
150 binding_.reset(); 143 binding_.reset();
144
145 // If |OnConnectionError| is invoked while there are pending requests, then
146 // it means we tried to wake the extension, but weren't able to complete the
147 // connection to media route provider. Since we do not know whether the error
148 // is transient, reattempt the wakeup.
149 if (!pending_requests_.empty()) {
150 DLOG_WITH_INSTANCE(ERROR) << "A connection error while there are pending "
151 "requests.";
152 AttemptWakeEventPage();
153 }
151 } 154 }
152 155
153 void MediaRouterMojoImpl::RegisterMediaRouteProvider( 156 void MediaRouterMojoImpl::RegisterMediaRouteProvider(
154 interfaces::MediaRouteProviderPtr media_route_provider_ptr, 157 interfaces::MediaRouteProviderPtr media_route_provider_ptr,
155 const interfaces::MediaRouter::RegisterMediaRouteProviderCallback& 158 const interfaces::MediaRouter::RegisterMediaRouteProviderCallback&
156 callback) { 159 callback) {
157 DCHECK(thread_checker_.CalledOnValidThread()); 160 DCHECK(thread_checker_.CalledOnValidThread());
158 161
162 if (event_page_tracker_->IsEventPageSuspended(
163 media_route_provider_extension_id_)) {
164 DVLOG_WITH_INSTANCE(1)
165 << "ExecutePendingRequests was called while extension is suspended.";
166 media_route_provider_.reset();
167 AttemptWakeEventPage();
168 return;
169 }
170
159 media_route_provider_ = media_route_provider_ptr.Pass(); 171 media_route_provider_ = media_route_provider_ptr.Pass();
160 media_route_provider_.set_connection_error_handler(base::Bind( 172 media_route_provider_.set_connection_error_handler(base::Bind(
161 &MediaRouterMojoImpl::OnConnectionError, base::Unretained(this))); 173 &MediaRouterMojoImpl::OnConnectionError, base::Unretained(this)));
162 callback.Run(instance_id_); 174 callback.Run(instance_id_);
163 ExecutePendingRequests(); 175 ExecutePendingRequests();
176 wakeup_attempt_count_ = 0;
164 } 177 }
165 178
166 void MediaRouterMojoImpl::OnIssue(const interfaces::IssuePtr issue) { 179 void MediaRouterMojoImpl::OnIssue(const interfaces::IssuePtr issue) {
167 DCHECK(thread_checker_.CalledOnValidThread()); 180 DCHECK(thread_checker_.CalledOnValidThread());
168 DVLOG_WITH_INSTANCE(1) << "OnIssue " << issue->title; 181 DVLOG_WITH_INSTANCE(1) << "OnIssue " << issue->title;
169 const Issue& issue_converted = issue.To<Issue>(); 182 const Issue& issue_converted = issue.To<Issue>();
170 issue_manager_.AddIssue(issue_converted); 183 issue_manager_.AddIssue(issue_converted);
171 } 184 }
172 185
173 void MediaRouterMojoImpl::OnSinksReceived( 186 void MediaRouterMojoImpl::OnSinksReceived(
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 media_route_provider_->StartObservingMediaRoutes(); 691 media_route_provider_->StartObservingMediaRoutes();
679 } 692 }
680 693
681 void MediaRouterMojoImpl::DoStopObservingMediaRoutes() { 694 void MediaRouterMojoImpl::DoStopObservingMediaRoutes() {
682 DVLOG_WITH_INSTANCE(1) << "DoStopObservingMediaRoutes"; 695 DVLOG_WITH_INSTANCE(1) << "DoStopObservingMediaRoutes";
683 media_route_provider_->StopObservingMediaRoutes(); 696 media_route_provider_->StopObservingMediaRoutes();
684 } 697 }
685 698
686 void MediaRouterMojoImpl::EnqueueTask(const base::Closure& closure) { 699 void MediaRouterMojoImpl::EnqueueTask(const base::Closure& closure) {
687 pending_requests_.push_back(closure); 700 pending_requests_.push_back(closure);
701 if (pending_requests_.size() > kMaxPendingRequests) {
702 DLOG_WITH_INSTANCE(ERROR) << "Reached max queue size. Dropping oldest "
703 << "request.";
704 pending_requests_.pop_front();
705 }
688 DVLOG_WITH_INSTANCE(2) << "EnqueueTask (queue-length=" 706 DVLOG_WITH_INSTANCE(2) << "EnqueueTask (queue-length="
689 << pending_requests_.size() << ")"; 707 << pending_requests_.size() << ")";
690 } 708 }
691 709
692 void MediaRouterMojoImpl::RunOrDefer(const base::Closure& request) { 710 void MediaRouterMojoImpl::RunOrDefer(const base::Closure& request) {
693 DCHECK(event_page_tracker_); 711 DCHECK(event_page_tracker_);
694 712
695 if (media_route_provider_extension_id_.empty()) { 713 if (media_route_provider_extension_id_.empty()) {
696 DVLOG_WITH_INSTANCE(1) << "Extension ID not known yet."; 714 DVLOG_WITH_INSTANCE(1) << "Extension ID not known yet.";
697 EnqueueTask(request); 715 EnqueueTask(request);
698 } else if (event_page_tracker_->IsEventPageSuspended( 716 } else if (event_page_tracker_->IsEventPageSuspended(
699 media_route_provider_extension_id_)) { 717 media_route_provider_extension_id_)) {
700 DVLOG_WITH_INSTANCE(1) << "Waking event page."; 718 DVLOG_WITH_INSTANCE(1) << "Waking event page.";
701 EnqueueTask(request); 719 EnqueueTask(request);
702 if (!event_page_tracker_->WakeEventPage( 720 AttemptWakeEventPage();
703 media_route_provider_extension_id_,
704 base::Bind(&EventPageWakeComplete))) {
705 LOG(ERROR) << "An error encountered while waking the event page.";
706 }
707 media_route_provider_.reset(); 721 media_route_provider_.reset();
708 } else if (!media_route_provider_) { 722 } else if (!media_route_provider_) {
709 DVLOG_WITH_INSTANCE(1) << "Extension is awake, awaiting ProvideMediaRouter " 723 DVLOG_WITH_INSTANCE(1) << "Extension is awake, awaiting ProvideMediaRouter "
710 " to be called."; 724 " to be called.";
711 EnqueueTask(request); 725 EnqueueTask(request);
712 } else { 726 } else {
713 request.Run(); 727 request.Run();
714 } 728 }
715 } 729 }
716 730
731 void MediaRouterMojoImpl::AttemptWakeEventPage() {
732 ++wakeup_attempt_count_;
733 if (wakeup_attempt_count_ > kMaxWakeupAttemptCount) {
734 DLOG_WITH_INSTANCE(ERROR) << "Attempted too many times to wake up event "
735 << "page.";
736 DrainPendingRequests();
737 wakeup_attempt_count_ = 0;
738 return;
739 }
740
741 DVLOG_WITH_INSTANCE(1) << "Attempting to wake up event page: attempt "
742 << wakeup_attempt_count_;
743
744 // This return false if the extension is already awake.
745 // Callback is bound using WeakPtr because |event_page_tracker_| outlives
746 // |this|.
747 if (!event_page_tracker_->WakeEventPage(
748 media_route_provider_extension_id_,
749 base::Bind(&MediaRouterMojoImpl::EventPageWakeComplete,
750 weak_factory_.GetWeakPtr()))) {
751 DLOG_WITH_INSTANCE(ERROR) << "Failed to schedule a wakeup for event page.";
752 }
753 }
754
717 void MediaRouterMojoImpl::ExecutePendingRequests() { 755 void MediaRouterMojoImpl::ExecutePendingRequests() {
718 DCHECK(thread_checker_.CalledOnValidThread()); 756 DCHECK(thread_checker_.CalledOnValidThread());
719 DCHECK(media_route_provider_); 757 DCHECK(media_route_provider_);
720 DCHECK(event_page_tracker_); 758 DCHECK(event_page_tracker_);
721 DCHECK(!media_route_provider_extension_id_.empty()); 759 DCHECK(!media_route_provider_extension_id_.empty());
722 760
723 if (event_page_tracker_->IsEventPageSuspended(
724 media_route_provider_extension_id_)) {
725 DVLOG_WITH_INSTANCE(1)
726 << "ExecutePendingRequests was called while extension is suspended.";
727 return;
728 }
729
730 for (const auto& next_request : pending_requests_) 761 for (const auto& next_request : pending_requests_)
731 next_request.Run(); 762 next_request.Run();
732 763
733 pending_requests_.clear(); 764 pending_requests_.clear();
734 } 765 }
735 766
767 void MediaRouterMojoImpl::EventPageWakeComplete(bool success) {
768 if (success)
769 return;
770
771 // This is likely an non-retriable error. Drop the pending requests.
772 DLOG_WITH_INSTANCE(ERROR)
773 << "An error encountered while waking the event page.";
774 DrainPendingRequests();
775 }
776
777 void MediaRouterMojoImpl::DrainPendingRequests() {
778 DLOG_WITH_INSTANCE(ERROR)
779 << "Draining request queue. (queue-length=" << pending_requests_.size()
780 << ")";
781 pending_requests_.clear();
782 }
783
736 } // namespace media_router 784 } // namespace media_router
OLDNEW
« no previous file with comments | « chrome/browser/media/router/media_router_mojo_impl.h ('k') | chrome/browser/media/router/media_router_mojo_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698