| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/serial/serial_connection.h" | 5 #include "chrome/browser/extensions/api/serial/serial_connection.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 SerialConnection::SerialConnection(const std::string& port, | 33 SerialConnection::SerialConnection(const std::string& port, |
| 34 const std::string& owner_extension_id) | 34 const std::string& owner_extension_id) |
| 35 : ApiResource(owner_extension_id), | 35 : ApiResource(owner_extension_id), |
| 36 port_(port), | 36 port_(port), |
| 37 persistent_(false), | 37 persistent_(false), |
| 38 buffer_size_(kDefaultBufferSize), | 38 buffer_size_(kDefaultBufferSize), |
| 39 receive_timeout_(0), | 39 receive_timeout_(0), |
| 40 send_timeout_(0), | 40 send_timeout_(0), |
| 41 paused_(false), | 41 paused_(false), |
| 42 io_handler_(SerialIoHandler::Create()) { | 42 io_handler_(SerialIoHandler::Create()) { |
| 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 43 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 44 } | 44 } |
| 45 | 45 |
| 46 SerialConnection::~SerialConnection() { | 46 SerialConnection::~SerialConnection() { |
| 47 DCHECK(open_complete_.is_null()); | 47 DCHECK(open_complete_.is_null()); |
| 48 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_DISCONNECTED); | 48 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_DISCONNECTED); |
| 49 io_handler_->CancelWrite(api::serial::SEND_ERROR_DISCONNECTED); | 49 io_handler_->CancelWrite(api::serial::SEND_ERROR_DISCONNECTED); |
| 50 Close(); | 50 Close(); |
| 51 } | 51 } |
| 52 | 52 |
| 53 bool SerialConnection::IsPersistent() const { return persistent(); } | 53 bool SerialConnection::IsPersistent() const { return persistent(); } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 65 } | 65 } |
| 66 | 66 |
| 67 void SerialConnection::set_paused(bool paused) { | 67 void SerialConnection::set_paused(bool paused) { |
| 68 paused_ = paused; | 68 paused_ = paused; |
| 69 if (paused) { | 69 if (paused) { |
| 70 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_NONE); | 70 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_NONE); |
| 71 } | 71 } |
| 72 } | 72 } |
| 73 | 73 |
| 74 void SerialConnection::Open(const OpenCompleteCallback& callback) { | 74 void SerialConnection::Open(const OpenCompleteCallback& callback) { |
| 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 75 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 76 DCHECK(open_complete_.is_null()); | 76 DCHECK(open_complete_.is_null()); |
| 77 open_complete_ = callback; | 77 open_complete_ = callback; |
| 78 BrowserThread::PostTask( | 78 BrowserThread::PostTask( |
| 79 BrowserThread::FILE, | 79 BrowserThread::FILE, |
| 80 FROM_HERE, | 80 FROM_HERE, |
| 81 base::Bind(&SerialConnection::StartOpen, base::Unretained(this))); | 81 base::Bind(&SerialConnection::StartOpen, base::Unretained(this))); |
| 82 } | 82 } |
| 83 | 83 |
| 84 void SerialConnection::Close() { | 84 void SerialConnection::Close() { |
| 85 DCHECK(open_complete_.is_null()); | 85 DCHECK(open_complete_.is_null()); |
| 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 86 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 87 if (file_.IsValid()) { | 87 if (file_.IsValid()) { |
| 88 BrowserThread::PostTask( | 88 BrowserThread::PostTask( |
| 89 BrowserThread::FILE, | 89 BrowserThread::FILE, |
| 90 FROM_HERE, | 90 FROM_HERE, |
| 91 base::Bind(&SerialConnection::DoClose, Passed(file_.Pass()))); | 91 base::Bind(&SerialConnection::DoClose, Passed(file_.Pass()))); |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 | 94 |
| 95 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) { | 95 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) { |
| 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 96 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 97 if (!receive_complete_.is_null()) | 97 if (!receive_complete_.is_null()) |
| 98 return false; | 98 return false; |
| 99 receive_complete_ = callback; | 99 receive_complete_ = callback; |
| 100 io_handler_->Read(buffer_size_); | 100 io_handler_->Read(buffer_size_); |
| 101 receive_timeout_task_.reset(); | 101 receive_timeout_task_.reset(); |
| 102 if (receive_timeout_ > 0) { | 102 if (receive_timeout_ > 0) { |
| 103 receive_timeout_task_.reset(new TimeoutTask( | 103 receive_timeout_task_.reset(new TimeoutTask( |
| 104 base::Bind(&SerialConnection::OnReceiveTimeout, AsWeakPtr()), | 104 base::Bind(&SerialConnection::OnReceiveTimeout, AsWeakPtr()), |
| 105 base::TimeDelta::FromMilliseconds(receive_timeout_))); | 105 base::TimeDelta::FromMilliseconds(receive_timeout_))); |
| 106 } | 106 } |
| 107 return true; | 107 return true; |
| 108 } | 108 } |
| 109 | 109 |
| 110 bool SerialConnection::Send(const std::string& data, | 110 bool SerialConnection::Send(const std::string& data, |
| 111 const SendCompleteCallback& callback) { | 111 const SendCompleteCallback& callback) { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 112 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 113 if (!send_complete_.is_null()) | 113 if (!send_complete_.is_null()) |
| 114 return false; | 114 return false; |
| 115 send_complete_ = callback; | 115 send_complete_ = callback; |
| 116 io_handler_->Write(data); | 116 io_handler_->Write(data); |
| 117 send_timeout_task_.reset(); | 117 send_timeout_task_.reset(); |
| 118 if (send_timeout_ > 0) { | 118 if (send_timeout_ > 0) { |
| 119 send_timeout_task_.reset(new TimeoutTask( | 119 send_timeout_task_.reset(new TimeoutTask( |
| 120 base::Bind(&SerialConnection::OnSendTimeout, AsWeakPtr()), | 120 base::Bind(&SerialConnection::OnSendTimeout, AsWeakPtr()), |
| 121 base::TimeDelta::FromMilliseconds(send_timeout_))); | 121 base::TimeDelta::FromMilliseconds(send_timeout_))); |
| 122 } | 122 } |
| 123 return true; | 123 return true; |
| 124 } | 124 } |
| 125 | 125 |
| 126 bool SerialConnection::Configure( | 126 bool SerialConnection::Configure( |
| 127 const api::serial::ConnectionOptions& options) { | 127 const api::serial::ConnectionOptions& options) { |
| 128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 128 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 129 if (options.persistent.get()) | 129 if (options.persistent.get()) |
| 130 set_persistent(*options.persistent); | 130 set_persistent(*options.persistent); |
| 131 if (options.name.get()) | 131 if (options.name.get()) |
| 132 set_name(*options.name); | 132 set_name(*options.name); |
| 133 if (options.buffer_size.get()) | 133 if (options.buffer_size.get()) |
| 134 set_buffer_size(*options.buffer_size); | 134 set_buffer_size(*options.buffer_size); |
| 135 if (options.receive_timeout.get()) | 135 if (options.receive_timeout.get()) |
| 136 set_receive_timeout(*options.receive_timeout); | 136 set_receive_timeout(*options.receive_timeout); |
| 137 if (options.send_timeout.get()) | 137 if (options.send_timeout.get()) |
| 138 set_send_timeout(*options.send_timeout); | 138 set_send_timeout(*options.send_timeout); |
| 139 bool success = ConfigurePort(options); | 139 bool success = ConfigurePort(options); |
| 140 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_NONE); | 140 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_NONE); |
| 141 return success; | 141 return success; |
| 142 } | 142 } |
| 143 | 143 |
| 144 void SerialConnection::SetIoHandlerForTest( | 144 void SerialConnection::SetIoHandlerForTest( |
| 145 scoped_refptr<SerialIoHandler> handler) { | 145 scoped_refptr<SerialIoHandler> handler) { |
| 146 io_handler_ = handler; | 146 io_handler_ = handler; |
| 147 } | 147 } |
| 148 | 148 |
| 149 bool SerialConnection::GetInfo(api::serial::ConnectionInfo* info) const { | 149 bool SerialConnection::GetInfo(api::serial::ConnectionInfo* info) const { |
| 150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 150 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 151 info->paused = paused_; | 151 info->paused = paused_; |
| 152 info->persistent = persistent_; | 152 info->persistent = persistent_; |
| 153 info->name = name_; | 153 info->name = name_; |
| 154 info->buffer_size = buffer_size_; | 154 info->buffer_size = buffer_size_; |
| 155 info->receive_timeout = receive_timeout_; | 155 info->receive_timeout = receive_timeout_; |
| 156 info->send_timeout = send_timeout_; | 156 info->send_timeout = send_timeout_; |
| 157 return GetPortInfo(info); | 157 return GetPortInfo(info); |
| 158 } | 158 } |
| 159 | 159 |
| 160 void SerialConnection::StartOpen() { | 160 void SerialConnection::StartOpen() { |
| 161 DCHECK(!open_complete_.is_null()); | 161 DCHECK(!open_complete_.is_null()); |
| 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 162 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 163 DCHECK(!file_.IsValid()); | 163 DCHECK(!file_.IsValid()); |
| 164 // It's the responsibility of the API wrapper around SerialConnection to | 164 // It's the responsibility of the API wrapper around SerialConnection to |
| 165 // validate the supplied path against the set of valid port names, and | 165 // validate the supplied path against the set of valid port names, and |
| 166 // it is a reasonable assumption that serial port names are ASCII. | 166 // it is a reasonable assumption that serial port names are ASCII. |
| 167 DCHECK(IsStringASCII(port_)); | 167 DCHECK(IsStringASCII(port_)); |
| 168 base::FilePath path( | 168 base::FilePath path( |
| 169 base::FilePath::FromUTF8Unsafe(MaybeFixUpPortName(port_))); | 169 base::FilePath::FromUTF8Unsafe(MaybeFixUpPortName(port_))); |
| 170 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ | | 170 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ | |
| 171 base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_WRITE | | 171 base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_WRITE | |
| 172 base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC | | 172 base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC | |
| 173 base::File::FLAG_TERMINAL_DEVICE; | 173 base::File::FLAG_TERMINAL_DEVICE; |
| 174 base::File file(path, flags); | 174 base::File file(path, flags); |
| 175 BrowserThread::PostTask( | 175 BrowserThread::PostTask( |
| 176 BrowserThread::IO, | 176 BrowserThread::IO, |
| 177 FROM_HERE, | 177 FROM_HERE, |
| 178 base::Bind(&SerialConnection::FinishOpen, base::Unretained(this), | 178 base::Bind(&SerialConnection::FinishOpen, base::Unretained(this), |
| 179 Passed(file.Pass()))); | 179 Passed(file.Pass()))); |
| 180 } | 180 } |
| 181 | 181 |
| 182 void SerialConnection::FinishOpen(base::File file) { | 182 void SerialConnection::FinishOpen(base::File file) { |
| 183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 183 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 184 DCHECK(!open_complete_.is_null()); | 184 DCHECK(!open_complete_.is_null()); |
| 185 DCHECK(!file_.IsValid()); | 185 DCHECK(!file_.IsValid()); |
| 186 OpenCompleteCallback callback = open_complete_; | 186 OpenCompleteCallback callback = open_complete_; |
| 187 open_complete_.Reset(); | 187 open_complete_.Reset(); |
| 188 | 188 |
| 189 if (!file.IsValid()) { | 189 if (!file.IsValid()) { |
| 190 callback.Run(false); | 190 callback.Run(false); |
| 191 return; | 191 return; |
| 192 } | 192 } |
| 193 | 193 |
| 194 // TODO(rvargas): crbug.com/351073. This is wrong. io_handler_ keeps a copy of | 194 // TODO(rvargas): crbug.com/351073. This is wrong. io_handler_ keeps a copy of |
| 195 // the handler that is not in sync with this one. | 195 // the handler that is not in sync with this one. |
| 196 file_ = file.Pass(); | 196 file_ = file.Pass(); |
| 197 io_handler_->Initialize( | 197 io_handler_->Initialize( |
| 198 file_.GetPlatformFile(), | 198 file_.GetPlatformFile(), |
| 199 base::Bind(&SerialConnection::OnAsyncReadComplete, AsWeakPtr()), | 199 base::Bind(&SerialConnection::OnAsyncReadComplete, AsWeakPtr()), |
| 200 base::Bind(&SerialConnection::OnAsyncWriteComplete, AsWeakPtr())); | 200 base::Bind(&SerialConnection::OnAsyncWriteComplete, AsWeakPtr())); |
| 201 | 201 |
| 202 bool success = PostOpen(); | 202 bool success = PostOpen(); |
| 203 if (!success) { | 203 if (!success) { |
| 204 Close(); | 204 Close(); |
| 205 } | 205 } |
| 206 | 206 |
| 207 callback.Run(success); | 207 callback.Run(success); |
| 208 } | 208 } |
| 209 | 209 |
| 210 // static | 210 // static |
| 211 void SerialConnection::DoClose(base::File port) { | 211 void SerialConnection::DoClose(base::File port) { |
| 212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 212 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 213 // port closed by destructor. | 213 // port closed by destructor. |
| 214 } | 214 } |
| 215 | 215 |
| 216 void SerialConnection::OnReceiveTimeout() { | 216 void SerialConnection::OnReceiveTimeout() { |
| 217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 217 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 218 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_TIMEOUT); | 218 io_handler_->CancelRead(api::serial::RECEIVE_ERROR_TIMEOUT); |
| 219 } | 219 } |
| 220 | 220 |
| 221 void SerialConnection::OnSendTimeout() { | 221 void SerialConnection::OnSendTimeout() { |
| 222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 222 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 223 io_handler_->CancelWrite(api::serial::SEND_ERROR_TIMEOUT); | 223 io_handler_->CancelWrite(api::serial::SEND_ERROR_TIMEOUT); |
| 224 } | 224 } |
| 225 | 225 |
| 226 void SerialConnection::OnAsyncReadComplete(const std::string& data, | 226 void SerialConnection::OnAsyncReadComplete(const std::string& data, |
| 227 api::serial::ReceiveError error) { | 227 api::serial::ReceiveError error) { |
| 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 228 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 229 DCHECK(!receive_complete_.is_null()); | 229 DCHECK(!receive_complete_.is_null()); |
| 230 ReceiveCompleteCallback callback = receive_complete_; | 230 ReceiveCompleteCallback callback = receive_complete_; |
| 231 receive_complete_.Reset(); | 231 receive_complete_.Reset(); |
| 232 receive_timeout_task_.reset(); | 232 receive_timeout_task_.reset(); |
| 233 callback.Run(data, error); | 233 callback.Run(data, error); |
| 234 } | 234 } |
| 235 | 235 |
| 236 void SerialConnection::OnAsyncWriteComplete(int bytes_sent, | 236 void SerialConnection::OnAsyncWriteComplete(int bytes_sent, |
| 237 api::serial::SendError error) { | 237 api::serial::SendError error) { |
| 238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 238 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 239 DCHECK(!send_complete_.is_null()); | 239 DCHECK(!send_complete_.is_null()); |
| 240 SendCompleteCallback callback = send_complete_; | 240 SendCompleteCallback callback = send_complete_; |
| 241 send_complete_.Reset(); | 241 send_complete_.Reset(); |
| 242 send_timeout_task_.reset(); | 242 send_timeout_task_.reset(); |
| 243 callback.Run(bytes_sent, error); | 243 callback.Run(bytes_sent, error); |
| 244 } | 244 } |
| 245 | 245 |
| 246 SerialConnection::TimeoutTask::TimeoutTask(const base::Closure& closure, | 246 SerialConnection::TimeoutTask::TimeoutTask(const base::Closure& closure, |
| 247 const base::TimeDelta& delay) | 247 const base::TimeDelta& delay) |
| 248 : weak_factory_(this), closure_(closure), delay_(delay) { | 248 : weak_factory_(this), closure_(closure), delay_(delay) { |
| 249 base::MessageLoop::current()->PostDelayedTask( | 249 base::MessageLoop::current()->PostDelayedTask( |
| 250 FROM_HERE, | 250 FROM_HERE, |
| 251 base::Bind(&TimeoutTask::Run, weak_factory_.GetWeakPtr()), | 251 base::Bind(&TimeoutTask::Run, weak_factory_.GetWeakPtr()), |
| 252 delay_); | 252 delay_); |
| 253 } | 253 } |
| 254 | 254 |
| 255 SerialConnection::TimeoutTask::~TimeoutTask() {} | 255 SerialConnection::TimeoutTask::~TimeoutTask() {} |
| 256 | 256 |
| 257 void SerialConnection::TimeoutTask::Run() const { closure_.Run(); } | 257 void SerialConnection::TimeoutTask::Run() const { closure_.Run(); } |
| 258 | 258 |
| 259 } // namespace extensions | 259 } // namespace extensions |
| OLD | NEW |