Update V8 to version 4.6.55.
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_android.cc
blob647accd5e4516227ee24f2391238ce5600da70b9
1 // Copyright 2013 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 "content/browser/web_contents/web_contents_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/command_line.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/json/json_writer.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "content/browser/accessibility/browser_accessibility_android.h"
16 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
17 #include "content/browser/android/content_view_core_impl.h"
18 #include "content/browser/android/interstitial_page_delegate_android.h"
19 #include "content/browser/frame_host/interstitial_page_impl.h"
20 #include "content/browser/media/android/browser_media_player_manager.h"
21 #include "content/browser/media/media_web_contents_observer.h"
22 #include "content/browser/renderer_host/render_view_host_impl.h"
23 #include "content/browser/web_contents/web_contents_impl.h"
24 #include "content/common/devtools_messages.h"
25 #include "content/common/frame_messages.h"
26 #include "content/common/input_messages.h"
27 #include "content/common/view_messages.h"
28 #include "content/public/browser/browser_context.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/message_port_provider.h"
31 #include "content/public/browser/web_contents.h"
32 #include "content/public/common/content_switches.h"
33 #include "jni/WebContentsImpl_jni.h"
34 #include "net/android/network_library.h"
35 #include "ui/accessibility/ax_node_data.h"
36 #include "ui/gfx/android/device_display_info.h"
38 using base::android::AttachCurrentThread;
39 using base::android::ConvertJavaStringToUTF8;
40 using base::android::ConvertJavaStringToUTF16;
41 using base::android::ConvertUTF8ToJavaString;
42 using base::android::ConvertUTF16ToJavaString;
43 using base::android::ScopedJavaGlobalRef;
44 using base::android::ToJavaIntArray;
46 namespace content {
48 namespace {
50 // Track all WebContentsAndroid objects here so that we don't deserialize a
51 // destroyed WebContents object.
52 base::LazyInstance<base::hash_set<WebContentsAndroid*> >::Leaky
53 g_allocated_web_contents_androids = LAZY_INSTANCE_INITIALIZER;
55 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
56 const base::Value* result) {
57 JNIEnv* env = base::android::AttachCurrentThread();
58 std::string json;
59 base::JSONWriter::Write(*result, &json);
60 ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
61 Java_WebContentsImpl_onEvaluateJavaScriptResult(
62 env, j_json.obj(), callback.obj());
65 ScopedJavaLocalRef<jobject> WalkAXTreeDepthFirst(JNIEnv* env,
66 BrowserAccessibilityAndroid* node, float scale_factor,
67 float y_offset, float x_scroll) {
68 ScopedJavaLocalRef<jstring> j_text =
69 ConvertUTF16ToJavaString(env, node->GetText());
70 ScopedJavaLocalRef<jstring> j_class =
71 ConvertUTF8ToJavaString(env, node->GetClassName());
72 const gfx::Rect& location = node->GetLocalBoundsRect();
73 // The style attributes exists and valid if size attribute exists. Otherwise,
74 // they are not. Use a negative size information to indicate the existence
75 // of style information.
76 float size = -1.0;
77 int color = 0;
78 int bgcolor = 0;
79 int text_style = 0;
80 if (node->HasFloatAttribute(ui::AX_ATTR_FONT_SIZE)) {
81 color = node->GetIntAttribute(ui::AX_ATTR_COLOR);
82 bgcolor = node->GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR);
83 size = node->GetFloatAttribute(ui::AX_ATTR_FONT_SIZE);
84 text_style = node->GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
86 ScopedJavaLocalRef<jobject> j_node =
87 Java_WebContentsImpl_createAccessibilitySnapshotNode(env,
88 scale_factor * location.x() - x_scroll,
89 scale_factor * location.y() + y_offset,
90 scale_factor * node->GetScrollX(), scale_factor * node->GetScrollY(),
91 scale_factor * location.width(), scale_factor * location.height(),
92 j_text.obj(), color, bgcolor, scale_factor * size, text_style,
93 j_class.obj());
95 for(uint32 i = 0; i < node->PlatformChildCount(); i++) {
96 BrowserAccessibilityAndroid* child =
97 static_cast<BrowserAccessibilityAndroid*>(
98 node->PlatformGetChild(i));
99 Java_WebContentsImpl_addAccessibilityNodeAsChild(env,
100 j_node.obj(), WalkAXTreeDepthFirst(env, child, scale_factor, y_offset,
101 x_scroll).obj());
103 return j_node;
106 // Walks over the AXTreeUpdate and creates a light weight snapshot.
107 void AXTreeSnapshotCallback(const ScopedJavaGlobalRef<jobject>& callback,
108 float scale_factor,
109 float y_offset,
110 float x_scroll,
111 const ui::AXTreeUpdate<ui::AXNodeData>& result) {
112 JNIEnv* env = base::android::AttachCurrentThread();
113 if (result.nodes.empty()) {
114 Java_WebContentsImpl_onAccessibilitySnapshot(env, nullptr, callback.obj());
115 return;
117 scoped_ptr<BrowserAccessibilityManagerAndroid> manager(
118 static_cast<BrowserAccessibilityManagerAndroid*>(
119 BrowserAccessibilityManager::Create(result, nullptr)));
120 manager->set_prune_tree_for_screen_reader(false);
121 BrowserAccessibilityAndroid* root =
122 static_cast<BrowserAccessibilityAndroid*>(manager->GetRoot());
123 ScopedJavaLocalRef<jobject> j_root =
124 WalkAXTreeDepthFirst(env, root, scale_factor, y_offset, x_scroll);
125 Java_WebContentsImpl_onAccessibilitySnapshot(
126 env, j_root.obj(), callback.obj());
129 void ReleaseAllMediaPlayers(WebContents* web_contents,
130 RenderFrameHost* render_frame_host) {
131 BrowserMediaPlayerManager* manager =
132 static_cast<WebContentsImpl*>(web_contents)->
133 media_web_contents_observer()->GetMediaPlayerManager(
134 render_frame_host);
135 if (manager)
136 manager->ReleaseAllMediaPlayers();
139 } // namespace
141 // static
142 WebContents* WebContents::FromJavaWebContents(
143 jobject jweb_contents_android) {
144 DCHECK_CURRENTLY_ON(BrowserThread::UI);
145 if (!jweb_contents_android)
146 return NULL;
148 WebContentsAndroid* web_contents_android =
149 reinterpret_cast<WebContentsAndroid*>(
150 Java_WebContentsImpl_getNativePointer(AttachCurrentThread(),
151 jweb_contents_android));
152 if (!web_contents_android)
153 return NULL;
154 return web_contents_android->web_contents();
157 // static
158 static void DestroyWebContents(JNIEnv* env,
159 jclass clazz,
160 jlong jweb_contents_android_ptr) {
161 WebContentsAndroid* web_contents_android =
162 reinterpret_cast<WebContentsAndroid*>(jweb_contents_android_ptr);
163 if (!web_contents_android)
164 return;
166 WebContents* web_contents = web_contents_android->web_contents();
167 if (!web_contents)
168 return;
170 delete web_contents;
173 // static
174 jobject FromNativePtr(JNIEnv* env,
175 jclass clazz,
176 jlong web_contents_ptr) {
177 WebContentsAndroid* web_contents_android =
178 reinterpret_cast<WebContentsAndroid*>(web_contents_ptr);
180 if (!web_contents_android)
181 return 0;
183 // Check to make sure this object hasn't been destroyed.
184 if (g_allocated_web_contents_androids.Get().find(web_contents_android) ==
185 g_allocated_web_contents_androids.Get().end()) {
186 return 0;
189 return web_contents_android->GetJavaObject().Release();
192 // static
193 bool WebContentsAndroid::Register(JNIEnv* env) {
194 return RegisterNativesImpl(env);
197 WebContentsAndroid::WebContentsAndroid(WebContents* web_contents)
198 : web_contents_(web_contents),
199 navigation_controller_(&(web_contents->GetController())),
200 weak_factory_(this) {
201 g_allocated_web_contents_androids.Get().insert(this);
202 JNIEnv* env = AttachCurrentThread();
203 obj_.Reset(env,
204 Java_WebContentsImpl_create(
205 env,
206 reinterpret_cast<intptr_t>(this),
207 navigation_controller_.GetJavaObject().obj()).obj());
208 RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
209 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
210 prefs->network_contry_iso =
211 command_line->HasSwitch(switches::kNetworkCountryIso) ?
212 command_line->GetSwitchValueASCII(switches::kNetworkCountryIso)
213 : net::android::GetTelephonyNetworkCountryIso();
216 WebContentsAndroid::~WebContentsAndroid() {
217 DCHECK(g_allocated_web_contents_androids.Get().find(this) !=
218 g_allocated_web_contents_androids.Get().end());
219 g_allocated_web_contents_androids.Get().erase(this);
220 Java_WebContentsImpl_clearNativePtr(AttachCurrentThread(), obj_.obj());
223 base::android::ScopedJavaLocalRef<jobject>
224 WebContentsAndroid::GetJavaObject() {
225 return base::android::ScopedJavaLocalRef<jobject>(obj_);
228 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetTitle(
229 JNIEnv* env, jobject obj) const {
230 return base::android::ConvertUTF16ToJavaString(env,
231 web_contents_->GetTitle());
234 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetVisibleURL(
235 JNIEnv* env, jobject obj) const {
236 return base::android::ConvertUTF8ToJavaString(
237 env, web_contents_->GetVisibleURL().spec());
240 bool WebContentsAndroid::IsLoading(JNIEnv* env, jobject obj) const {
241 return web_contents_->IsLoading();
244 bool WebContentsAndroid::IsLoadingToDifferentDocument(JNIEnv* env,
245 jobject obj) const {
246 return web_contents_->IsLoadingToDifferentDocument();
249 void WebContentsAndroid::Stop(JNIEnv* env, jobject obj) {
250 web_contents_->Stop();
253 void WebContentsAndroid::Cut(JNIEnv* env, jobject obj) {
254 web_contents_->Cut();
257 void WebContentsAndroid::Copy(JNIEnv* env, jobject obj) {
258 web_contents_->Copy();
261 void WebContentsAndroid::Paste(JNIEnv* env, jobject obj) {
262 web_contents_->Paste();
265 void WebContentsAndroid::SelectAll(JNIEnv* env, jobject obj) {
266 web_contents_->SelectAll();
269 void WebContentsAndroid::Unselect(JNIEnv* env, jobject obj) {
270 web_contents_->Unselect();
273 void WebContentsAndroid::InsertCSS(
274 JNIEnv* env, jobject jobj, jstring jcss) {
275 web_contents_->InsertCSS(base::android::ConvertJavaStringToUTF8(env, jcss));
278 RenderWidgetHostViewAndroid*
279 WebContentsAndroid::GetRenderWidgetHostViewAndroid() {
280 RenderWidgetHostView* rwhv = NULL;
281 rwhv = web_contents_->GetRenderWidgetHostView();
282 if (web_contents_->ShowingInterstitialPage()) {
283 rwhv = web_contents_->GetInterstitialPage()
284 ->GetMainFrame()
285 ->GetRenderViewHost()
286 ->GetView();
288 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
291 jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env, jobject obj) {
292 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
293 if (!rwhva)
294 return SK_ColorWHITE;
295 return rwhva->GetCachedBackgroundColor();
298 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL(JNIEnv* env,
299 jobject obj) const {
300 return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec());
303 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetLastCommittedURL(
304 JNIEnv* env,
305 jobject) const {
306 return ConvertUTF8ToJavaString(env,
307 web_contents_->GetLastCommittedURL().spec());
311 jboolean WebContentsAndroid::IsIncognito(JNIEnv* env, jobject obj) {
312 return web_contents_->GetBrowserContext()->IsOffTheRecord();
315 void WebContentsAndroid::ResumeLoadingCreatedWebContents(JNIEnv* env,
316 jobject obj) {
317 web_contents_->ResumeLoadingCreatedWebContents();
320 void WebContentsAndroid::OnHide(JNIEnv* env, jobject obj) {
321 web_contents_->WasHidden();
324 void WebContentsAndroid::OnShow(JNIEnv* env, jobject obj) {
325 web_contents_->WasShown();
328 void WebContentsAndroid::ReleaseMediaPlayers(JNIEnv* env, jobject jobj) {
329 #if defined(ENABLE_BROWSER_CDMS)
330 web_contents_->ForEachFrame(
331 base::Bind(&ReleaseAllMediaPlayers, base::Unretained(web_contents_)));
332 #endif // defined(ENABLE_BROWSER_CDMS)
335 void WebContentsAndroid::ShowInterstitialPage(
336 JNIEnv* env,
337 jobject obj,
338 jstring jurl,
339 jlong delegate_ptr) {
340 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
341 InterstitialPageDelegateAndroid* delegate =
342 reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
343 InterstitialPage* interstitial = InterstitialPage::Create(
344 web_contents_, false, url, delegate);
345 delegate->set_interstitial_page(interstitial);
346 interstitial->Show();
349 jboolean WebContentsAndroid::IsShowingInterstitialPage(JNIEnv* env,
350 jobject obj) {
351 return web_contents_->ShowingInterstitialPage();
354 jboolean WebContentsAndroid::IsRenderWidgetHostViewReady(
355 JNIEnv* env,
356 jobject obj) {
357 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
358 return view && view->HasValidFrame();
361 void WebContentsAndroid::ExitFullscreen(JNIEnv* env, jobject obj) {
362 web_contents_->ExitFullscreen();
365 void WebContentsAndroid::UpdateTopControlsState(
366 JNIEnv* env,
367 jobject obj,
368 bool enable_hiding,
369 bool enable_showing,
370 bool animate) {
371 RenderViewHost* host = web_contents_->GetRenderViewHost();
372 if (!host)
373 return;
374 host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
375 enable_hiding,
376 enable_showing,
377 animate));
380 void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
381 RenderViewHost* host = web_contents_->GetRenderViewHost();
382 if (!host)
383 return;
384 host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
387 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
388 JNIEnv* env,
389 jobject obj) {
390 RenderViewHost* host = web_contents_->GetRenderViewHost();
391 if (!host)
392 return;
393 host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
394 host->GetRoutingID(), gfx::Rect()));
397 void WebContentsAndroid::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
398 RenderViewHost* host = web_contents_->GetRenderViewHost();
399 if (!host)
400 return;
401 host->SelectWordAroundCaret();
404 void WebContentsAndroid::AdjustSelectionByCharacterOffset(JNIEnv* env,
405 jobject obj,
406 jint start_adjust,
407 jint end_adjust) {
408 web_contents_->AdjustSelectionByCharacterOffset(start_adjust, end_adjust);
411 void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
412 jobject obj,
413 jstring script,
414 jobject callback) {
415 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
416 DCHECK(rvh);
418 if (!rvh->IsRenderViewLive()) {
419 if (!static_cast<WebContentsImpl*>(web_contents_)->
420 CreateRenderViewForInitialEmptyDocument()) {
421 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
422 return;
426 if (!callback) {
427 // No callback requested.
428 web_contents_->GetMainFrame()->ExecuteJavaScript(
429 ConvertJavaStringToUTF16(env, script));
430 return;
433 // Secure the Java callback in a scoped object and give ownership of it to the
434 // base::Callback.
435 ScopedJavaGlobalRef<jobject> j_callback;
436 j_callback.Reset(env, callback);
437 RenderFrameHost::JavaScriptResultCallback js_callback =
438 base::Bind(&JavaScriptResultCallback, j_callback);
440 web_contents_->GetMainFrame()->ExecuteJavaScript(
441 ConvertJavaStringToUTF16(env, script), js_callback);
444 void WebContentsAndroid::EvaluateJavaScriptForTests(JNIEnv* env,
445 jobject obj,
446 jstring script,
447 jobject callback) {
448 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
449 DCHECK(rvh);
451 if (!rvh->IsRenderViewLive()) {
452 if (!static_cast<WebContentsImpl*>(web_contents_)->
453 CreateRenderViewForInitialEmptyDocument()) {
454 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScriptForTests";
455 return;
459 if (!callback) {
460 // No callback requested.
461 web_contents_->GetMainFrame()->ExecuteJavaScriptForTests(
462 ConvertJavaStringToUTF16(env, script));
463 return;
466 // Secure the Java callback in a scoped object and give ownership of it to the
467 // base::Callback.
468 ScopedJavaGlobalRef<jobject> j_callback;
469 j_callback.Reset(env, callback);
470 RenderFrameHost::JavaScriptResultCallback js_callback =
471 base::Bind(&JavaScriptResultCallback, j_callback);
473 web_contents_->GetMainFrame()->ExecuteJavaScriptForTests(
474 ConvertJavaStringToUTF16(env, script), js_callback);
477 void WebContentsAndroid::AddMessageToDevToolsConsole(JNIEnv* env,
478 jobject jobj,
479 jint level,
480 jstring message) {
481 DCHECK_GE(level, 0);
482 DCHECK_LE(level, CONSOLE_MESSAGE_LEVEL_LAST);
484 web_contents_->GetMainFrame()->AddMessageToConsole(
485 static_cast<ConsoleMessageLevel>(level),
486 ConvertJavaStringToUTF8(env, message));
489 void WebContentsAndroid::SendMessageToFrame(JNIEnv* env,
490 jobject obj,
491 jstring frame_name,
492 jstring message,
493 jstring target_origin) {
494 base::string16 source_origin;
495 base::string16 j_target_origin(ConvertJavaStringToUTF16(env, target_origin));
496 base::string16 j_message(ConvertJavaStringToUTF16(env, message));
497 std::vector<content::TransferredMessagePort> ports;
498 content::MessagePortProvider::PostMessageToFrame(
499 web_contents_, source_origin, j_target_origin, j_message, ports);
502 jboolean WebContentsAndroid::HasAccessedInitialDocument(
503 JNIEnv* env,
504 jobject jobj) {
505 return static_cast<WebContentsImpl*>(web_contents_)->
506 HasAccessedInitialDocument();
509 jint WebContentsAndroid::GetThemeColor(JNIEnv* env, jobject obj) {
510 return web_contents_->GetThemeColor();
513 void WebContentsAndroid::RequestAccessibilitySnapshot(JNIEnv* env,
514 jobject obj,
515 jobject callback,
516 jfloat y_offset,
517 jfloat x_scroll) {
518 // Secure the Java callback in a scoped object and give ownership of it to the
519 // base::Callback.
520 ScopedJavaGlobalRef<jobject> j_callback;
521 j_callback.Reset(env, callback);
522 gfx::DeviceDisplayInfo device_info;
523 ContentViewCoreImpl* contentViewCore =
524 ContentViewCoreImpl::FromWebContents(web_contents_);
525 WebContentsImpl::AXTreeSnapshotCallback snapshot_callback =
526 base::Bind(&AXTreeSnapshotCallback, j_callback,
527 contentViewCore->GetScaleFactor(), y_offset, x_scroll);
528 static_cast<WebContentsImpl*>(web_contents_)->RequestAXTreeSnapshot(
529 snapshot_callback);
532 void WebContentsAndroid::ResumeMediaSession(JNIEnv* env, jobject obj) {
533 web_contents_->ResumeMediaSession();
536 void WebContentsAndroid::SuspendMediaSession(JNIEnv* env, jobject obj) {
537 web_contents_->SuspendMediaSession();
540 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetEncoding(
541 JNIEnv* env, jobject obj) const {
542 return base::android::ConvertUTF8ToJavaString(env,
543 web_contents_->GetEncoding());
546 } // namespace content