1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
#include <string>
#include <utility>
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/browser/file_system/file_system_url.h"
namespace {
base::LazyInstance<MTPDeviceMapService>::DestructorAtExit
g_mtp_device_map_service = LAZY_INSTANCE_INITIALIZER;
} // namespace
// static
MTPDeviceMapService* MTPDeviceMapService::GetInstance() {
return g_mtp_device_map_service.Pointer();
}
void MTPDeviceMapService::RegisterMTPFileSystem(
const base::FilePath::StringType& device_location,
const std::string& filesystem_id,
const bool read_only) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(!device_location.empty());
DCHECK(!filesystem_id.empty());
const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only);
if (!base::Contains(mtp_device_usage_map_, key)) {
// Note that this initializes the delegate asynchronously, but since
// the delegate will only be used from the IO thread, it is guaranteed
// to be created before use of it expects it to be there.
CreateMTPDeviceAsyncDelegate(
device_location, read_only,
base::BindOnce(&MTPDeviceMapService::AddAsyncDelegate,
base::Unretained(this), device_location, read_only));
mtp_device_usage_map_[key] = 0;
}
mtp_device_usage_map_[key]++;
mtp_device_map_[filesystem_id] = make_pair(device_location, read_only);
}
void MTPDeviceMapService::RevokeMTPFileSystem(
const std::string& filesystem_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(!filesystem_id.empty());
MTPDeviceFileSystemMap::iterator it = mtp_device_map_.find(filesystem_id);
if (it != mtp_device_map_.end()) {
const base::FilePath::StringType device_location = it->second.first;
const bool read_only = it->second.second;
mtp_device_map_.erase(it);
const AsyncDelegateKey key =
GetAsyncDelegateKey(device_location, read_only);
MTPDeviceUsageMap::iterator delegate_it = mtp_device_usage_map_.find(key);
CHECK(delegate_it != mtp_device_usage_map_.end());
mtp_device_usage_map_[key]--;
if (mtp_device_usage_map_[key] == 0) {
mtp_device_usage_map_.erase(delegate_it);
RemoveAsyncDelegate(device_location, read_only);
}
}
}
void MTPDeviceMapService::AddAsyncDelegate(
const base::FilePath::StringType& device_location,
const bool read_only,
MTPDeviceAsyncDelegate* delegate) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(delegate);
DCHECK(!device_location.empty());
const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only);
if (base::Contains(async_delegate_map_, key))
return;
async_delegate_map_[key] = delegate;
}
void MTPDeviceMapService::RemoveAsyncDelegate(
const base::FilePath::StringType& device_location,
const bool read_only) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(!device_location.empty());
const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only);
AsyncDelegateMap::iterator it = async_delegate_map_.find(key);
CHECK(it != async_delegate_map_.end());
it->second->CancelPendingTasksAndDeleteDelegate();
async_delegate_map_.erase(it);
}
// static
MTPDeviceMapService::AsyncDelegateKey MTPDeviceMapService::GetAsyncDelegateKey(
const base::FilePath::StringType& device_location,
const bool read_only) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
base::FilePath::StringType key;
key.append(read_only ? FILE_PATH_LITERAL("ReadOnly")
: FILE_PATH_LITERAL("ReadWrite"));
key.append(FILE_PATH_LITERAL("|"));
key.append(device_location);
return key;
}
MTPDeviceAsyncDelegate* MTPDeviceMapService::GetMTPDeviceAsyncDelegate(
const storage::FileSystemURL& filesystem_url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(!filesystem_url.filesystem_id().empty());
const std::string& filesystem_id = filesystem_url.filesystem_id();
// File system may be already revoked on ExternalMountPoints side, we check
// here that the file system is still valid.
base::FilePath device_path;
if (!storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(
filesystem_id, &device_path)) {
return nullptr;
}
const base::FilePath::StringType& device_location = device_path.value();
MTPDeviceFileSystemMap::const_iterator mtp_device_map_it =
mtp_device_map_.find(filesystem_id);
if (mtp_device_map_it == mtp_device_map_.end())
return nullptr;
DCHECK_EQ(device_path.value(), mtp_device_map_it->second.first);
const bool read_only = mtp_device_map_it->second.second;
const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only);
AsyncDelegateMap::const_iterator async_delegate_map_it =
async_delegate_map_.find(key);
return (async_delegate_map_it != async_delegate_map_.end())
? async_delegate_map_it->second
: NULL;
}
MTPDeviceMapService::MTPDeviceMapService() = default;
MTPDeviceMapService::~MTPDeviceMapService() {
DCHECK(mtp_device_usage_map_.empty());
}
|