drivefs_host.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. // Copyright 2018 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. #include "ash/components/drivefs/drivefs_host.h"
  5. #include <map>
  6. #include <set>
  7. #include <utility>
  8. #include "ash/components/drivefs/drivefs_bootstrap.h"
  9. #include "ash/components/drivefs/drivefs_host_observer.h"
  10. #include "ash/components/drivefs/drivefs_http_client.h"
  11. #include "ash/components/drivefs/drivefs_search.h"
  12. #include "ash/constants/ash_features.h"
  13. #include "base/bind.h"
  14. #include "base/strings/strcat.h"
  15. #include "base/unguessable_token.h"
  16. #include "components/drive/drive_notification_manager.h"
  17. #include "components/drive/drive_notification_observer.h"
  18. #include "mojo/public/cpp/bindings/callback_helpers.h"
  19. #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
  20. #include "mojo/public/cpp/system/invitation.h"
  21. #include "services/network/public/cpp/network_connection_tracker.h"
  22. #include "services/network/public/cpp/shared_url_loader_factory.h"
  23. namespace drivefs {
  24. namespace {
  25. constexpr char kDataPath[] = "GCache/v2";
  26. } // namespace
  27. std::unique_ptr<DriveFsBootstrapListener>
  28. DriveFsHost::Delegate::CreateMojoListener() {
  29. return std::make_unique<DriveFsBootstrapListener>();
  30. }
  31. // A container of state tied to a particular mounting of DriveFS. None of this
  32. // should be shared between mounts.
  33. class DriveFsHost::MountState : public DriveFsSession,
  34. public drive::DriveNotificationObserver {
  35. public:
  36. explicit MountState(DriveFsHost* host)
  37. : DriveFsSession(host->timer_.get(),
  38. DiskMounter::Create(host->disk_mount_manager_),
  39. CreateMojoConnection(host->account_token_delegate_.get(),
  40. host->delegate_),
  41. host->GetDataPath(),
  42. host->delegate_->GetMyFilesPath(),
  43. host->GetDefaultMountDirName(),
  44. host->mount_observer_),
  45. host_(host) {
  46. token_fetch_attempted_ =
  47. bool{host->account_token_delegate_->GetCachedAccessToken()};
  48. search_ = std::make_unique<DriveFsSearch>(
  49. drivefs_interface(), host_->network_connection_tracker_, host_->clock_);
  50. if (base::FeatureList::IsEnabled(
  51. chromeos::features::kDriveFsChromeNetworking)) {
  52. http_client_ = std::make_unique<DriveFsHttpClient>(
  53. host_->delegate_->GetURLLoaderFactory());
  54. }
  55. }
  56. MountState(const MountState&) = delete;
  57. MountState& operator=(const MountState&) = delete;
  58. ~MountState() override {
  59. DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
  60. if (team_drives_fetched_) {
  61. host_->delegate_->GetDriveNotificationManager().ClearTeamDriveIds();
  62. host_->delegate_->GetDriveNotificationManager().RemoveObserver(this);
  63. }
  64. if (is_mounted()) {
  65. for (auto& observer : host_->observers_) {
  66. observer.OnUnmounted();
  67. }
  68. }
  69. }
  70. static std::unique_ptr<DriveFsConnection> CreateMojoConnection(
  71. DriveFsAuth* auth_delegate,
  72. DriveFsHost::Delegate* delegate) {
  73. auto access_token = auth_delegate->GetCachedAccessToken();
  74. mojom::DriveFsConfigurationPtr config = {
  75. absl::in_place,
  76. auth_delegate->GetAccountId().GetUserEmail(),
  77. std::move(access_token),
  78. auth_delegate->IsMetricsCollectionEnabled(),
  79. delegate->GetLostAndFoundDirectoryName(),
  80. base::FeatureList::IsEnabled(chromeos::features::kDriveFsMirroring),
  81. delegate->IsVerboseLoggingEnabled(),
  82. base::FeatureList::IsEnabled(
  83. chromeos::features::kDriveFsChromeNetworking),
  84. };
  85. return DriveFsConnection::Create(delegate->CreateMojoListener(),
  86. std::move(config));
  87. }
  88. mojom::QueryParameters::QuerySource SearchDriveFs(
  89. mojom::QueryParametersPtr query,
  90. mojom::SearchQuery::GetNextPageCallback callback) {
  91. return search_->PerformSearch(std::move(query), std::move(callback));
  92. }
  93. private:
  94. // mojom::DriveFsDelegate:
  95. void GetAccessToken(const std::string& client_id,
  96. const std::string& app_id,
  97. const std::vector<std::string>& scopes,
  98. GetAccessTokenCallback callback) override {
  99. DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
  100. host_->account_token_delegate_->GetAccessToken(!token_fetch_attempted_,
  101. std::move(callback));
  102. token_fetch_attempted_ = true;
  103. }
  104. void OnSyncingStatusUpdate(mojom::SyncingStatusPtr status) override {
  105. for (auto& observer : host_->observers_) {
  106. observer.OnSyncingStatusUpdate(*status);
  107. }
  108. }
  109. void OnMirrorSyncingStatusUpdate(mojom::SyncingStatusPtr status) override {
  110. for (auto& observer : host_->observers_) {
  111. observer.OnMirrorSyncingStatusUpdate(*status);
  112. }
  113. }
  114. void OnFilesChanged(std::vector<mojom::FileChangePtr> changes) override {
  115. std::vector<mojom::FileChange> changes_values;
  116. changes_values.reserve(changes.size());
  117. for (auto& change : changes) {
  118. changes_values.emplace_back(std::move(*change));
  119. }
  120. for (auto& observer : host_->observers_) {
  121. observer.OnFilesChanged(changes_values);
  122. }
  123. }
  124. void OnError(mojom::DriveErrorPtr error) override {
  125. if (!IsKnownEnumValue(error->type)) {
  126. return;
  127. }
  128. for (auto& observer : host_->observers_) {
  129. observer.OnError(*error);
  130. }
  131. }
  132. void OnTeamDrivesListReady(
  133. const std::vector<std::string>& team_drive_ids) override {
  134. host_->delegate_->GetDriveNotificationManager().AddObserver(this);
  135. host_->delegate_->GetDriveNotificationManager().UpdateTeamDriveIds(
  136. std::set<std::string>(team_drive_ids.begin(), team_drive_ids.end()),
  137. {});
  138. team_drives_fetched_ = true;
  139. }
  140. void OnTeamDriveChanged(const std::string& team_drive_id,
  141. CreateOrDelete change_type) override {
  142. if (!team_drives_fetched_) {
  143. return;
  144. }
  145. std::set<std::string> additions;
  146. std::set<std::string> removals;
  147. if (change_type == mojom::DriveFsDelegate::CreateOrDelete::kCreated) {
  148. additions.insert(team_drive_id);
  149. } else {
  150. removals.insert(team_drive_id);
  151. }
  152. host_->delegate_->GetDriveNotificationManager().UpdateTeamDriveIds(
  153. additions, removals);
  154. }
  155. void ConnectToExtension(
  156. mojom::ExtensionConnectionParamsPtr params,
  157. mojo::PendingReceiver<mojom::NativeMessagingPort> port,
  158. mojo::PendingRemote<mojom::NativeMessagingHost> host,
  159. ConnectToExtensionCallback callback) override {
  160. std::move(callback).Run(host_->delegate_->ConnectToExtension(
  161. std::move(params), std::move(port), std::move(host)));
  162. }
  163. void DisplayConfirmDialog(mojom::DialogReasonPtr error,
  164. DisplayConfirmDialogCallback callback) override {
  165. if (!IsKnownEnumValue(error->type) || !host_->dialog_handler_) {
  166. std::move(callback).Run(mojom::DialogResult::kNotDisplayed);
  167. return;
  168. }
  169. host_->dialog_handler_.Run(
  170. *error, mojo::WrapCallbackWithDefaultInvokeIfNotRun(
  171. std::move(callback), mojom::DialogResult::kNotDisplayed));
  172. }
  173. void ExecuteHttpRequest(
  174. mojom::HttpRequestPtr request,
  175. mojo::PendingRemote<mojom::HttpDelegate> delegate) override {
  176. if (!http_client_) {
  177. // The Chrome Network Service <-> DriveFS bridge is not enabled. Ignore
  178. // the request and allow the |delegate| to close itself. DriveFS will
  179. // pick up on the |delegate| closure and fallback to cURL.
  180. return;
  181. }
  182. http_client_->ExecuteHttpRequest(std::move(request), std::move(delegate));
  183. }
  184. void GetMachineRootID(GetMachineRootIDCallback callback) override {
  185. if (!chromeos::features::IsDriveFsMirroringEnabled()) {
  186. std::move(callback).Run({});
  187. return;
  188. }
  189. std::move(callback).Run(host_->delegate_->GetMachineRootID());
  190. }
  191. void PersistMachineRootID(const std::string& id) override {
  192. if (!chromeos::features::IsDriveFsMirroringEnabled()) {
  193. return;
  194. }
  195. host_->delegate_->PersistMachineRootID(std::move(id));
  196. }
  197. // DriveNotificationObserver overrides:
  198. void OnNotificationReceived(
  199. const std::map<std::string, int64_t>& invalidations) override {
  200. std::vector<mojom::FetchChangeLogOptionsPtr> options;
  201. options.reserve(invalidations.size());
  202. for (const auto& invalidation : invalidations) {
  203. options.emplace_back(absl::in_place, invalidation.second,
  204. invalidation.first);
  205. }
  206. drivefs_interface()->FetchChangeLog(std::move(options));
  207. }
  208. void OnNotificationTimerFired() override {
  209. drivefs_interface()->FetchAllChangeLogs();
  210. }
  211. // Owns |this|.
  212. DriveFsHost* const host_;
  213. std::unique_ptr<DriveFsSearch> search_;
  214. std::unique_ptr<DriveFsHttpClient> http_client_;
  215. bool token_fetch_attempted_ = false;
  216. bool team_drives_fetched_ = false;
  217. };
  218. DriveFsHost::DriveFsHost(
  219. const base::FilePath& profile_path,
  220. DriveFsHost::Delegate* delegate,
  221. DriveFsHost::MountObserver* mount_observer,
  222. network::NetworkConnectionTracker* network_connection_tracker,
  223. const base::Clock* clock,
  224. ash::disks::DiskMountManager* disk_mount_manager,
  225. std::unique_ptr<base::OneShotTimer> timer)
  226. : profile_path_(profile_path),
  227. delegate_(delegate),
  228. mount_observer_(mount_observer),
  229. network_connection_tracker_(network_connection_tracker),
  230. clock_(clock),
  231. disk_mount_manager_(disk_mount_manager),
  232. timer_(std::move(timer)),
  233. account_token_delegate_(
  234. std::make_unique<DriveFsAuth>(clock,
  235. profile_path,
  236. std::make_unique<base::OneShotTimer>(),
  237. delegate)) {
  238. DCHECK(delegate_);
  239. DCHECK(mount_observer_);
  240. DCHECK(network_connection_tracker_);
  241. DCHECK(clock_);
  242. }
  243. DriveFsHost::~DriveFsHost() {
  244. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  245. }
  246. void DriveFsHost::AddObserver(DriveFsHostObserver* observer) {
  247. observers_.AddObserver(observer);
  248. }
  249. void DriveFsHost::RemoveObserver(DriveFsHostObserver* observer) {
  250. observers_.RemoveObserver(observer);
  251. }
  252. bool DriveFsHost::Mount() {
  253. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  254. const AccountId& account_id = delegate_->GetAccountId();
  255. if (mount_state_ || !account_id.HasAccountIdKey() ||
  256. account_id.GetUserEmail().empty()) {
  257. return false;
  258. }
  259. mount_state_ = std::make_unique<MountState>(this);
  260. return true;
  261. }
  262. void DriveFsHost::Unmount() {
  263. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  264. mount_state_.reset();
  265. }
  266. bool DriveFsHost::IsMounted() const {
  267. return mount_state_ && mount_state_->is_mounted();
  268. }
  269. base::FilePath DriveFsHost::GetMountPath() const {
  270. return mount_state_ && mount_state_->is_mounted()
  271. ? mount_state_->mount_path()
  272. : base::FilePath("/media/fuse").Append(GetDefaultMountDirName());
  273. }
  274. base::FilePath DriveFsHost::GetDataPath() const {
  275. return profile_path_.Append(kDataPath).Append(
  276. delegate_->GetObfuscatedAccountId());
  277. }
  278. mojom::DriveFs* DriveFsHost::GetDriveFsInterface() const {
  279. if (!mount_state_ || !mount_state_->is_mounted()) {
  280. return nullptr;
  281. }
  282. return mount_state_->drivefs_interface();
  283. }
  284. mojom::QueryParameters::QuerySource DriveFsHost::PerformSearch(
  285. mojom::QueryParametersPtr query,
  286. mojom::SearchQuery::GetNextPageCallback callback) {
  287. if (!mount_state_ || !mount_state_->is_mounted()) {
  288. std::move(callback).Run(drive::FileError::FILE_ERROR_SERVICE_UNAVAILABLE,
  289. {});
  290. return mojom::QueryParameters::QuerySource::kLocalOnly;
  291. }
  292. return mount_state_->SearchDriveFs(std::move(query), std::move(callback));
  293. }
  294. std::string DriveFsHost::GetDefaultMountDirName() const {
  295. return base::StrCat({"drivefs-", delegate_->GetObfuscatedAccountId()});
  296. }
  297. } // namespace drivefs