aw_web_contents_delegate.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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. 4 5#include "android_webview/native/aw_web_contents_delegate.h" 6 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 "android_webview/native/aw_contents_io_thread_client_impl.h" 11#include "base/android/jni_array.h" 12#include "base/android/jni_string.h" 13#include "base/android/scoped_java_ref.h" 14#include "base/lazy_instance.h" 15#include "base/message_loop/message_loop.h" 16#include "base/strings/string_util.h" 17#include "content/public/browser/render_process_host.h" 18#include "content/public/browser/render_view_host.h" 19#include "content/public/browser/web_contents.h" 20#include "content/public/common/file_chooser_params.h" 21#include "jni/AwWebContentsDelegate_jni.h" 22#include "ui/shell_dialogs/selected_file_info.h" 23 24using base::android::AttachCurrentThread; 25using base::android::ConvertUTF16ToJavaString; 26using base::android::ConvertUTF8ToJavaString; 27using base::android::ScopedJavaLocalRef; 28using content::FileChooserParams; 29using content::WebContents; 30 31namespace android_webview { 32 33namespace { 34 35// WARNING: these constants are exposed in the public interface Java side, so 36// must remain in sync with what clients are expecting. 37const int kFileChooserModeOpenMultiple = 1 << 0; 38const int kFileChooserModeOpenFolder = 1 << 1; 39 40base::LazyInstance<AwJavaScriptDialogManager>::Leaky 41 g_javascript_dialog_manager = LAZY_INSTANCE_INITIALIZER; 42} 43 44AwWebContentsDelegate::AwWebContentsDelegate( 45 JNIEnv* env, 46 jobject obj) 47 : WebContentsDelegateAndroid(env, obj) { 48} 49 50AwWebContentsDelegate::~AwWebContentsDelegate() { 51} 52 53content::JavaScriptDialogManager* 54AwWebContentsDelegate::GetJavaScriptDialogManager() { 55 return g_javascript_dialog_manager.Pointer(); 56} 57 58void AwWebContentsDelegate::FindReply(WebContents* web_contents, 59 int request_id, 60 int number_of_matches, 61 const gfx::Rect& selection_rect, 62 int active_match_ordinal, 63 bool final_update) { 64 AwContents* aw_contents = AwContents::FromWebContents(web_contents); 65 if (!aw_contents) 66 return; 67 68 aw_contents->GetFindHelper()->HandleFindReply(request_id, 69 number_of_matches, 70 active_match_ordinal, 71 final_update); 72} 73 74void AwWebContentsDelegate::CanDownload( 75 content::RenderViewHost* source, 76 int request_id, 77 const std::string& request_method, 78 const base::Callback<void(bool)>& callback) { 79 // Android webview intercepts download in its resource dispatcher host 80 // delegate, so should not reach here. 81 NOTREACHED(); 82 callback.Run(false); 83} 84 85void AwWebContentsDelegate::RunFileChooser(WebContents* web_contents, 86 const FileChooserParams& params) { 87 JNIEnv* env = AttachCurrentThread(); 88 ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env); 89 if (!java_delegate.obj()) 90 return; 91 92 int mode_flags = 0; 93 if (params.mode == FileChooserParams::OpenMultiple) { 94 mode_flags |= kFileChooserModeOpenMultiple; 95 } else if (params.mode == FileChooserParams::UploadFolder) { 96 // Folder implies multiple in Chrome. 97 mode_flags |= kFileChooserModeOpenMultiple | kFileChooserModeOpenFolder; 98 } else if (params.mode == FileChooserParams::Save) { 99 // Save not supported, so cancel it. 100 web_contents->GetRenderViewHost()->FilesSelectedInChooser( 101 std::vector<ui::SelectedFileInfo>(), 102 params.mode); 103 return; 104 } else { 105 DCHECK_EQ(FileChooserParams::Open, params.mode); 106 } 107 Java_AwWebContentsDelegate_runFileChooser(env, 108 java_delegate.obj(), 109 web_contents->GetRenderProcessHost()->GetID(), 110 web_contents->GetRenderViewHost()->GetRoutingID(), 111 mode_flags, 112 ConvertUTF16ToJavaString(env, 113 JoinString(params.accept_types, ',')).obj(), 114 params.title.empty() ? NULL : 115 ConvertUTF16ToJavaString(env, params.title).obj(), 116 params.default_file_name.empty() ? NULL : 117 ConvertUTF8ToJavaString(env, params.default_file_name.value()).obj(), 118 params.capture); 119} 120 121void AwWebContentsDelegate::AddNewContents(WebContents* source, 122 WebContents* new_contents, 123 WindowOpenDisposition disposition, 124 const gfx::Rect& initial_pos, 125 bool user_gesture, 126 bool* was_blocked) { 127 JNIEnv* env = AttachCurrentThread(); 128 129 bool is_dialog = disposition == NEW_POPUP; 130 ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env); 131 bool create_popup = false; 132 133 if (java_delegate.obj()) { 134 create_popup = Java_AwWebContentsDelegate_addNewContents(env, 135 java_delegate.obj(), is_dialog, user_gesture); 136 } 137 138 if (create_popup) { 139 // The embedder would like to display the popup and we will receive 140 // a callback from them later with an AwContents to use to display 141 // it. The source AwContents takes ownership of the new WebContents 142 // until then, and when the callback is made we will swap the WebContents 143 // out into the new AwContents. 144 AwContents::FromWebContents(source)->SetPendingWebContentsForPopup( 145 make_scoped_ptr(new_contents)); 146 // Hide the WebContents for the pop up now, we will show it again 147 // when the user calls us back with an AwContents to use to show it. 148 new_contents->WasHidden(); 149 } else { 150 // The embedder has forgone their chance to display this popup 151 // window, so we're done with the WebContents now. We use 152 // DeleteSoon as WebContentsImpl may call methods on |new_contents| 153 // after this method returns. 154 base::MessageLoop::current()->DeleteSoon(FROM_HERE, new_contents); 155 } 156 157 if (was_blocked) { 158 *was_blocked = !create_popup; 159 } 160} 161 162// Notifies the delegate about the creation of a new WebContents. This 163// typically happens when popups are created. 164void AwWebContentsDelegate::WebContentsCreated( 165 WebContents* source_contents, 166 int64 source_frame_id, 167 const base::string16& frame_name, 168 const GURL& target_url, 169 content::WebContents* new_contents) { 170 AwContentsIoThreadClientImpl::RegisterPendingContents(new_contents); 171} 172 173void AwWebContentsDelegate::CloseContents(WebContents* source) { 174 JNIEnv* env = AttachCurrentThread(); 175 176 ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env); 177 if (java_delegate.obj()) { 178 Java_AwWebContentsDelegate_closeContents(env, java_delegate.obj()); 179 } 180} 181 182void AwWebContentsDelegate::ActivateContents(WebContents* contents) { 183 JNIEnv* env = AttachCurrentThread(); 184 185 ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env); 186 if (java_delegate.obj()) { 187 Java_AwWebContentsDelegate_activateContents(env, java_delegate.obj()); 188 } 189} 190 191static void FilesSelectedInChooser( 192 JNIEnv* env, jclass clazz, 193 jint process_id, jint render_id, jint mode_flags, 194 jobjectArray file_paths) { 195 content::RenderViewHost* rvh = content::RenderViewHost::FromID(process_id, 196 render_id); 197 if (!rvh) 198 return; 199 200 std::vector<std::string> file_path_str; 201 // Note file_paths maybe NULL, but this will just yield a zero-length vector. 202 base::android::AppendJavaStringArrayToStringVector(env, file_paths, 203 &file_path_str); 204 std::vector<ui::SelectedFileInfo> files; 205 files.reserve(file_path_str.size()); 206 for (size_t i = 0; i < file_path_str.size(); ++i) { 207 GURL url(file_path_str[i]); 208 if (!url.is_valid()) 209 continue; 210 base::FilePath path(url.SchemeIsFile() ? url.path() : file_path_str[i]); 211 files.push_back(ui::SelectedFileInfo(path, base::FilePath())); 212 } 213 FileChooserParams::Mode mode; 214 if (mode_flags & kFileChooserModeOpenFolder) { 215 mode = FileChooserParams::UploadFolder; 216 } else if (mode_flags & kFileChooserModeOpenMultiple) { 217 mode = FileChooserParams::OpenMultiple; 218 } else { 219 mode = FileChooserParams::Open; 220 } 221 DVLOG(0) << "File Chooser result: mode = " << mode 222 << ", file paths = " << JoinString(file_path_str, ":"); 223 rvh->FilesSelectedInChooser(files, mode); 224} 225 226bool RegisterAwWebContentsDelegate(JNIEnv* env) { 227 return RegisterNativesImpl(env); 228} 229 230} // namespace android_webview 231