| Index: content/renderer/render_frame_impl.cc
|
| diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
| index 13392d1784ee20bce387f8fdb3496debf9589912..06b064f61b76c7ce0b217dd8dd7341111ddaebf1 100644
|
| --- a/content/renderer/render_frame_impl.cc
|
| +++ b/content/renderer/render_frame_impl.cc
|
| @@ -69,6 +69,8 @@
|
| #include "content/public/common/content_features.h"
|
| #include "content/public/common/content_switches.h"
|
| #include "content/public/common/context_menu_params.h"
|
| +#include "content/public/common/file_chooser_file_info.h"
|
| +#include "content/public/common/file_chooser_params.h"
|
| #include "content/public/common/isolated_world_ids.h"
|
| #include "content/public/common/page_state.h"
|
| #include "content/public/common/resource_response.h"
|
| @@ -151,6 +153,7 @@
|
| #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
| #include "net/http/http_util.h"
|
| #include "storage/common/data_element.h"
|
| +#include "third_party/WebKit/public/platform/FilePathConversion.h"
|
| #include "third_party/WebKit/public/platform/URLConversion.h"
|
| #include "third_party/WebKit/public/platform/WebCachePolicy.h"
|
| #include "third_party/WebKit/public/platform/WebData.h"
|
| @@ -851,6 +854,14 @@ bool UseMojoCdm() {
|
|
|
| } // namespace
|
|
|
| +struct RenderFrameImpl::PendingFileChooser {
|
| + PendingFileChooser(const FileChooserParams& p,
|
| + blink::WebFileChooserCompletion* c)
|
| + : params(p), completion(c) {}
|
| + FileChooserParams params;
|
| + blink::WebFileChooserCompletion* completion; // MAY BE NULL to skip callback.
|
| +};
|
| +
|
| // static
|
| RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
|
| int32_t routing_id) {
|
| @@ -1114,6 +1125,15 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
|
| }
|
|
|
| RenderFrameImpl::~RenderFrameImpl() {
|
| + // If file chooser is still waiting for answer, dispatch empty answer.
|
| + while (!file_chooser_completions_.empty()) {
|
| + if (file_chooser_completions_.front()->completion) {
|
| + file_chooser_completions_.front()->completion->didChooseFile(
|
| + WebVector<WebString>());
|
| + }
|
| + file_chooser_completions_.pop_front();
|
| + }
|
| +
|
| FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone());
|
| FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct());
|
|
|
| @@ -1505,6 +1525,7 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
|
| IPC_MESSAGE_HANDLER(FrameMsg_EnableViewSourceMode, OnEnableViewSourceMode)
|
| IPC_MESSAGE_HANDLER(FrameMsg_SuppressFurtherDialogs,
|
| OnSuppressFurtherDialogs)
|
| + IPC_MESSAGE_HANDLER(FrameMsg_RunFileChooserResponse, OnFileChooserResponse)
|
| #if defined(OS_ANDROID)
|
| IPC_MESSAGE_HANDLER(FrameMsg_ActivateNearestFindResult,
|
| OnActivateNearestFindResult)
|
| @@ -2218,6 +2239,31 @@ bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type,
|
| return success;
|
| }
|
|
|
| +bool RenderFrameImpl::ScheduleFileChooser(
|
| + const FileChooserParams& params,
|
| + blink::WebFileChooserCompletion* completion) {
|
| + static const size_t kMaximumPendingFileChooseRequests = 4;
|
| + if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) {
|
| + // This sanity check prevents too many file choose requests from getting
|
| + // queued which could DoS the user. Getting these is most likely a
|
| + // programming error (there are many ways to DoS the user so it's not
|
| + // considered a "real" security check), either in JS requesting many file
|
| + // choosers to pop up, or in a plugin.
|
| + //
|
| + // TODO(brettw): We might possibly want to require a user gesture to open
|
| + // a file picker, which will address this issue in a better way.
|
| + return false;
|
| + }
|
| +
|
| + file_chooser_completions_.push_back(
|
| + base::WrapUnique(new PendingFileChooser(params, completion)));
|
| + if (file_chooser_completions_.size() == 1) {
|
| + // Actually show the browse dialog when this is the first request.
|
| + Send(new FrameHostMsg_RunFileChooser(routing_id_, params));
|
| + }
|
| + return true;
|
| +}
|
| +
|
| void RenderFrameImpl::LoadNavigationErrorPage(
|
| const WebURLRequest& failed_request,
|
| const WebURLError& error,
|
| @@ -3744,6 +3790,37 @@ bool RenderFrameImpl::runModalBeforeUnloadDialog(bool is_reload) {
|
| return success;
|
| }
|
|
|
| +bool RenderFrameImpl::runFileChooser(
|
| + const blink::WebFileChooserParams& params,
|
| + blink::WebFileChooserCompletion* chooser_completion) {
|
| + // Do not open the file dialog in a hidden RenderView.
|
| + if (render_view_->is_hidden())
|
| + return false;
|
| +
|
| + FileChooserParams ipc_params;
|
| + if (params.directory)
|
| + ipc_params.mode = FileChooserParams::UploadFolder;
|
| + else if (params.multiSelect)
|
| + ipc_params.mode = FileChooserParams::OpenMultiple;
|
| + else if (params.saveAs)
|
| + ipc_params.mode = FileChooserParams::Save;
|
| + else
|
| + ipc_params.mode = FileChooserParams::Open;
|
| + ipc_params.title = params.title;
|
| + ipc_params.default_file_name =
|
| + blink::WebStringToFilePath(params.initialValue).BaseName();
|
| + ipc_params.accept_types.reserve(params.acceptTypes.size());
|
| + for (const auto& type : params.acceptTypes)
|
| + ipc_params.accept_types.push_back(type);
|
| + ipc_params.need_local_path = params.needLocalPath;
|
| +#if defined(OS_ANDROID)
|
| + ipc_params.capture = params.useMediaCapture;
|
| +#endif
|
| + ipc_params.requestor = params.requestor;
|
| +
|
| + return ScheduleFileChooser(ipc_params, chooser_completion);
|
| +}
|
| +
|
| void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
|
| ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
|
| blink::WebRect position_in_window(params.x, params.y, 0, 0);
|
| @@ -5129,6 +5206,43 @@ void RenderFrameImpl::OnSuppressFurtherDialogs() {
|
| suppress_further_dialogs_ = true;
|
| }
|
|
|
| +void RenderFrameImpl::OnFileChooserResponse(
|
| + const std::vector<content::FileChooserFileInfo>& files) {
|
| + // This could happen if we navigated to a different page before the user
|
| + // closed the chooser.
|
| + if (file_chooser_completions_.empty())
|
| + return;
|
| +
|
| + // Convert Chrome's SelectedFileInfo list to WebKit's.
|
| + WebVector<blink::WebFileChooserCompletion::SelectedFileInfo> selected_files(
|
| + files.size());
|
| + for (size_t i = 0; i < files.size(); ++i) {
|
| + blink::WebFileChooserCompletion::SelectedFileInfo selected_file;
|
| + selected_file.path = files[i].file_path.AsUTF16Unsafe();
|
| + selected_file.displayName =
|
| + base::FilePath(files[i].display_name).AsUTF16Unsafe();
|
| + if (files[i].file_system_url.is_valid()) {
|
| + selected_file.fileSystemURL = files[i].file_system_url;
|
| + selected_file.length = files[i].length;
|
| + selected_file.modificationTime = files[i].modification_time.ToDoubleT();
|
| + selected_file.isDirectory = files[i].is_directory;
|
| + }
|
| + selected_files[i] = selected_file;
|
| + }
|
| +
|
| + if (file_chooser_completions_.front()->completion) {
|
| + file_chooser_completions_.front()->completion->didChooseFile(
|
| + selected_files);
|
| + }
|
| + file_chooser_completions_.pop_front();
|
| +
|
| + // If there are more pending file chooser requests, schedule one now.
|
| + if (!file_chooser_completions_.empty()) {
|
| + Send(new FrameHostMsg_RunFileChooser(
|
| + routing_id_, file_chooser_completions_.front()->params));
|
| + }
|
| +}
|
| +
|
| #if defined(OS_ANDROID)
|
| void RenderFrameImpl::OnActivateNearestFindResult(int request_id,
|
| float x,
|
|
|