1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "remoting/host/native_messaging/native_messaging_writer.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_writer.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 4-byte type used for the message header. 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef uint32 MessageLengthType; 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Defined as an int, for passing to APIs that take an int, to avoid 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// signed/unsigned warnings about implicit cast. 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kMessageHeaderSize = sizeof(MessageLengthType); 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Limit the size of sent messages, since Chrome will not accept messages 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// larger than 1MB, and this helps deal with the problem of integer overflow 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// when passing sizes to net::FileStream APIs that take |int| parameters. 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This is defined as size_t (unsigned type) so it can be compared with the 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// result of std::string::length() without compiler warnings. 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kMaximumMessageSize = 1024 * 1024; 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace remoting { 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)NativeMessagingWriter::NativeMessagingWriter(base::File file) 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : write_stream_(file.Pass()), 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fail_(false) { 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NativeMessagingWriter::~NativeMessagingWriter() { 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingWriter::WriteMessage(const base::Value& message) { 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (fail_) { 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Stream marked as corrupt."; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string message_json; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::JSONWriter::Write(&message, &message_json); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK_LE(message_json.length(), kMaximumMessageSize); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Cast from size_t to the proper header type. The check above ensures this 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // won't overflow. 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MessageLengthType message_length = 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<MessageLengthType>(message_json.length()); 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int result = write_stream_.WriteAtCurrentPos( 57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reinterpret_cast<char*>(&message_length), kMessageHeaderSize); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result != kMessageHeaderSize) { 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Failed to send message header, write returned " << result; 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fail_ = true; 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The length check above ensures that the cast won't overflow a signed 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 32-bit int. 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int message_length_as_int = message_length; 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // CHECK needed since data() is undefined on an empty std::string. 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK(!message_json.empty()); 70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch result = write_stream_.WriteAtCurrentPos(message_json.data(), 71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_length_as_int); 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result != message_length_as_int) { 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Failed to send message body, write returned " << result; 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fail_ = true; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace remoting 82