Fix infinite recursion on hiding panel when created during fullscreen mode.
[chromium-blink-merge.git] / chrome / browser / android / chrome_web_contents_delegate_android.cc
blob3f6aa0e530c02820964c685c930475b4ca908b66
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 "chrome/browser/android/chrome_web_contents_delegate_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/command_line.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/file_select_helper.h"
12 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
13 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
14 #include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
15 #include "chrome/browser/prerender/prerender_manager.h"
16 #include "chrome/browser/prerender/prerender_manager_factory.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h"
19 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
20 #include "chrome/browser/ui/browser_navigator.h"
21 #include "chrome/browser/ui/find_bar/find_notification_details.h"
22 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
23 #include "chrome/browser/ui/tab_helpers.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/common/file_chooser_params.h"
32 #include "jni/ChromeWebContentsDelegateAndroid_jni.h"
33 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
34 #include "ui/gfx/rect.h"
35 #include "ui/gfx/rect_f.h"
37 #if defined(ENABLE_PLUGINS)
38 #include "chrome/browser/pepper_broker_infobar_delegate.h"
39 #endif
41 using base::android::AttachCurrentThread;
42 using base::android::ScopedJavaLocalRef;
43 using content::FileChooserParams;
44 using content::WebContents;
46 namespace {
48 ScopedJavaLocalRef<jobject> CreateJavaRectF(
49 JNIEnv* env,
50 const gfx::RectF& rect) {
51 return ScopedJavaLocalRef<jobject>(
52 Java_ChromeWebContentsDelegateAndroid_createRectF(env,
53 rect.x(),
54 rect.y(),
55 rect.right(),
56 rect.bottom()));
59 ScopedJavaLocalRef<jobject> CreateJavaRect(
60 JNIEnv* env,
61 const gfx::Rect& rect) {
62 return ScopedJavaLocalRef<jobject>(
63 Java_ChromeWebContentsDelegateAndroid_createRect(
64 env,
65 static_cast<int>(rect.x()),
66 static_cast<int>(rect.y()),
67 static_cast<int>(rect.right()),
68 static_cast<int>(rect.bottom())));
71 } // anonymous namespace
73 namespace chrome {
74 namespace android {
76 ChromeWebContentsDelegateAndroid::ChromeWebContentsDelegateAndroid(JNIEnv* env,
77 jobject obj)
78 : WebContentsDelegateAndroid(env, obj) {
81 ChromeWebContentsDelegateAndroid::~ChromeWebContentsDelegateAndroid() {
82 notification_registrar_.RemoveAll();
85 // Register native methods.
86 bool RegisterChromeWebContentsDelegateAndroid(JNIEnv* env) {
87 return RegisterNativesImpl(env);
90 void ChromeWebContentsDelegateAndroid::LoadingStateChanged(
91 WebContents* source) {
92 bool has_stopped = source == NULL || !source->IsLoading();
93 WebContentsDelegateAndroid::LoadingStateChanged(source);
94 LoadProgressChanged(source, has_stopped ? 1 : 0);
97 void ChromeWebContentsDelegateAndroid::RunFileChooser(
98 WebContents* web_contents,
99 const FileChooserParams& params) {
100 FileSelectHelper::RunFileChooser(web_contents, params);
103 void ChromeWebContentsDelegateAndroid::CloseContents(
104 WebContents* web_contents) {
105 // Prevent dangling registrations assigned to closed web contents.
106 if (notification_registrar_.IsRegistered(this,
107 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE,
108 content::Source<WebContents>(web_contents))) {
109 notification_registrar_.Remove(this,
110 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE,
111 content::Source<WebContents>(web_contents));
114 WebContentsDelegateAndroid::CloseContents(web_contents);
117 void ChromeWebContentsDelegateAndroid::Observe(
118 int type,
119 const content::NotificationSource& source,
120 const content::NotificationDetails& details) {
121 switch (type) {
122 case chrome::NOTIFICATION_FIND_RESULT_AVAILABLE:
123 OnFindResultAvailable(
124 content::Source<WebContents>(source).ptr(),
125 content::Details<FindNotificationDetails>(details).ptr());
126 break;
127 default:
128 NOTREACHED() << "Unexpected notification: " << type;
129 break;
133 void ChromeWebContentsDelegateAndroid::FindReply(
134 WebContents* web_contents,
135 int request_id,
136 int number_of_matches,
137 const gfx::Rect& selection_rect,
138 int active_match_ordinal,
139 bool final_update) {
140 if (!notification_registrar_.IsRegistered(this,
141 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE,
142 content::Source<WebContents>(web_contents))) {
143 notification_registrar_.Add(this,
144 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE,
145 content::Source<WebContents>(web_contents));
148 FindTabHelper* find_tab_helper = FindTabHelper::FromWebContents(web_contents);
149 find_tab_helper->HandleFindReply(request_id,
150 number_of_matches,
151 selection_rect,
152 active_match_ordinal,
153 final_update);
156 void ChromeWebContentsDelegateAndroid::OnFindResultAvailable(
157 WebContents* web_contents,
158 const FindNotificationDetails* find_result) {
159 JNIEnv* env = base::android::AttachCurrentThread();
160 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
161 if (obj.is_null())
162 return;
164 ScopedJavaLocalRef<jobject> selection_rect = CreateJavaRect(
165 env, find_result->selection_rect());
167 // Create the details object.
168 ScopedJavaLocalRef<jobject> details_object =
169 Java_ChromeWebContentsDelegateAndroid_createFindNotificationDetails(
170 env,
171 find_result->number_of_matches(),
172 selection_rect.obj(),
173 find_result->active_match_ordinal(),
174 find_result->final_update());
176 Java_ChromeWebContentsDelegateAndroid_onFindResultAvailable(
177 env,
178 obj.obj(),
179 details_object.obj());
182 void ChromeWebContentsDelegateAndroid::FindMatchRectsReply(
183 WebContents* web_contents,
184 int version,
185 const std::vector<gfx::RectF>& rects,
186 const gfx::RectF& active_rect) {
187 JNIEnv* env = base::android::AttachCurrentThread();
188 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
189 if (obj.is_null())
190 return;
192 // Create the details object.
193 ScopedJavaLocalRef<jobject> details_object =
194 Java_ChromeWebContentsDelegateAndroid_createFindMatchRectsDetails(
195 env,
196 version,
197 rects.size(),
198 CreateJavaRectF(env, active_rect).obj());
200 // Add the rects
201 for (size_t i = 0; i < rects.size(); ++i) {
202 Java_ChromeWebContentsDelegateAndroid_setMatchRectByIndex(
203 env,
204 details_object.obj(),
206 CreateJavaRectF(env, rects[i]).obj());
209 Java_ChromeWebContentsDelegateAndroid_onFindMatchRectsAvailable(
210 env,
211 obj.obj(),
212 details_object.obj());
215 content::JavaScriptDialogManager*
216 ChromeWebContentsDelegateAndroid::GetJavaScriptDialogManager() {
217 return GetJavaScriptDialogManagerInstance();
220 void ChromeWebContentsDelegateAndroid::RequestMediaAccessPermission(
221 content::WebContents* web_contents,
222 const content::MediaStreamRequest& request,
223 const content::MediaResponseCallback& callback) {
224 MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
225 web_contents, request, callback, NULL);
228 bool ChromeWebContentsDelegateAndroid::RequestPpapiBrokerPermission(
229 WebContents* web_contents,
230 const GURL& url,
231 const base::FilePath& plugin_path,
232 const base::Callback<void(bool)>& callback) {
233 #if defined(ENABLE_PLUGINS)
234 PepperBrokerInfoBarDelegate::Create(
235 web_contents, url, plugin_path, callback);
236 return true;
237 #else
238 return false;
239 #endif
242 WebContents* ChromeWebContentsDelegateAndroid::OpenURLFromTab(
243 WebContents* source,
244 const content::OpenURLParams& params) {
245 WindowOpenDisposition disposition = params.disposition;
246 if (!source || (disposition != CURRENT_TAB &&
247 disposition != NEW_FOREGROUND_TAB &&
248 disposition != NEW_BACKGROUND_TAB &&
249 disposition != OFF_THE_RECORD &&
250 disposition != NEW_POPUP &&
251 disposition != NEW_WINDOW)) {
252 // We can't handle this here. Give the parent a chance.
253 return WebContentsDelegateAndroid::OpenURLFromTab(source, params);
256 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
257 chrome::NavigateParams nav_params(profile,
258 params.url,
259 params.transition);
260 FillNavigateParamsFromOpenURLParams(&nav_params, params);
261 nav_params.source_contents = source;
262 nav_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
263 nav_params.user_gesture = params.user_gesture;
265 PopupBlockerTabHelper* popup_blocker_helper =
266 PopupBlockerTabHelper::FromWebContents(source);
267 DCHECK(popup_blocker_helper);
269 if ((params.disposition == NEW_POPUP ||
270 params.disposition == NEW_FOREGROUND_TAB ||
271 params.disposition == NEW_BACKGROUND_TAB ||
272 params.disposition == NEW_WINDOW) &&
273 !params.user_gesture &&
274 !CommandLine::ForCurrentProcess()->HasSwitch(
275 switches::kDisablePopupBlocking)) {
276 if (popup_blocker_helper->MaybeBlockPopup(nav_params,
277 blink::WebWindowFeatures())) {
278 return NULL;
282 if (disposition == CURRENT_TAB) {
283 // Only prerender for a current-tab navigation to avoid session storage
284 // namespace issues.
285 nav_params.target_contents = source;
286 prerender::PrerenderManager* prerender_manager =
287 prerender::PrerenderManagerFactory::GetForProfile(profile);
288 if (prerender_manager &&
289 prerender_manager->MaybeUsePrerenderedPage(params.url, &nav_params)) {
290 return nav_params.target_contents;
294 return WebContentsDelegateAndroid::OpenURLFromTab(source, params);
297 void ChromeWebContentsDelegateAndroid::AddNewContents(
298 WebContents* source,
299 WebContents* new_contents,
300 WindowOpenDisposition disposition,
301 const gfx::Rect& initial_pos,
302 bool user_gesture,
303 bool* was_blocked) {
304 // No code for this yet.
305 DCHECK_NE(disposition, SAVE_TO_DISK);
306 // Can't create a new contents for the current tab - invalid case.
307 DCHECK_NE(disposition, CURRENT_TAB);
309 TabHelpers::AttachTabHelpers(new_contents);
311 JNIEnv* env = AttachCurrentThread();
312 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
313 bool handled = false;
314 if (!obj.is_null()) {
315 handled = Java_ChromeWebContentsDelegateAndroid_addNewContents(
316 env,
317 obj.obj(),
318 reinterpret_cast<intptr_t>(source),
319 reinterpret_cast<intptr_t>(new_contents),
320 static_cast<jint>(disposition),
321 NULL,
322 user_gesture);
325 if (!handled)
326 delete new_contents;
329 void ChromeWebContentsDelegateAndroid::WebContentsCreated(
330 content::WebContents* source_contents, int opener_render_frame_id,
331 const base::string16& frame_name, const GURL& target_url,
332 content::WebContents* new_contents) {
333 JNIEnv* env = AttachCurrentThread();
334 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
335 if (obj.is_null())
336 return;
337 Java_ChromeWebContentsDelegateAndroid_webContentsCreated(env, obj.obj(),
338 reinterpret_cast<intptr_t>(source_contents), opener_render_frame_id,
339 base::android::ConvertUTF16ToJavaString(env, frame_name).Release(),
340 base::android::ConvertUTF8ToJavaString(env, target_url.spec()).Release(),
341 reinterpret_cast<intptr_t>(new_contents));
344 } // namespace android
345 } // namespace chrome