1 // Copyright (c) 2012 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.
5 #include "android_webview/native/aw_web_contents_delegate.h"
7 #include "android_webview/browser/aw_javascript_dialog_manager.h"
8 #include "android_webview/browser/find_helper.h"
9 #include "android_webview/native/aw_contents.h"
10 #include "base/android/jni_array.h"
11 #include "base/android/jni_string.h"
12 #include "base/android/scoped_java_ref.h"
13 #include "base/lazy_instance.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/string_util.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/file_chooser_params.h"
20 #include "jni/AwWebContentsDelegate_jni.h"
21 #include "ui/shell_dialogs/selected_file_info.h"
23 using base::android::AttachCurrentThread
;
24 using base::android::ConvertUTF16ToJavaString
;
25 using base::android::ConvertUTF8ToJavaString
;
26 using base::android::ScopedJavaLocalRef
;
27 using content::FileChooserParams
;
28 using content::WebContents
;
30 namespace android_webview
{
34 // WARNING: these constants are exposed in the public interface Java side, so
35 // must remain in sync with what clients are expecting.
36 const int kFileChooserModeOpenMultiple
= 1 << 0;
37 const int kFileChooserModeOpenFolder
= 1 << 1;
39 base::LazyInstance
<AwJavaScriptDialogManager
>::Leaky
40 g_javascript_dialog_manager
= LAZY_INSTANCE_INITIALIZER
;
43 AwWebContentsDelegate::AwWebContentsDelegate(
46 : WebContentsDelegateAndroid(env
, obj
) {
49 AwWebContentsDelegate::~AwWebContentsDelegate() {
52 content::JavaScriptDialogManager
*
53 AwWebContentsDelegate::GetJavaScriptDialogManager() {
54 return g_javascript_dialog_manager
.Pointer();
57 void AwWebContentsDelegate::FindReply(WebContents
* web_contents
,
59 int number_of_matches
,
60 const gfx::Rect
& selection_rect
,
61 int active_match_ordinal
,
63 AwContents
* aw_contents
= AwContents::FromWebContents(web_contents
);
67 aw_contents
->GetFindHelper()->HandleFindReply(request_id
,
73 void AwWebContentsDelegate::CanDownload(
74 content::RenderViewHost
* source
,
76 const std::string
& request_method
,
77 const base::Callback
<void(bool)>& callback
) {
78 // Android webview intercepts download in its resource dispatcher host
79 // delegate, so should not reach here.
84 void AwWebContentsDelegate::RunFileChooser(WebContents
* web_contents
,
85 const FileChooserParams
& params
) {
86 JNIEnv
* env
= AttachCurrentThread();
87 ScopedJavaLocalRef
<jobject
> java_delegate
= GetJavaDelegate(env
);
88 if (!java_delegate
.obj())
92 if (params
.mode
== FileChooserParams::OpenMultiple
) {
93 mode_flags
|= kFileChooserModeOpenMultiple
;
94 } else if (params
.mode
== FileChooserParams::UploadFolder
) {
95 // Folder implies multiple in Chrome.
96 mode_flags
|= kFileChooserModeOpenMultiple
| kFileChooserModeOpenFolder
;
97 } else if (params
.mode
== FileChooserParams::Save
) {
98 // Save not supported, so cancel it.
99 web_contents
->GetRenderViewHost()->FilesSelectedInChooser(
100 std::vector
<ui::SelectedFileInfo
>(),
104 DCHECK_EQ(FileChooserParams::Open
, params
.mode
);
106 Java_AwWebContentsDelegate_runFileChooser(env
,
108 web_contents
->GetRenderProcessHost()->GetID(),
109 web_contents
->GetRenderViewHost()->GetRoutingID(),
111 ConvertUTF16ToJavaString(env
,
112 JoinString(params
.accept_types
, ',')).obj(),
113 params
.title
.empty() ? NULL
:
114 ConvertUTF16ToJavaString(env
, params
.title
).obj(),
115 params
.default_file_name
.empty() ? NULL
:
116 ConvertUTF8ToJavaString(env
, params
.default_file_name
.value()).obj(),
120 void AwWebContentsDelegate::AddNewContents(WebContents
* source
,
121 WebContents
* new_contents
,
122 WindowOpenDisposition disposition
,
123 const gfx::Rect
& initial_pos
,
126 JNIEnv
* env
= AttachCurrentThread();
128 bool is_dialog
= disposition
== NEW_POPUP
;
129 ScopedJavaLocalRef
<jobject
> java_delegate
= GetJavaDelegate(env
);
130 bool create_popup
= false;
132 if (java_delegate
.obj()) {
133 create_popup
= Java_AwWebContentsDelegate_addNewContents(env
,
134 java_delegate
.obj(), is_dialog
, user_gesture
);
138 // The embedder would like to display the popup and we will receive
139 // a callback from them later with an AwContents to use to display
140 // it. The source AwContents takes ownership of the new WebContents
141 // until then, and when the callback is made we will swap the WebContents
142 // out into the new AwContents.
143 AwContents::FromWebContents(source
)->SetPendingWebContentsForPopup(
144 make_scoped_ptr(new_contents
));
145 // Hide the WebContents for the pop up now, we will show it again
146 // when the user calls us back with an AwContents to use to show it.
147 new_contents
->WasHidden();
149 // The embedder has forgone their chance to display this popup
150 // window, so we're done with the WebContents now. We use
151 // DeleteSoon as WebContentsImpl may call methods on |new_contents|
152 // after this method returns.
153 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, new_contents
);
157 *was_blocked
= !create_popup
;
161 void AwWebContentsDelegate::CloseContents(WebContents
* source
) {
162 JNIEnv
* env
= AttachCurrentThread();
164 ScopedJavaLocalRef
<jobject
> java_delegate
= GetJavaDelegate(env
);
165 if (java_delegate
.obj()) {
166 Java_AwWebContentsDelegate_closeContents(env
, java_delegate
.obj());
170 void AwWebContentsDelegate::ActivateContents(WebContents
* contents
) {
171 JNIEnv
* env
= AttachCurrentThread();
173 ScopedJavaLocalRef
<jobject
> java_delegate
= GetJavaDelegate(env
);
174 if (java_delegate
.obj()) {
175 Java_AwWebContentsDelegate_activateContents(env
, java_delegate
.obj());
179 void AwWebContentsDelegate::RequestProtectedMediaIdentifierPermission(
180 const content::WebContents
* web_contents
,
181 const GURL
& frame_url
,
182 const base::Callback
<void(bool)>& callback
) {
186 static void FilesSelectedInChooser(
187 JNIEnv
* env
, jclass clazz
,
188 jint process_id
, jint render_id
, jint mode_flags
,
189 jobjectArray file_paths
) {
190 content::RenderViewHost
* rvh
= content::RenderViewHost::FromID(process_id
,
195 std::vector
<std::string
> file_path_str
;
196 // Note file_paths maybe NULL, but this will just yield a zero-length vector.
197 base::android::AppendJavaStringArrayToStringVector(env
, file_paths
,
199 std::vector
<ui::SelectedFileInfo
> files
;
200 files
.reserve(file_path_str
.size());
201 for (size_t i
= 0; i
< file_path_str
.size(); ++i
) {
202 files
.push_back(ui::SelectedFileInfo(base::FilePath(file_path_str
[i
]),
205 FileChooserParams::Mode mode
;
206 if (mode_flags
& kFileChooserModeOpenFolder
) {
207 mode
= FileChooserParams::UploadFolder
;
208 } else if (mode_flags
& kFileChooserModeOpenMultiple
) {
209 mode
= FileChooserParams::OpenMultiple
;
211 mode
= FileChooserParams::Open
;
213 LOG(INFO
) << "File Chooser result: mode = " << mode
214 << ", file paths = " << JoinString(file_path_str
, ":");
215 rvh
->FilesSelectedInChooser(files
, mode
);
218 bool RegisterAwWebContentsDelegate(JNIEnv
* env
) {
219 return RegisterNativesImpl(env
);
222 } // namespace android_webview