OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/copresence/copresence_manager_impl.h" | 5 #include "components/copresence/copresence_manager_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/strings/stringprintf.h" |
8 #include "components/copresence/public/copresence_delegate.h" | 9 #include "components/copresence/public/copresence_delegate.h" |
9 #include "components/copresence/public/whispernet_client.h" | 10 #include "components/copresence/public/whispernet_client.h" |
10 #include "components/copresence/rpc/rpc_handler.h" | 11 #include "components/copresence/rpc/rpc_handler.h" |
11 | 12 |
| 13 namespace { |
| 14 |
| 15 // Number of characters of suffix to log for auth tokens |
| 16 const int kTokenSuffix = 5; |
| 17 |
| 18 } // namespace |
| 19 |
12 namespace copresence { | 20 namespace copresence { |
13 | 21 |
14 PendingRequest::PendingRequest(const copresence::ReportRequest& report, | 22 PendingRequest::PendingRequest(const ReportRequest& report, |
15 const std::string app_id, | 23 const std::string& app_id, |
| 24 const std::string& auth_token, |
16 const StatusCallback& callback) | 25 const StatusCallback& callback) |
17 : report(report), app_id(app_id), callback(callback) { | 26 : report(new ReportRequest(report)), |
| 27 app_id(app_id), |
| 28 auth_token(auth_token), |
| 29 callback(callback) {} |
| 30 |
| 31 PendingRequest::~PendingRequest() {} |
| 32 |
| 33 // static |
| 34 scoped_ptr<CopresenceManager> CopresenceManager::Create( |
| 35 CopresenceDelegate* delegate) { |
| 36 return make_scoped_ptr(new CopresenceManagerImpl(delegate)); |
18 } | 37 } |
19 | 38 |
20 PendingRequest::~PendingRequest() { | |
21 } | |
22 | 39 |
23 // Public methods | 40 // Public methods |
24 | 41 |
25 CopresenceManagerImpl::~CopresenceManagerImpl() {} | 42 CopresenceManagerImpl::~CopresenceManagerImpl() { |
| 43 whispernet_init_callback_.Cancel(); |
| 44 } |
26 | 45 |
27 // Returns false if any operations were malformed. | 46 // Returns false if any operations were malformed. |
28 void CopresenceManagerImpl::ExecuteReportRequest( | 47 void CopresenceManagerImpl::ExecuteReportRequest( |
29 ReportRequest request, | 48 const ReportRequest& request, |
30 const std::string& app_id, | 49 const std::string& app_id, |
31 const StatusCallback& callback) { | 50 const StatusCallback& callback) { |
32 // Don't take on any more requests. We can't execute them since init failed. | 51 // If initialization has failed, reject all requests. |
33 if (init_failed_) { | 52 if (init_failed_) { |
34 callback.Run(FAIL); | 53 callback.Run(FAIL); |
35 return; | 54 return; |
36 } | 55 } |
37 | 56 |
38 DCHECK(rpc_handler_.get()); | 57 // Check if we are initialized enough to execute this request. |
| 58 // If we haven't seen this auth token yet, we need to register for it. |
| 59 // TODO(ckehoe): Queue per device ID instead of globally. |
| 60 DCHECK(rpc_handler_); |
| 61 const std::string& auth_token = delegate_->GetAuthToken(); |
| 62 if (!rpc_handler_->IsRegisteredForToken(auth_token)) { |
| 63 std::string token_str = auth_token.empty() ? "(anonymous)" : |
| 64 base::StringPrintf("(token ...%s)", |
| 65 auth_token.substr(auth_token.length() - kTokenSuffix, |
| 66 kTokenSuffix).c_str()); |
| 67 rpc_handler_->RegisterForToken( |
| 68 auth_token, |
| 69 // The manager owns the RpcHandler, so this callback cannot outlive us. |
| 70 base::Bind(&CopresenceManagerImpl::InitStepComplete, |
| 71 base::Unretained(this), |
| 72 "Device registration " + token_str)); |
| 73 pending_init_operations_++; |
| 74 } |
| 75 |
| 76 // Execute the request if possible, or queue it |
| 77 // if initialization is still in progress. |
39 if (pending_init_operations_) { | 78 if (pending_init_operations_) { |
40 pending_requests_queue_.push_back( | 79 pending_requests_queue_.push_back( |
41 PendingRequest(request, app_id, callback)); | 80 new PendingRequest(request, app_id, auth_token, callback)); |
42 } else { | 81 } else { |
43 rpc_handler_->SendReportRequest( | 82 rpc_handler_->SendReportRequest( |
44 make_scoped_ptr(new copresence::ReportRequest(request)), | 83 make_scoped_ptr(new ReportRequest(request)), |
45 app_id, | 84 app_id, |
| 85 auth_token, |
46 callback); | 86 callback); |
47 } | 87 } |
48 } | 88 } |
49 | 89 |
50 // Private methods | 90 // Private methods |
51 | 91 |
52 CopresenceManagerImpl::CopresenceManagerImpl(CopresenceDelegate* delegate) | 92 CopresenceManagerImpl::CopresenceManagerImpl(CopresenceDelegate* delegate) |
53 : init_failed_(false), | 93 : init_failed_(false), |
| 94 // This callback gets cancelled when we are destroyed. |
| 95 whispernet_init_callback_( |
| 96 base::Bind(&CopresenceManagerImpl::InitStepComplete, |
| 97 base::Unretained(this), |
| 98 "Whispernet proxy initialization")), |
54 pending_init_operations_(0), | 99 pending_init_operations_(0), |
55 delegate_(delegate) { | 100 delegate_(delegate), |
| 101 rpc_handler_(new RpcHandler(delegate)) { |
56 DCHECK(delegate); | 102 DCHECK(delegate); |
| 103 DCHECK(delegate->GetWhispernetClient()); |
| 104 |
| 105 delegate->GetWhispernetClient()->Initialize( |
| 106 whispernet_init_callback_.callback()); |
| 107 pending_init_operations_++; |
57 } | 108 } |
58 | 109 |
59 void CopresenceManagerImpl::CompleteInitialization() { | 110 void CopresenceManagerImpl::CompleteInitialization() { |
60 if (pending_init_operations_) | 111 if (pending_init_operations_) |
61 return; | 112 return; |
62 | 113 |
63 DCHECK(rpc_handler_.get()); | 114 DCHECK(rpc_handler_.get()); |
64 if (!init_failed_) | 115 if (!init_failed_) |
65 rpc_handler_->ConnectToWhispernet(); | 116 rpc_handler_->ConnectToWhispernet(); |
66 | 117 |
67 for (PendingRequest& request : pending_requests_queue_) { | 118 // Not const because SendReportRequest takes ownership of the ReportRequests. |
| 119 // This is ok though, as the entire queue is deleted afterwards. |
| 120 for (PendingRequest* request : pending_requests_queue_) { |
68 if (init_failed_) { | 121 if (init_failed_) { |
69 request.callback.Run(FAIL); | 122 request->callback.Run(FAIL); |
70 } else { | 123 } else { |
71 rpc_handler_->SendReportRequest( | 124 rpc_handler_->SendReportRequest( |
72 make_scoped_ptr(new copresence::ReportRequest(request.report)), | 125 request->report.Pass(), |
73 request.app_id, | 126 request->app_id, |
74 request.callback); | 127 request->auth_token, |
| 128 request->callback); |
75 } | 129 } |
76 } | 130 } |
77 pending_requests_queue_.clear(); | 131 pending_requests_queue_.clear(); |
78 } | 132 } |
79 | 133 |
80 void CopresenceManagerImpl::InitStepComplete( | 134 void CopresenceManagerImpl::InitStepComplete( |
81 const std::string& step, bool success) { | 135 const std::string& step, bool success) { |
82 if (!success) { | 136 if (!success) { |
83 LOG(ERROR) << step << " failed!"; | 137 LOG(ERROR) << step << " failed!"; |
84 init_failed_ = true; | 138 init_failed_ = true; |
| 139 // TODO(ckehoe): Retry for registration failures. But maybe not here. |
85 } | 140 } |
86 | 141 |
87 DVLOG(3) << "Init step: " << step << " complete."; | 142 DVLOG(3) << step << " complete."; |
| 143 DCHECK(pending_init_operations_ > 0); |
88 pending_init_operations_--; | 144 pending_init_operations_--; |
89 CompleteInitialization(); | 145 CompleteInitialization(); |
90 } | 146 } |
91 | 147 |
92 } // namespace copresence | 148 } // namespace copresence |
OLD | NEW |