| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "blimp/engine/renderer/blob_channel_sender_proxy.h" | |
| 6 | |
| 7 #include <unordered_map> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "base/memory/ptr_util.h" | |
| 11 #include "blimp/common/blob_cache/id_util.h" | |
| 12 #include "content/public/renderer/render_thread.h" | |
| 13 #include "services/service_manager/public/cpp/interface_provider.h" | |
| 14 | |
| 15 namespace blimp { | |
| 16 namespace engine { | |
| 17 namespace { | |
| 18 | |
| 19 mojom::BlobChannelPtr GetConnectedBlobChannel() { | |
| 20 mojom::BlobChannelPtr blob_channel_ptr; | |
| 21 content::RenderThread::Get()->GetRemoteInterfaces()->GetInterface( | |
| 22 &blob_channel_ptr); | |
| 23 CHECK(blob_channel_ptr) << "Could not connect to BlobChannel Mojo interface."; | |
| 24 return blob_channel_ptr; | |
| 25 } | |
| 26 | |
| 27 // Manages the creation and lifetime of Mojo shared memory buffers for blobs. | |
| 28 class SharedMemoryBlob { | |
| 29 public: | |
| 30 explicit SharedMemoryBlob(BlobDataPtr data); | |
| 31 ~SharedMemoryBlob(); | |
| 32 | |
| 33 mojo::ScopedSharedBufferHandle CreateRemoteHandle(); | |
| 34 | |
| 35 private: | |
| 36 mojo::ScopedSharedBufferHandle local_handle_; | |
| 37 | |
| 38 DISALLOW_COPY_AND_ASSIGN(SharedMemoryBlob); | |
| 39 }; | |
| 40 | |
| 41 SharedMemoryBlob::SharedMemoryBlob(BlobDataPtr data) { | |
| 42 DCHECK_GE(kMaxBlobSizeBytes, data->data.size()); | |
| 43 | |
| 44 local_handle_ = mojo::SharedBufferHandle::Create(data->data.size()); | |
| 45 DCHECK(local_handle_.is_valid()); | |
| 46 | |
| 47 mojo::ScopedSharedBufferMapping mapped = | |
| 48 local_handle_->Map(data->data.size()); | |
| 49 DCHECK(mapped); | |
| 50 memcpy(mapped.get(), data->data.data(), data->data.size()); | |
| 51 } | |
| 52 | |
| 53 SharedMemoryBlob::~SharedMemoryBlob() {} | |
| 54 | |
| 55 mojo::ScopedSharedBufferHandle SharedMemoryBlob::CreateRemoteHandle() { | |
| 56 mojo::ScopedSharedBufferHandle remote_handle = | |
| 57 local_handle_->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY); | |
| 58 CHECK(remote_handle.is_valid()) | |
| 59 << "Mojo error when creating read-only buffer handle."; | |
| 60 return remote_handle; | |
| 61 } | |
| 62 | |
| 63 } // namespace | |
| 64 | |
| 65 BlobChannelSenderProxy::BlobChannelSenderProxy() | |
| 66 : blob_channel_(GetConnectedBlobChannel()), weak_factory_(this) { | |
| 67 blob_channel_->GetCachedBlobIds( | |
| 68 base::Bind(&BlobChannelSenderProxy::OnGetCacheStateComplete, | |
| 69 weak_factory_.GetWeakPtr())); | |
| 70 } | |
| 71 | |
| 72 BlobChannelSenderProxy::~BlobChannelSenderProxy() {} | |
| 73 | |
| 74 BlobChannelSenderProxy::BlobChannelSenderProxy( | |
| 75 mojom::BlobChannelPtr blob_channel) | |
| 76 : blob_channel_(std::move(blob_channel)), weak_factory_(this) {} | |
| 77 | |
| 78 // static | |
| 79 std::unique_ptr<BlobChannelSenderProxy> BlobChannelSenderProxy::CreateForTest( | |
| 80 mojom::BlobChannelPtr blob_channel) { | |
| 81 return base::WrapUnique(new BlobChannelSenderProxy(std::move(blob_channel))); | |
| 82 } | |
| 83 | |
| 84 bool BlobChannelSenderProxy::IsInEngineCache(const std::string& id) const { | |
| 85 return replication_state_.find(id) != replication_state_.end(); | |
| 86 } | |
| 87 | |
| 88 bool BlobChannelSenderProxy::IsInClientCache(const std::string& id) const { | |
| 89 auto found = replication_state_.find(id); | |
| 90 return found != replication_state_.end() && found->second; | |
| 91 } | |
| 92 | |
| 93 void BlobChannelSenderProxy::PutBlob(const BlobId& id, BlobDataPtr data) { | |
| 94 DCHECK(!IsInEngineCache(id)); | |
| 95 | |
| 96 size_t size = data->data.size(); | |
| 97 CHECK(!data->data.empty()) << "Zero length blob sent: " << BlobIdToString(id); | |
| 98 | |
| 99 replication_state_[id] = false; | |
| 100 std::unique_ptr<SharedMemoryBlob> shared_mem_blob( | |
| 101 new SharedMemoryBlob(std::move(data))); | |
| 102 blob_channel_->PutBlob(id, shared_mem_blob->CreateRemoteHandle(), size); | |
| 103 } | |
| 104 | |
| 105 void BlobChannelSenderProxy::DeliverBlob(const std::string& id) { | |
| 106 DCHECK(IsInEngineCache(id)) << "Attempted to deliver an invalid blob: " | |
| 107 << BlobIdToString(id); | |
| 108 DCHECK(!IsInClientCache(id)) << "Blob is already in the remote cache:" | |
| 109 << BlobIdToString(id); | |
| 110 | |
| 111 // We assume that the client will have the blob if we push it. | |
| 112 // TODO(kmarshall): Revisit this assumption when asynchronous blob transport | |
| 113 // is supported. | |
| 114 replication_state_[id] = true; | |
| 115 | |
| 116 blob_channel_->DeliverBlob(id); | |
| 117 } | |
| 118 | |
| 119 std::vector<BlobChannelSender::CacheStateEntry> | |
| 120 BlobChannelSenderProxy::GetCachedBlobIds() const { | |
| 121 NOTREACHED(); | |
| 122 return std::vector<BlobChannelSender::CacheStateEntry>(); | |
| 123 } | |
| 124 | |
| 125 void BlobChannelSenderProxy::OnGetCacheStateComplete( | |
| 126 const std::unordered_map<std::string, bool>& cache_state) { | |
| 127 VLOG(1) << "Received cache state from browser (" << cache_state.size() | |
| 128 << " items)"; | |
| 129 replication_state_.clear(); | |
| 130 for (const auto& next_item : cache_state) { | |
| 131 replication_state_[next_item.first] = next_item.second; | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 } // namespace engine | |
| 136 } // namespace blimp | |
| OLD | NEW |