blob: e304ae155a20a7320153184a49cb90b33eec0025 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_ARC_FILEAPI_ARC_SELECT_FILES_HANDLER_H_
#define CHROME_BROWSER_ASH_ARC_FILEAPI_ARC_SELECT_FILES_HANDLER_H_
#include <vector>
#include "ash/components/arc/mojom/file_system.mojom.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/views/select_file_dialog_extension.h"
#include "content/public/browser/render_frame_host.h"
#include "ui/shell_dialogs/select_file_dialog.h"
class Profile;
namespace content {
class BrowserContext;
} // namespace content
namespace arc {
class ArcSelectFilesHandler;
class SelectFileDialogHolder;
// Exposed for testing.
extern const char kScriptClickOk[];
extern const char kScriptClickCancel[];
extern const char kScriptClickDirectory[];
extern const char kScriptClickFile[];
extern const char kScriptGetElements[];
// Manages multiple ArcSelectFilesHandler instances.
class ArcSelectFilesHandlersManager {
public:
explicit ArcSelectFilesHandlersManager(content::BrowserContext* context);
ArcSelectFilesHandlersManager(const ArcSelectFilesHandlersManager&) = delete;
ArcSelectFilesHandlersManager& operator=(
const ArcSelectFilesHandlersManager&) = delete;
~ArcSelectFilesHandlersManager();
// Delete all handlers and close all SelectFileDialogs.
void DeleteAllHandlers() { handlers_by_task_id_.clear(); }
// Handler for FileSystemHost.SelectFiles.
// Creates a new ArcSelectFilesHandler instance.
void SelectFiles(const mojom::SelectFilesRequestPtr& request,
mojom::FileSystemHost::SelectFilesCallback callback);
// Handler for FileSystemHost.OnFileSelectorEvent.
// Routes the request to the right ArcSelectFilesHandler instance.
void OnFileSelectorEvent(
mojom::FileSelectorEventPtr event,
mojom::FileSystemHost::OnFileSelectorEventCallback callback);
// Handler for FileSystemHost.GetFileSelectorElements.
// Routes the request to the right ArcSelectFilesHandler instance.
void GetFileSelectorElements(
mojom::GetFileSelectorElementsRequestPtr request,
mojom::FileSystemHost::GetFileSelectorElementsCallback callback);
private:
// Helper function for SelectFiles.
void EraseHandlerAndRunCallback(
int task_id,
mojom::FileSystemHost::SelectFilesCallback callback,
mojom::SelectFilesResultPtr result);
content::BrowserContext* const context_;
// Map of Task ID -> ArcSelectFilesHandler.
std::map<int, std::unique_ptr<ArcSelectFilesHandler>> handlers_by_task_id_;
base::WeakPtrFactory<ArcSelectFilesHandlersManager> weak_ptr_factory_{this};
};
// Manages a single SelectFileDialog instance.
class ArcSelectFilesHandler : public ui::SelectFileDialog::Listener {
public:
explicit ArcSelectFilesHandler(content::BrowserContext* context);
ArcSelectFilesHandler(const ArcSelectFilesHandler&) = delete;
ArcSelectFilesHandler& operator=(const ArcSelectFilesHandler&) = delete;
~ArcSelectFilesHandler() override;
void SelectFiles(const mojom::SelectFilesRequestPtr& request,
mojom::FileSystemHost::SelectFilesCallback callback);
void OnFileSelectorEvent(
mojom::FileSelectorEventPtr event,
mojom::FileSystemHost::OnFileSelectorEventCallback callback);
void GetFileSelectorElements(
mojom::GetFileSelectorElementsRequestPtr request,
mojom::FileSystemHost::GetFileSelectorElementsCallback callback);
// ui::SelectFileDialog::Listener overrides:
void FileSelected(const base::FilePath& path,
int index,
void* params) override;
void MultiFilesSelected(const std::vector<base::FilePath>& files,
void* params) override;
void FileSelectionCanceled(void* params) override;
private:
friend class ArcSelectFilesHandlerTest;
void FilesSelectedInternal(const std::vector<base::FilePath>& files,
void* params);
void SetDialogHolderForTesting(
std::unique_ptr<SelectFileDialogHolder> dialog_holder);
Profile* const profile_;
mojom::FileSystemHost::SelectFilesCallback callback_;
std::unique_ptr<SelectFileDialogHolder> dialog_holder_;
};
// Wrapper for SelectFileDialogExtension.
// Since it is not easy to create a mock class for SelectFileDialogExtension,
// this class is replaced with a mock class instead in unit tests.
class SelectFileDialogHolder {
public:
explicit SelectFileDialogHolder(ui::SelectFileDialog::Listener* listener);
virtual ~SelectFileDialogHolder();
// Obtains the owner window from |task_id| and opens the select file dialog
// with it. Returns false if the owner window is not found.
virtual bool SelectFile(ui::SelectFileDialog::Type type,
const base::FilePath& default_path,
const ui::SelectFileDialog::FileTypeInfo* file_types,
int task_id,
const std::string& search_query,
bool show_android_picker_apps,
bool use_media_store_filter);
virtual void ExecuteJavaScript(
const std::string& script,
content::RenderFrameHost::JavaScriptResultCallback callback);
private:
scoped_refptr<SelectFileDialogExtension> select_file_dialog_;
};
} // namespace arc
#endif // CHROME_BROWSER_ASH_ARC_FILEAPI_ARC_SELECT_FILES_HANDLER_H_