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 "remoting/host/setup/native_messaging_host.h" | 5 #include "remoting/host/setup/native_messaging_host.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 base::PlatformFile output, | 69 base::PlatformFile output, |
70 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 70 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
71 const base::Closure& quit_closure) | 71 const base::Closure& quit_closure) |
72 : caller_task_runner_(caller_task_runner), | 72 : caller_task_runner_(caller_task_runner), |
73 quit_closure_(quit_closure), | 73 quit_closure_(quit_closure), |
74 native_messaging_reader_(input), | 74 native_messaging_reader_(input), |
75 native_messaging_writer_(output), | 75 native_messaging_writer_(output), |
76 daemon_controller_(daemon_controller.Pass()), | 76 daemon_controller_(daemon_controller.Pass()), |
77 pairing_registry_(pairing_registry), | 77 pairing_registry_(pairing_registry), |
78 oauth_client_(oauth_client.Pass()), | 78 oauth_client_(oauth_client.Pass()), |
| 79 pending_requests_(0), |
| 80 shutdown_(false), |
79 weak_factory_(this) { | 81 weak_factory_(this) { |
80 weak_ptr_ = weak_factory_.GetWeakPtr(); | 82 weak_ptr_ = weak_factory_.GetWeakPtr(); |
81 } | 83 } |
82 | 84 |
83 NativeMessagingHost::~NativeMessagingHost() {} | 85 NativeMessagingHost::~NativeMessagingHost() {} |
84 | 86 |
85 void NativeMessagingHost::Start() { | 87 void NativeMessagingHost::Start() { |
86 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 88 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
87 | 89 |
88 native_messaging_reader_.Start( | 90 native_messaging_reader_.Start( |
89 base::Bind(&NativeMessagingHost::ProcessMessage, weak_ptr_), | 91 base::Bind(&NativeMessagingHost::ProcessMessage, weak_ptr_), |
90 base::Bind(&NativeMessagingHost::Shutdown, weak_ptr_)); | 92 base::Bind(&NativeMessagingHost::Shutdown, weak_ptr_)); |
91 } | 93 } |
92 | 94 |
93 void NativeMessagingHost::Shutdown() { | 95 void NativeMessagingHost::Shutdown() { |
94 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 96 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
95 if (!quit_closure_.is_null()) { | 97 |
| 98 if (shutdown_) |
| 99 return; |
| 100 |
| 101 shutdown_ = true; |
| 102 if (!pending_requests_) |
96 caller_task_runner_->PostTask(FROM_HERE, quit_closure_); | 103 caller_task_runner_->PostTask(FROM_HERE, quit_closure_); |
97 quit_closure_.Reset(); | |
98 } | |
99 } | 104 } |
100 | 105 |
101 void NativeMessagingHost::ProcessMessage(scoped_ptr<base::Value> message) { | 106 void NativeMessagingHost::ProcessMessage(scoped_ptr<base::Value> message) { |
102 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 107 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
103 | 108 |
104 // Don't process any more messages if Shutdown() has been called. | 109 // Don't process any more messages if Shutdown() has been called. |
105 if (quit_closure_.is_null()) | 110 if (shutdown_) |
106 return; | 111 return; |
107 | 112 |
108 const base::DictionaryValue* message_dict; | 113 const base::DictionaryValue* message_dict; |
109 if (!message->GetAsDictionary(&message_dict)) { | 114 if (!message->GetAsDictionary(&message_dict)) { |
110 LOG(ERROR) << "Expected DictionaryValue"; | 115 LOG(ERROR) << "Expected DictionaryValue"; |
111 Shutdown(); | 116 Shutdown(); |
112 return; | 117 return; |
113 } | 118 } |
114 | 119 |
115 scoped_ptr<base::DictionaryValue> response_dict(new base::DictionaryValue()); | 120 scoped_ptr<base::DictionaryValue> response_dict(new base::DictionaryValue()); |
116 | 121 |
117 // If the client supplies an ID, it will expect it in the response. This | 122 // If the client supplies an ID, it will expect it in the response. This |
118 // might be a string or a number, so cope with both. | 123 // might be a string or a number, so cope with both. |
119 const base::Value* id; | 124 const base::Value* id; |
120 if (message_dict->Get("id", &id)) | 125 if (message_dict->Get("id", &id)) |
121 response_dict->Set("id", id->DeepCopy()); | 126 response_dict->Set("id", id->DeepCopy()); |
122 | 127 |
123 std::string type; | 128 std::string type; |
124 if (!message_dict->GetString("type", &type)) { | 129 if (!message_dict->GetString("type", &type)) { |
125 LOG(ERROR) << "'type' not found"; | 130 LOG(ERROR) << "'type' not found"; |
126 Shutdown(); | 131 Shutdown(); |
127 return; | 132 return; |
128 } | 133 } |
129 | 134 |
130 response_dict->SetString("type", type + "Response"); | 135 response_dict->SetString("type", type + "Response"); |
131 | 136 |
| 137 DCHECK_GE(pending_requests_, 0); |
| 138 pending_requests_++; |
| 139 |
132 bool success = false; | 140 bool success = false; |
133 if (type == "hello") { | 141 if (type == "hello") { |
134 success = ProcessHello(*message_dict, response_dict.Pass()); | 142 success = ProcessHello(*message_dict, response_dict.Pass()); |
135 } else if (type == "clearPairedClients") { | 143 } else if (type == "clearPairedClients") { |
136 success = ProcessClearPairedClients(*message_dict, response_dict.Pass()); | 144 success = ProcessClearPairedClients(*message_dict, response_dict.Pass()); |
137 } else if (type == "deletePairedClient") { | 145 } else if (type == "deletePairedClient") { |
138 success = ProcessDeletePairedClient(*message_dict, response_dict.Pass()); | 146 success = ProcessDeletePairedClient(*message_dict, response_dict.Pass()); |
139 } else if (type == "getHostName") { | 147 } else if (type == "getHostName") { |
140 success = ProcessGetHostName(*message_dict, response_dict.Pass()); | 148 success = ProcessGetHostName(*message_dict, response_dict.Pass()); |
141 } else if (type == "getPinHash") { | 149 } else if (type == "getPinHash") { |
(...skipping 16 matching lines...) Expand all Loading... |
158 success = ProcessGetDaemonState(*message_dict, response_dict.Pass()); | 166 success = ProcessGetDaemonState(*message_dict, response_dict.Pass()); |
159 } else if (type == "getHostClientId") { | 167 } else if (type == "getHostClientId") { |
160 success = ProcessGetHostClientId(*message_dict, response_dict.Pass()); | 168 success = ProcessGetHostClientId(*message_dict, response_dict.Pass()); |
161 } else if (type == "getCredentialsFromAuthCode") { | 169 } else if (type == "getCredentialsFromAuthCode") { |
162 success = ProcessGetCredentialsFromAuthCode( | 170 success = ProcessGetCredentialsFromAuthCode( |
163 *message_dict, response_dict.Pass()); | 171 *message_dict, response_dict.Pass()); |
164 } else { | 172 } else { |
165 LOG(ERROR) << "Unsupported request type: " << type; | 173 LOG(ERROR) << "Unsupported request type: " << type; |
166 } | 174 } |
167 | 175 |
168 if (!success) | 176 if (!success) { |
| 177 pending_requests_--; |
| 178 DCHECK_GE(pending_requests_, 0); |
| 179 |
169 Shutdown(); | 180 Shutdown(); |
| 181 } |
170 } | 182 } |
171 | 183 |
172 bool NativeMessagingHost::ProcessHello( | 184 bool NativeMessagingHost::ProcessHello( |
173 const base::DictionaryValue& message, | 185 const base::DictionaryValue& message, |
174 scoped_ptr<base::DictionaryValue> response) { | 186 scoped_ptr<base::DictionaryValue> response) { |
175 response->SetString("version", STRINGIZE(VERSION)); | 187 response->SetString("version", STRINGIZE(VERSION)); |
176 scoped_ptr<base::ListValue> supported_features_list(new base::ListValue()); | 188 scoped_ptr<base::ListValue> supported_features_list(new base::ListValue()); |
177 supported_features_list->AppendStrings(std::vector<std::string>( | 189 supported_features_list->AppendStrings(std::vector<std::string>( |
178 kSupportedFeatures, kSupportedFeatures + arraysize(kSupportedFeatures))); | 190 kSupportedFeatures, kSupportedFeatures + arraysize(kSupportedFeatures))); |
179 response->Set("supportedFeatures", supported_features_list.release()); | 191 response->Set("supportedFeatures", supported_features_list.release()); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 scoped_ptr<base::DictionaryValue> response) { | 411 scoped_ptr<base::DictionaryValue> response) { |
400 if (!caller_task_runner_->BelongsToCurrentThread()) { | 412 if (!caller_task_runner_->BelongsToCurrentThread()) { |
401 caller_task_runner_->PostTask( | 413 caller_task_runner_->PostTask( |
402 FROM_HERE, base::Bind(&NativeMessagingHost::SendResponse, weak_ptr_, | 414 FROM_HERE, base::Bind(&NativeMessagingHost::SendResponse, weak_ptr_, |
403 base::Passed(&response))); | 415 base::Passed(&response))); |
404 return; | 416 return; |
405 } | 417 } |
406 | 418 |
407 if (!native_messaging_writer_.WriteMessage(*response)) | 419 if (!native_messaging_writer_.WriteMessage(*response)) |
408 Shutdown(); | 420 Shutdown(); |
| 421 |
| 422 pending_requests_--; |
| 423 DCHECK_GE(pending_requests_, 0); |
| 424 |
| 425 if (shutdown_ && !pending_requests_) |
| 426 caller_task_runner_->PostTask(FROM_HERE, quit_closure_); |
409 } | 427 } |
410 | 428 |
411 void NativeMessagingHost::SendConfigResponse( | 429 void NativeMessagingHost::SendConfigResponse( |
412 scoped_ptr<base::DictionaryValue> response, | 430 scoped_ptr<base::DictionaryValue> response, |
413 scoped_ptr<base::DictionaryValue> config) { | 431 scoped_ptr<base::DictionaryValue> config) { |
414 if (config) { | 432 if (config) { |
415 response->Set("config", config.release()); | 433 response->Set("config", config.release()); |
416 } else { | 434 } else { |
417 response->Set("config", Value::CreateNullValue()); | 435 response->Set("config", Value::CreateNullValue()); |
418 } | 436 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 oauth_client.Pass(), | 518 oauth_client.Pass(), |
501 read_file, write_file, | 519 read_file, write_file, |
502 message_loop.message_loop_proxy(), | 520 message_loop.message_loop_proxy(), |
503 run_loop.QuitClosure()); | 521 run_loop.QuitClosure()); |
504 host.Start(); | 522 host.Start(); |
505 run_loop.Run(); | 523 run_loop.Run(); |
506 return kSuccessExitCode; | 524 return kSuccessExitCode; |
507 } | 525 } |
508 | 526 |
509 } // namespace remoting | 527 } // namespace remoting |
OLD | NEW |