| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromeos/ash/components/smbfs/smbfs_host.h" |
| |
| #include <utility> |
| |
| #include "base/files/file_util.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/logging.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "chromeos/ash/components/disks/disk_mount_manager.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| |
| namespace smbfs { |
| namespace { |
| |
| class SmbFsDelegateImpl : public mojom::SmbFsDelegate { |
| public: |
| SmbFsDelegateImpl( |
| mojo::PendingReceiver<mojom::SmbFsDelegate> pending_receiver, |
| base::OnceClosure disconnect_callback, |
| SmbFsHost::Delegate* delegate) |
| : receiver_(this, std::move(pending_receiver)), delegate_(delegate) { |
| receiver_.set_disconnect_handler(std::move(disconnect_callback)); |
| } |
| |
| SmbFsDelegateImpl(const SmbFsDelegateImpl&) = delete; |
| SmbFsDelegateImpl& operator=(const SmbFsDelegateImpl&) = delete; |
| |
| ~SmbFsDelegateImpl() override = default; |
| |
| // mojom::SmbFsDelegate overrides. |
| void RequestCredentials(RequestCredentialsCallback callback) override { |
| delegate_->RequestCredentials( |
| base::BindOnce(&SmbFsDelegateImpl::OnRequestCredentialsDone, |
| weak_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| private: |
| void OnRequestCredentialsDone(RequestCredentialsCallback callback, |
| bool cancel, |
| const std::string& username, |
| const std::string& workgroup, |
| const std::string& password) { |
| if (cancel) { |
| std::move(callback).Run(nullptr); |
| return; |
| } |
| |
| mojom::CredentialsPtr creds = |
| mojom::Credentials::New(username, workgroup, nullptr); |
| if (password.size() > mojom::Password::kMaxLength) { |
| LOG(WARNING) << "smbfs password too long"; |
| } else if (!password.empty()) { |
| // Create pipe and write password. |
| base::ScopedFD pipe_read_end; |
| base::ScopedFD pipe_write_end; |
| CHECK(base::CreatePipe(&pipe_read_end, &pipe_write_end, |
| true /* non_blocking */)); |
| CHECK(base::WriteFileDescriptor(pipe_write_end.get(), password)); |
| |
| creds->password = mojom::Password::New( |
| mojo::WrapPlatformHandle( |
| mojo::PlatformHandle(std::move(pipe_read_end))), |
| static_cast<int32_t>(password.size())); |
| } |
| std::move(callback).Run(std::move(creds)); |
| } |
| |
| mojo::Receiver<mojom::SmbFsDelegate> receiver_; |
| const raw_ptr<SmbFsHost::Delegate> delegate_; |
| |
| base::WeakPtrFactory<SmbFsDelegateImpl> weak_factory_{this}; |
| }; |
| |
| } // namespace |
| |
| SmbFsHost::Delegate::~Delegate() = default; |
| |
| SmbFsHost::SmbFsHost( |
| std::unique_ptr<ash::disks::MountPoint> mount_point, |
| Delegate* delegate, |
| mojo::Remote<mojom::SmbFs> smbfs_remote, |
| mojo::PendingReceiver<mojom::SmbFsDelegate> delegate_receiver) |
| : mount_point_(std::move(mount_point)), |
| delegate_(delegate), |
| smbfs_(std::move(smbfs_remote)), |
| delegate_impl_(std::make_unique<SmbFsDelegateImpl>( |
| std::move(delegate_receiver), |
| base::BindOnce(&SmbFsHost::OnDisconnect, base::Unretained(this)), |
| delegate)) { |
| DCHECK(mount_point_); |
| DCHECK(delegate); |
| |
| smbfs_.set_disconnect_handler( |
| base::BindOnce(&SmbFsHost::OnDisconnect, base::Unretained(this))); |
| } |
| |
| SmbFsHost::~SmbFsHost() = default; |
| |
| void SmbFsHost::Unmount(SmbFsHost::UnmountCallback callback) { |
| mount_point_->Unmount(base::BindOnce( |
| &SmbFsHost::OnUnmountDone, base::Unretained(this), std::move(callback))); |
| } |
| |
| void SmbFsHost::OnUnmountDone(SmbFsHost::UnmountCallback callback, |
| ash::MountError result) { |
| LOG_IF(ERROR, result != ash::MountError::kSuccess) |
| << "Could not unmount smbfs share: " << result; |
| std::move(callback).Run(result); |
| } |
| |
| void SmbFsHost::RemoveSavedCredentials( |
| SmbFsHost::RemoveSavedCredentialsCallback callback) { |
| smbfs_->RemoveSavedCredentials( |
| base::BindOnce(&SmbFsHost::OnRemoveSavedCredentialsDone, |
| base::Unretained(this), std::move(callback))); |
| } |
| |
| void SmbFsHost::OnRemoveSavedCredentialsDone( |
| SmbFsHost::RemoveSavedCredentialsCallback callback, |
| bool success) { |
| LOG_IF(ERROR, !success) << "Unable to remove saved password for smbfs"; |
| std::move(callback).Run(success); |
| } |
| |
| void SmbFsHost::OnDisconnect() { |
| // Ensure only one disconnection event occurs. |
| smbfs_.reset(); |
| delegate_impl_.reset(); |
| |
| // This may delete us. |
| delegate_->OnDisconnected(); |
| } |
| |
| void SmbFsHost::DeleteRecursively(const base::FilePath& path, |
| DeleteRecursivelyCallback callback) { |
| smbfs_->DeleteRecursively( |
| path, base::BindOnce(&SmbFsHost::OnDeleteRecursivelyDone, |
| base::Unretained(this), std::move(callback))); |
| } |
| |
| void SmbFsHost::OnDeleteRecursivelyDone( |
| DeleteRecursivelyCallback callback, |
| smbfs::mojom::DeleteRecursivelyError error) { |
| base::File::Error file_error = |
| error == smbfs::mojom::DeleteRecursivelyError::kOk |
| ? base::File::FILE_OK |
| : base::File::FILE_ERROR_FAILED; |
| |
| std::move(callback).Run(file_error); |
| } |
| |
| } // namespace smbfs |