1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2014 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/router.h" 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h> 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <utility> 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/bind.h" 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/location.h" 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/logging.h" 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/memory/ptr_util.h" 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/stl_util.h" 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/sync_call_restrictions.h" 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace internal { 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// ---------------------------------------------------------------------------- 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace { 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid DCheckIfInvalid(const base::WeakPtr<Router>& router, 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const std::string& message) { 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool is_valid = router && !router->encountered_error() && router->is_valid(); 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!is_valid) << message; 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass ResponderThunk : public MessageReceiverWithStatus { 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public: 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez explicit ResponderThunk(const base::WeakPtr<Router>& router, 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> runner) 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : router_(router), 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez accept_was_invoked_(false), 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task_runner_(std::move(runner)) {} 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ~ResponderThunk() override { 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!accept_was_invoked_) { 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The Mojo application handled a message that was expecting a response 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // but did not send a response. 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We raise an error to signal the calling application that an error 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // condition occurred. Without this the calling application would have no 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // way of knowing it should stop waiting for a response. 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (task_runner_->RunsTasksOnCurrentThread()) { 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Please note that even if this code is run from a different task 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // runner on the same thread as |task_runner_|, it is okay to directly 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // call Router::RaiseError(), because it will raise error from the 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // correct task runner asynchronously. 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (router_) 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->RaiseError(); 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task_runner_->PostTask(FROM_HERE, 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&Router::RaiseError, router_)); 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // MessageReceiver implementation: 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool Accept(Message* message) override { 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->RunsTasksOnCurrentThread()); 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez accept_was_invoked_ = true; 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(message->has_flag(Message::kFlagIsResponse)); 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool result = false; 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (router_) 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result = router_->Accept(message); 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return result; 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // MessageReceiverWithStatus implementation: 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool IsValid() override { 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->RunsTasksOnCurrentThread()); 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return router_ && !router_->encountered_error() && router_->is_valid(); 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void DCheckInvalid(const std::string& message) override { 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (task_runner_->RunsTasksOnCurrentThread()) { 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCheckIfInvalid(router_, message); 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task_runner_->PostTask(FROM_HERE, 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&DCheckIfInvalid, router_, message)); 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private: 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::WeakPtr<Router> router_; 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool accept_was_invoked_; 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// ---------------------------------------------------------------------------- 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezRouter::SyncResponseInfo::SyncResponseInfo(bool* in_response_received) 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : response_received(in_response_received) {} 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezRouter::SyncResponseInfo::~SyncResponseInfo() {} 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// ---------------------------------------------------------------------------- 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezRouter::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router) 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : router_(router) { 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezRouter::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() { 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Router::HandleIncomingMessageThunk::Accept(Message* message) { 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return router_->HandleIncomingMessage(message); 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// ---------------------------------------------------------------------------- 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezRouter::Router(ScopedMessagePipeHandle message_pipe, 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez FilterChain filters, 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool expects_sync_requests, 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> runner) 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : thunk_(this), 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez filters_(std::move(filters)), 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_(std::move(message_pipe), 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Connector::SINGLE_THREADED_SEND, 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::move(runner)), 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez incoming_receiver_(nullptr), 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez next_request_id_(0), 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez testing_mode_(false), 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pending_task_for_messages_(false), 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encountered_error_(false), 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez weak_factory_(this) { 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez filters_.SetSink(&thunk_); 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (expects_sync_requests) 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.AllowWokenUpBySyncWatchOnSameThread(); 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.set_incoming_receiver(filters_.GetHead()); 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.set_connection_error_handler( 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&Router::OnConnectionError, base::Unretained(this))); 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezRouter::~Router() {} 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Router::Accept(Message* message) { 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!message->has_flag(Message::kFlagExpectsResponse)); 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return connector_.Accept(message); 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Router::AcceptWithResponder(Message* message, MessageReceiver* responder) { 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(message->has_flag(Message::kFlagExpectsResponse)); 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Reserve 0 in case we want it to convey special meaning in the future. 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint64_t request_id = next_request_id_++; 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (request_id == 0) 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez request_id = next_request_id_++; 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool is_sync = message->has_flag(Message::kFlagIsSync); 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez message->set_request_id(request_id); 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!connector_.Accept(message)) 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!is_sync) { 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We assume ownership of |responder|. 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez async_responders_[request_id] = base::WrapUnique(responder); 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SyncCallRestrictions::AssertSyncCallAllowed(); 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool response_received = false; 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<MessageReceiver> sync_responder(responder); 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_responses_.insert(std::make_pair( 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez request_id, base::WrapUnique(new SyncResponseInfo(&response_received)))); 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::WeakPtr<Router> weak_self = weak_factory_.GetWeakPtr(); 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.SyncWatch(&response_received); 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Make sure that this instance hasn't been destroyed. 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (weak_self) { 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(ContainsKey(sync_responses_, request_id)); 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto iter = sync_responses_.find(request_id); 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(&response_received, iter->second->response_received); 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (response_received) { 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<Message> response = std::move(iter->second->response); 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ignore_result(sync_responder->Accept(response.get())); 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_responses_.erase(iter); 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Return true means that we take ownership of |responder|. 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Router::EnableTestingMode() { 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez testing_mode_ = true; 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.set_enforce_errors_from_incoming_receiver(false); 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Router::HandleIncomingMessage(Message* message) { 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const bool during_sync_call = 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.during_sync_handle_watcher_callback(); 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!message->has_flag(Message::kFlagIsSync) && 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (during_sync_call || !pending_messages_.empty())) { 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<Message> pending_message(new Message); 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez message->MoveTo(pending_message.get()); 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pending_messages_.push(std::move(pending_message)); 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!pending_task_for_messages_) { 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pending_task_for_messages_ = true; 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.task_runner()->PostTask( 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez FROM_HERE, base::Bind(&Router::HandleQueuedMessages, 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez weak_factory_.GetWeakPtr())); 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return HandleMessageInternal(message); 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Router::HandleQueuedMessages() { 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(pending_task_for_messages_); 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::WeakPtr<Router> weak_self = weak_factory_.GetWeakPtr(); 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez while (!pending_messages_.empty()) { 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<Message> message(std::move(pending_messages_.front())); 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pending_messages_.pop(); 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool result = HandleMessageInternal(message.get()); 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!weak_self) 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!result && !testing_mode_) { 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.RaiseError(); 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pending_task_for_messages_ = false; 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We may have already seen a connection error from the connector, but 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // haven't notified the user because we want to process all the queued 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // messages first. We should do it now. 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (connector_.encountered_error() && !encountered_error_) 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez OnConnectionError(); 250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Router::HandleMessageInternal(Message* message) { 253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (message->has_flag(Message::kFlagExpectsResponse)) { 254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!incoming_receiver_) 255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MessageReceiverWithStatus* responder = new ResponderThunk( 258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez weak_factory_.GetWeakPtr(), connector_.task_runner()); 259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool ok = incoming_receiver_->AcceptWithResponder(message, responder); 260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!ok) 261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez delete responder; 262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ok; 263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else if (message->has_flag(Message::kFlagIsResponse)) { 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint64_t request_id = message->request_id(); 266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (message->has_flag(Message::kFlagIsSync)) { 268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto it = sync_responses_.find(request_id); 269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (it == sync_responses_.end()) { 270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(testing_mode_); 271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez it->second->response.reset(new Message()); 274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez message->MoveTo(it->second->response.get()); 275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *it->second->response_received = true; 276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto it = async_responders_.find(request_id); 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (it == async_responders_.end()) { 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(testing_mode_); 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<MessageReceiver> responder = std::move(it->second); 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez async_responders_.erase(it); 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return responder->Accept(message); 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!incoming_receiver_) 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return incoming_receiver_->Accept(message); 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Router::OnConnectionError() { 296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (encountered_error_) 297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!pending_messages_.empty()) { 300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // After all the pending messages are processed, we will check whether an 301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // error has been encountered and run the user's connection error handler 302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // if necessary. 303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(pending_task_for_messages_); 304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (connector_.during_sync_handle_watcher_callback()) { 308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We don't want the error handler to reenter an ongoing sync call. 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.task_runner()->PostTask( 310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez FROM_HERE, 311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&Router::OnConnectionError, weak_factory_.GetWeakPtr())); 312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encountered_error_ = true; 316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!error_handler_.is_null()) 317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez error_handler_.Run(); 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// ---------------------------------------------------------------------------- 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace internal 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 324