chrome/browser/extensions: Remove use of MessageLoopProxy and deprecated MessageLoop...
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_android.cc
bloba18923aa80deb402d4129f1d9f08d6d6f167725f
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.h"
17 #include "content/browser/android/interstitial_page_delegate_android.h"
18 #include "content/browser/frame_host/interstitial_page_impl.h"
19 #include "content/browser/media/android/browser_media_player_manager.h"
20 #include "content/browser/media/media_web_contents_observer.h"
21 #include "content/browser/renderer_host/render_view_host_impl.h"
22 #include "content/browser/web_contents/web_contents_impl.h"
23 #include "content/common/devtools_messages.h"
24 #include "content/common/frame_messages.h"
25 #include "content/common/input_messages.h"
26 #include "content/common/view_messages.h"
27 #include "content/public/browser/browser_context.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/content_switches.h"
31 #include "jni/WebContentsImpl_jni.h"
32 #include "net/android/network_library.h"
33 #include "ui/accessibility/ax_node_data.h"
35 using base::android::AttachCurrentThread;
36 using base::android::ConvertJavaStringToUTF8;
37 using base::android::ConvertJavaStringToUTF16;
38 using base::android::ConvertUTF8ToJavaString;
39 using base::android::ConvertUTF16ToJavaString;
40 using base::android::ScopedJavaGlobalRef;
41 using base::android::ToJavaIntArray;
43 namespace content {
45 namespace {
47 // Track all WebContentsAndroid objects here so that we don't deserialize a
48 // destroyed WebContents object.
49 base::LazyInstance<base::hash_set<WebContentsAndroid*> >::Leaky
50 g_allocated_web_contents_androids = LAZY_INSTANCE_INITIALIZER;
52 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
53 const base::Value* result) {
54 JNIEnv* env = base::android::AttachCurrentThread();
55 std::string json;
56 base::JSONWriter::Write(*result, &json);
57 ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
58 Java_WebContentsImpl_onEvaluateJavaScriptResult(
59 env, j_json.obj(), callback.obj());
62 ScopedJavaLocalRef<jobject> WalkAXTreeDepthFirst(JNIEnv* env,
63 BrowserAccessibilityAndroid* node) {
65 ScopedJavaLocalRef<jstring> j_text =
66 ConvertUTF16ToJavaString(env, node->GetText());
67 ScopedJavaLocalRef<jstring> j_class =
68 ConvertUTF8ToJavaString(env, node->GetClassName());
69 const gfx::Rect& location = node->GetLocation();
70 // The style attributes exists and valid if size attribute exists. Otherwise,
71 // they are not. Use a negative size information to indicate the existence
72 // of style information.
73 float size = -1.0;
74 int color = 0;
75 int bgcolor = 0;
76 int text_style = 0;
77 if (node->HasFloatAttribute(ui::AX_ATTR_FONT_SIZE)) {
78 color = node->GetIntAttribute(ui::AX_ATTR_COLOR);
79 bgcolor = node->GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR);
80 size = node->GetFloatAttribute(ui::AX_ATTR_FONT_SIZE);
81 text_style = node->GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
84 ScopedJavaLocalRef<jobject> j_node =
85 Java_WebContentsImpl_createAccessibilitySnapshotNode(env,
86 location.x(), location.y(), node->GetScrollX(),
87 node->GetScrollY(), location.width(), location.height(),
88 j_text.obj(), color, bgcolor, size, text_style, j_class.obj());
90 for(uint32 i = 0; i < node->PlatformChildCount(); i++) {
91 BrowserAccessibilityAndroid* child =
92 static_cast<BrowserAccessibilityAndroid*>(
93 node->PlatformGetChild(i));
94 Java_WebContentsImpl_addAccessibilityNodeAsChild(env,
95 j_node.obj(), WalkAXTreeDepthFirst(env, child).obj());
97 return j_node;
100 // Walks over the AXTreeUpdate and creates a light weight snapshot.
101 void AXTreeSnapshotCallback(const ScopedJavaGlobalRef<jobject>& callback,
102 const ui::AXTreeUpdate& result) {
103 JNIEnv* env = base::android::AttachCurrentThread();
104 if (result.nodes.empty()) {
105 Java_WebContentsImpl_onAccessibilitySnapshot(env, nullptr, callback.obj());
106 return;
108 scoped_ptr<BrowserAccessibilityManager> manager(
109 BrowserAccessibilityManager::Create(result, nullptr));
110 BrowserAccessibilityAndroid* root =
111 static_cast<BrowserAccessibilityAndroid*>(manager->GetRoot());
112 ScopedJavaLocalRef<jobject> j_root = WalkAXTreeDepthFirst(env, root);
113 Java_WebContentsImpl_onAccessibilitySnapshot(
114 env, j_root.obj(), callback.obj());
117 void ReleaseAllMediaPlayers(WebContents* web_contents,
118 RenderFrameHost* render_frame_host) {
119 BrowserMediaPlayerManager* manager =
120 static_cast<WebContentsImpl*>(web_contents)->
121 media_web_contents_observer()->GetMediaPlayerManager(
122 render_frame_host);
123 if (manager)
124 manager->ReleaseAllMediaPlayers();
127 } // namespace
129 // static
130 WebContents* WebContents::FromJavaWebContents(
131 jobject jweb_contents_android) {
132 DCHECK_CURRENTLY_ON(BrowserThread::UI);
133 if (!jweb_contents_android)
134 return NULL;
136 WebContentsAndroid* web_contents_android =
137 reinterpret_cast<WebContentsAndroid*>(
138 Java_WebContentsImpl_getNativePointer(AttachCurrentThread(),
139 jweb_contents_android));
140 if (!web_contents_android)
141 return NULL;
142 return web_contents_android->web_contents();
145 // static
146 static void DestroyWebContents(JNIEnv* env,
147 jclass clazz,
148 jlong jweb_contents_android_ptr) {
149 WebContentsAndroid* web_contents_android =
150 reinterpret_cast<WebContentsAndroid*>(jweb_contents_android_ptr);
151 if (!web_contents_android)
152 return;
154 WebContents* web_contents = web_contents_android->web_contents();
155 if (!web_contents)
156 return;
158 delete web_contents;
161 // static
162 jobject FromNativePtr(JNIEnv* env,
163 jclass clazz,
164 jlong web_contents_ptr) {
165 WebContentsAndroid* web_contents_android =
166 reinterpret_cast<WebContentsAndroid*>(web_contents_ptr);
168 if (!web_contents_android)
169 return 0;
171 // Check to make sure this object hasn't been destroyed.
172 if (g_allocated_web_contents_androids.Get().find(web_contents_android) ==
173 g_allocated_web_contents_androids.Get().end()) {
174 return 0;
177 return web_contents_android->GetJavaObject().Release();
180 // static
181 bool WebContentsAndroid::Register(JNIEnv* env) {
182 return RegisterNativesImpl(env);
185 WebContentsAndroid::WebContentsAndroid(WebContents* web_contents)
186 : web_contents_(web_contents),
187 navigation_controller_(&(web_contents->GetController())),
188 weak_factory_(this) {
189 g_allocated_web_contents_androids.Get().insert(this);
190 JNIEnv* env = AttachCurrentThread();
191 obj_.Reset(env,
192 Java_WebContentsImpl_create(
193 env,
194 reinterpret_cast<intptr_t>(this),
195 navigation_controller_.GetJavaObject().obj()).obj());
196 RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
197 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
198 prefs->network_contry_iso =
199 command_line->HasSwitch(switches::kNetworkCountryIso) ?
200 command_line->GetSwitchValueASCII(switches::kNetworkCountryIso)
201 : net::android::GetTelephonyNetworkCountryIso();
204 WebContentsAndroid::~WebContentsAndroid() {
205 DCHECK(g_allocated_web_contents_androids.Get().find(this) !=
206 g_allocated_web_contents_androids.Get().end());
207 g_allocated_web_contents_androids.Get().erase(this);
208 Java_WebContentsImpl_clearNativePtr(AttachCurrentThread(), obj_.obj());
211 base::android::ScopedJavaLocalRef<jobject>
212 WebContentsAndroid::GetJavaObject() {
213 return base::android::ScopedJavaLocalRef<jobject>(obj_);
216 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetTitle(
217 JNIEnv* env, jobject obj) const {
218 return base::android::ConvertUTF16ToJavaString(env,
219 web_contents_->GetTitle());
222 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetVisibleURL(
223 JNIEnv* env, jobject obj) const {
224 return base::android::ConvertUTF8ToJavaString(
225 env, web_contents_->GetVisibleURL().spec());
228 bool WebContentsAndroid::IsLoading(JNIEnv* env, jobject obj) const {
229 return web_contents_->IsLoading();
232 bool WebContentsAndroid::IsLoadingToDifferentDocument(JNIEnv* env,
233 jobject obj) const {
234 return web_contents_->IsLoadingToDifferentDocument();
237 void WebContentsAndroid::Stop(JNIEnv* env, jobject obj) {
238 web_contents_->Stop();
241 void WebContentsAndroid::InsertCSS(
242 JNIEnv* env, jobject jobj, jstring jcss) {
243 web_contents_->InsertCSS(base::android::ConvertJavaStringToUTF8(env, jcss));
246 RenderWidgetHostViewAndroid*
247 WebContentsAndroid::GetRenderWidgetHostViewAndroid() {
248 RenderWidgetHostView* rwhv = NULL;
249 rwhv = web_contents_->GetRenderWidgetHostView();
250 if (web_contents_->ShowingInterstitialPage()) {
251 rwhv = web_contents_->GetInterstitialPage()
252 ->GetMainFrame()
253 ->GetRenderViewHost()
254 ->GetView();
256 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
259 jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env, jobject obj) {
260 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
261 if (!rwhva)
262 return SK_ColorWHITE;
263 return rwhva->GetCachedBackgroundColor();
266 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL(JNIEnv* env,
267 jobject obj) const {
268 return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec());
271 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetLastCommittedURL(
272 JNIEnv* env,
273 jobject) const {
274 return ConvertUTF8ToJavaString(env,
275 web_contents_->GetLastCommittedURL().spec());
279 jboolean WebContentsAndroid::IsIncognito(JNIEnv* env, jobject obj) {
280 return web_contents_->GetBrowserContext()->IsOffTheRecord();
283 void WebContentsAndroid::ResumeLoadingCreatedWebContents(JNIEnv* env,
284 jobject obj) {
285 web_contents_->ResumeLoadingCreatedWebContents();
288 void WebContentsAndroid::OnHide(JNIEnv* env, jobject obj) {
289 web_contents_->WasHidden();
292 void WebContentsAndroid::OnShow(JNIEnv* env, jobject obj) {
293 web_contents_->WasShown();
296 void WebContentsAndroid::ReleaseMediaPlayers(JNIEnv* env, jobject jobj) {
297 #if defined(ENABLE_BROWSER_CDMS)
298 web_contents_->ForEachFrame(
299 base::Bind(&ReleaseAllMediaPlayers, base::Unretained(web_contents_)));
300 #endif // defined(ENABLE_BROWSER_CDMS)
303 void WebContentsAndroid::ShowInterstitialPage(
304 JNIEnv* env,
305 jobject obj,
306 jstring jurl,
307 jlong delegate_ptr) {
308 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
309 InterstitialPageDelegateAndroid* delegate =
310 reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
311 InterstitialPage* interstitial = InterstitialPage::Create(
312 web_contents_, false, url, delegate);
313 delegate->set_interstitial_page(interstitial);
314 interstitial->Show();
317 jboolean WebContentsAndroid::IsShowingInterstitialPage(JNIEnv* env,
318 jobject obj) {
319 return web_contents_->ShowingInterstitialPage();
322 jboolean WebContentsAndroid::IsRenderWidgetHostViewReady(
323 JNIEnv* env,
324 jobject obj) {
325 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
326 return view && view->HasValidFrame();
329 void WebContentsAndroid::ExitFullscreen(JNIEnv* env, jobject obj) {
330 web_contents_->ExitFullscreen();
333 void WebContentsAndroid::UpdateTopControlsState(
334 JNIEnv* env,
335 jobject obj,
336 bool enable_hiding,
337 bool enable_showing,
338 bool animate) {
339 RenderViewHost* host = web_contents_->GetRenderViewHost();
340 if (!host)
341 return;
342 host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
343 enable_hiding,
344 enable_showing,
345 animate));
348 void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
349 RenderViewHost* host = web_contents_->GetRenderViewHost();
350 if (!host)
351 return;
352 host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
355 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
356 JNIEnv* env,
357 jobject obj) {
358 RenderViewHost* host = web_contents_->GetRenderViewHost();
359 if (!host)
360 return;
361 host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
362 host->GetRoutingID(), gfx::Rect()));
365 void WebContentsAndroid::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
366 RenderViewHost* host = web_contents_->GetRenderViewHost();
367 if (!host)
368 return;
369 host->SelectWordAroundCaret();
372 void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
373 jobject obj,
374 jstring script,
375 jobject callback) {
376 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
377 DCHECK(rvh);
379 if (!rvh->IsRenderViewLive()) {
380 if (!static_cast<WebContentsImpl*>(web_contents_)->
381 CreateRenderViewForInitialEmptyDocument()) {
382 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
383 return;
387 if (!callback) {
388 // No callback requested.
389 web_contents_->GetMainFrame()->ExecuteJavaScript(
390 ConvertJavaStringToUTF16(env, script));
391 return;
394 // Secure the Java callback in a scoped object and give ownership of it to the
395 // base::Callback.
396 ScopedJavaGlobalRef<jobject> j_callback;
397 j_callback.Reset(env, callback);
398 RenderFrameHost::JavaScriptResultCallback js_callback =
399 base::Bind(&JavaScriptResultCallback, j_callback);
401 web_contents_->GetMainFrame()->ExecuteJavaScript(
402 ConvertJavaStringToUTF16(env, script), js_callback);
405 void WebContentsAndroid::AddMessageToDevToolsConsole(JNIEnv* env,
406 jobject jobj,
407 jint level,
408 jstring message) {
409 DCHECK_GE(level, 0);
410 DCHECK_LE(level, CONSOLE_MESSAGE_LEVEL_LAST);
412 web_contents_->GetMainFrame()->AddMessageToConsole(
413 static_cast<ConsoleMessageLevel>(level),
414 ConvertJavaStringToUTF8(env, message));
417 jboolean WebContentsAndroid::HasAccessedInitialDocument(
418 JNIEnv* env,
419 jobject jobj) {
420 return static_cast<WebContentsImpl*>(web_contents_)->
421 HasAccessedInitialDocument();
424 jint WebContentsAndroid::GetThemeColor(JNIEnv* env, jobject obj) {
425 return web_contents_->GetThemeColor();
428 void WebContentsAndroid::RequestAccessibilitySnapshot(JNIEnv* env,
429 jobject obj,
430 jobject callback) {
431 // Secure the Java callback in a scoped object and give ownership of it to the
432 // base::Callback.
433 ScopedJavaGlobalRef<jobject> j_callback;
434 j_callback.Reset(env, callback);
435 WebContentsImpl::AXTreeSnapshotCallback snapshot_callback =
436 base::Bind(&AXTreeSnapshotCallback, j_callback);
438 static_cast<WebContentsImpl*>(web_contents_)->RequestAXTreeSnapshot(
439 snapshot_callback);
442 } // namespace content