Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_android.cc
blob760003589094a5774a563be77a0abd638598d546
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/json/json_writer.h"
12 #include "base/logging.h"
13 #include "content/browser/accessibility/browser_accessibility_android.h"
14 #include "content/browser/accessibility/browser_accessibility_manager.h"
15 #include "content/browser/android/interstitial_page_delegate_android.h"
16 #include "content/browser/frame_host/interstitial_page_impl.h"
17 #include "content/browser/media/android/browser_media_player_manager.h"
18 #include "content/browser/media/media_web_contents_observer.h"
19 #include "content/browser/renderer_host/render_view_host_impl.h"
20 #include "content/browser/web_contents/web_contents_impl.h"
21 #include "content/common/devtools_messages.h"
22 #include "content/common/frame_messages.h"
23 #include "content/common/input_messages.h"
24 #include "content/common/view_messages.h"
25 #include "content/public/browser/browser_context.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/content_switches.h"
29 #include "jni/WebContentsImpl_jni.h"
30 #include "net/android/network_library.h"
31 #include "ui/accessibility/ax_node_data.h"
33 using base::android::AttachCurrentThread;
34 using base::android::ConvertJavaStringToUTF8;
35 using base::android::ConvertJavaStringToUTF16;
36 using base::android::ConvertUTF8ToJavaString;
37 using base::android::ConvertUTF16ToJavaString;
38 using base::android::ScopedJavaGlobalRef;
39 using base::android::ToJavaIntArray;
41 namespace content {
43 namespace {
45 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
46 const base::Value* result) {
47 JNIEnv* env = base::android::AttachCurrentThread();
48 std::string json;
49 base::JSONWriter::Write(result, &json);
50 ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
51 Java_WebContentsImpl_onEvaluateJavaScriptResult(
52 env, j_json.obj(), callback.obj());
55 ScopedJavaLocalRef<jobject> WalkAXTreeDepthFirst(JNIEnv* env,
56 BrowserAccessibilityAndroid* node) {
58 ScopedJavaLocalRef<jstring> j_text =
59 ConvertUTF16ToJavaString(env, node->GetText());
60 ScopedJavaLocalRef<jstring> j_class =
61 ConvertUTF8ToJavaString(env, node->GetClassName());
62 const gfx::Rect& location = node->GetLocation();
63 ScopedJavaLocalRef<jobject> j_node =
64 Java_WebContentsImpl_createAccessibilitySnapshotNode(env,
65 location.x(), location.y(), node->GetScrollX(),
66 node->GetScrollY(), location.width(), location.height(),
67 j_text.obj(), j_class.obj());
69 for(uint32 i = 0; i < node->PlatformChildCount(); i++) {
70 BrowserAccessibilityAndroid* child =
71 static_cast<BrowserAccessibilityAndroid*>(
72 node->PlatformGetChild(i));
73 Java_WebContentsImpl_addAccessibilityNodeAsChild(env,
74 j_node.obj(), WalkAXTreeDepthFirst(env, child).obj());
76 return j_node;
79 // Walks over the AXTreeUpdate and creates a light weight snapshot.
80 void AXTreeSnapshotCallback(const ScopedJavaGlobalRef<jobject>& callback,
81 const ui::AXTreeUpdate& result) {
82 JNIEnv* env = base::android::AttachCurrentThread();
83 if (result.nodes.empty()) {
84 Java_WebContentsImpl_onAccessibilitySnapshot(env, nullptr, callback.obj());
85 return;
87 scoped_ptr<BrowserAccessibilityManager> manager(
88 BrowserAccessibilityManager::Create(result, nullptr));
89 BrowserAccessibilityAndroid* root =
90 static_cast<BrowserAccessibilityAndroid*>(manager->GetRoot());
91 ScopedJavaLocalRef<jobject> j_root = WalkAXTreeDepthFirst(env, root);
92 Java_WebContentsImpl_onAccessibilitySnapshot(
93 env, j_root.obj(), callback.obj());
96 void ReleaseAllMediaPlayers(WebContents* web_contents,
97 RenderFrameHost* render_frame_host) {
98 BrowserMediaPlayerManager* manager =
99 static_cast<WebContentsImpl*>(web_contents)->
100 media_web_contents_observer()->GetMediaPlayerManager(
101 render_frame_host);
102 if (manager)
103 manager->ReleaseAllMediaPlayers();
106 } // namespace
108 // static
109 WebContents* WebContents::FromJavaWebContents(
110 jobject jweb_contents_android) {
111 DCHECK_CURRENTLY_ON(BrowserThread::UI);
112 if (!jweb_contents_android)
113 return NULL;
115 WebContentsAndroid* web_contents_android =
116 reinterpret_cast<WebContentsAndroid*>(
117 Java_WebContentsImpl_getNativePointer(AttachCurrentThread(),
118 jweb_contents_android));
119 if (!web_contents_android)
120 return NULL;
121 return web_contents_android->web_contents();
124 // static
125 static void DestroyWebContents(JNIEnv* env,
126 jclass clazz,
127 jlong jweb_contents_android_ptr) {
128 WebContentsAndroid* web_contents_android =
129 reinterpret_cast<WebContentsAndroid*>(jweb_contents_android_ptr);
130 if (!web_contents_android)
131 return;
133 WebContents* web_contents = web_contents_android->web_contents();
134 if (!web_contents)
135 return;
137 delete web_contents;
140 // static
141 bool WebContentsAndroid::Register(JNIEnv* env) {
142 return RegisterNativesImpl(env);
145 WebContentsAndroid::WebContentsAndroid(WebContents* web_contents)
146 : web_contents_(web_contents),
147 navigation_controller_(&(web_contents->GetController())),
148 weak_factory_(this) {
149 JNIEnv* env = AttachCurrentThread();
150 obj_.Reset(env,
151 Java_WebContentsImpl_create(
152 env,
153 reinterpret_cast<intptr_t>(this),
154 navigation_controller_.GetJavaObject().obj()).obj());
155 RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
156 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
157 prefs->network_contry_iso =
158 command_line->HasSwitch(switches::kNetworkCountryIso) ?
159 command_line->GetSwitchValueASCII(switches::kNetworkCountryIso)
160 : net::android::GetTelephonyNetworkCountryIso();
163 WebContentsAndroid::~WebContentsAndroid() {
164 Java_WebContentsImpl_clearNativePtr(AttachCurrentThread(), obj_.obj());
167 base::android::ScopedJavaLocalRef<jobject>
168 WebContentsAndroid::GetJavaObject() {
169 return base::android::ScopedJavaLocalRef<jobject>(obj_);
172 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetTitle(
173 JNIEnv* env, jobject obj) const {
174 return base::android::ConvertUTF16ToJavaString(env,
175 web_contents_->GetTitle());
178 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetVisibleURL(
179 JNIEnv* env, jobject obj) const {
180 return base::android::ConvertUTF8ToJavaString(
181 env, web_contents_->GetVisibleURL().spec());
184 bool WebContentsAndroid::IsLoading(JNIEnv* env, jobject obj) const {
185 return web_contents_->IsLoading();
188 bool WebContentsAndroid::IsLoadingToDifferentDocument(JNIEnv* env,
189 jobject obj) const {
190 return web_contents_->IsLoadingToDifferentDocument();
193 void WebContentsAndroid::Stop(JNIEnv* env, jobject obj) {
194 web_contents_->Stop();
197 void WebContentsAndroid::InsertCSS(
198 JNIEnv* env, jobject jobj, jstring jcss) {
199 web_contents_->InsertCSS(base::android::ConvertJavaStringToUTF8(env, jcss));
202 RenderWidgetHostViewAndroid*
203 WebContentsAndroid::GetRenderWidgetHostViewAndroid() {
204 RenderWidgetHostView* rwhv = NULL;
205 rwhv = web_contents_->GetRenderWidgetHostView();
206 if (web_contents_->ShowingInterstitialPage()) {
207 rwhv = web_contents_->GetInterstitialPage()
208 ->GetMainFrame()
209 ->GetRenderViewHost()
210 ->GetView();
212 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
215 jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env, jobject obj) {
216 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
217 if (!rwhva)
218 return SK_ColorWHITE;
219 return rwhva->GetCachedBackgroundColor();
222 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL(JNIEnv* env,
223 jobject obj) const {
224 return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec());
227 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetLastCommittedURL(
228 JNIEnv* env,
229 jobject) const {
230 return ConvertUTF8ToJavaString(env,
231 web_contents_->GetLastCommittedURL().spec());
235 jboolean WebContentsAndroid::IsIncognito(JNIEnv* env, jobject obj) {
236 return web_contents_->GetBrowserContext()->IsOffTheRecord();
239 void WebContentsAndroid::ResumeResponseDeferredAtStart(JNIEnv* env,
240 jobject obj) {
241 static_cast<WebContentsImpl*>(web_contents_)->ResumeResponseDeferredAtStart();
244 void WebContentsAndroid::ResumeLoadingCreatedWebContents(JNIEnv* env,
245 jobject obj) {
246 web_contents_->ResumeLoadingCreatedWebContents();
249 void WebContentsAndroid::SetHasPendingNavigationTransitionForTesting(
250 JNIEnv* env,
251 jobject obj) {
252 base::CommandLine::ForCurrentProcess()->AppendSwitch(
253 switches::kEnableExperimentalWebPlatformFeatures);
254 RenderFrameHost* frame =
255 static_cast<WebContentsImpl*>(web_contents_)->GetMainFrame();
256 BrowserThread::PostTask(
257 BrowserThread::IO,
258 FROM_HERE,
259 base::Bind(
260 &TransitionRequestManager::AddPendingTransitionRequestDataForTesting,
261 base::Unretained(TransitionRequestManager::GetInstance()),
262 frame->GetProcess()->GetID(),
263 frame->GetRoutingID()));
266 void WebContentsAndroid::SetupTransitionView(JNIEnv* env,
267 jobject jobj,
268 jstring markup) {
269 web_contents_->GetMainFrame()->Send(new FrameMsg_SetupTransitionView(
270 web_contents_->GetMainFrame()->GetRoutingID(),
271 ConvertJavaStringToUTF8(env, markup)));
274 void WebContentsAndroid::BeginExitTransition(JNIEnv* env,
275 jobject jobj,
276 jstring css_selector,
277 jboolean exit_to_native_app) {
278 web_contents_->GetMainFrame()->Send(new FrameMsg_BeginExitTransition(
279 web_contents_->GetMainFrame()->GetRoutingID(),
280 ConvertJavaStringToUTF8(env, css_selector),
281 exit_to_native_app));
284 void WebContentsAndroid::RevertExitTransition(JNIEnv* env,
285 jobject jobj) {
286 web_contents_->GetMainFrame()->Send(new FrameMsg_RevertExitTransition(
287 web_contents_->GetMainFrame()->GetRoutingID()));
290 void WebContentsAndroid::HideTransitionElements(JNIEnv* env,
291 jobject jobj,
292 jstring css_selector) {
293 web_contents_->GetMainFrame()->Send(
294 new FrameMsg_HideTransitionElements(
295 web_contents_->GetMainFrame()->GetRoutingID(),
296 ConvertJavaStringToUTF8(env, css_selector)));
299 void WebContentsAndroid::ShowTransitionElements(JNIEnv* env,
300 jobject jobj,
301 jstring css_selector) {
302 web_contents_->GetMainFrame()->Send(
303 new FrameMsg_ShowTransitionElements(
304 web_contents_->GetMainFrame()->GetRoutingID(),
305 ConvertJavaStringToUTF8(env, css_selector)));
309 void WebContentsAndroid::ClearNavigationTransitionData(JNIEnv* env,
310 jobject jobj) {
311 static_cast<WebContentsImpl*>(web_contents_)->ClearNavigationTransitionData();
314 void WebContentsAndroid::FetchTransitionElements(JNIEnv* env,
315 jobject jobj,
316 jstring jurl) {
317 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
318 RenderFrameHost* frame = web_contents_->GetMainFrame();
320 scoped_ptr<TransitionLayerData> transition_data(new TransitionLayerData());
321 BrowserThread::PostTaskAndReplyWithResult(
322 BrowserThread::IO,
323 FROM_HERE,
324 base::Bind(&TransitionRequestManager::GetPendingTransitionRequest,
325 base::Unretained(TransitionRequestManager::GetInstance()),
326 frame->GetProcess()->GetID(),
327 frame->GetRoutingID(),
328 url,
329 transition_data.get()),
330 base::Bind(&WebContentsAndroid::OnTransitionElementsFetched,
331 weak_factory_.GetWeakPtr(),
332 base::Passed(&transition_data)));
335 void WebContentsAndroid::OnTransitionElementsFetched(
336 scoped_ptr<const TransitionLayerData> transition_data,
337 bool has_transition_data) {
338 // FetchTransitionElements is called after the navigation transition state
339 // machine starts, which means there must be transition data.
340 DCHECK(has_transition_data);
341 JNIEnv* env = AttachCurrentThread();
343 std::vector<TransitionElement>::const_iterator it =
344 transition_data->elements.begin();
345 for (; it != transition_data->elements.end(); ++it) {
346 ScopedJavaLocalRef<jstring> jstring_name(ConvertUTF8ToJavaString(env,
347 it->id));
348 Java_WebContentsImpl_addNavigationTransitionElements(
349 env, obj_.obj(), jstring_name.obj(),
350 it->rect.x(), it->rect.y(), it->rect.width(), it->rect.height());
353 ScopedJavaLocalRef<jstring> jstring_css_selector(
354 ConvertUTF8ToJavaString(env, transition_data->css_selector));
355 Java_WebContentsImpl_onTransitionElementsFetched(
356 env, obj_.obj(), jstring_css_selector.obj());
359 void WebContentsAndroid::OnHide(JNIEnv* env, jobject obj) {
360 web_contents_->WasHidden();
363 void WebContentsAndroid::OnShow(JNIEnv* env, jobject obj) {
364 web_contents_->WasShown();
367 void WebContentsAndroid::ReleaseMediaPlayers(JNIEnv* env, jobject jobj) {
368 #if defined(ENABLE_BROWSER_CDMS)
369 web_contents_->ForEachFrame(
370 base::Bind(&ReleaseAllMediaPlayers, base::Unretained(web_contents_)));
371 #endif // defined(ENABLE_BROWSER_CDMS)
374 void WebContentsAndroid::AddStyleSheetByURL(
375 JNIEnv* env,
376 jobject obj,
377 jstring url) {
378 web_contents_->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
379 web_contents_->GetMainFrame()->GetRoutingID(),
380 ConvertJavaStringToUTF8(env, url)));
383 void WebContentsAndroid::ShowInterstitialPage(
384 JNIEnv* env,
385 jobject obj,
386 jstring jurl,
387 jlong delegate_ptr) {
388 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
389 InterstitialPageDelegateAndroid* delegate =
390 reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
391 InterstitialPage* interstitial = InterstitialPage::Create(
392 web_contents_, false, url, delegate);
393 delegate->set_interstitial_page(interstitial);
394 interstitial->Show();
397 jboolean WebContentsAndroid::IsShowingInterstitialPage(JNIEnv* env,
398 jobject obj) {
399 return web_contents_->ShowingInterstitialPage();
402 jboolean WebContentsAndroid::IsRenderWidgetHostViewReady(
403 JNIEnv* env,
404 jobject obj) {
405 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
406 return view && view->HasValidFrame();
409 void WebContentsAndroid::ExitFullscreen(JNIEnv* env, jobject obj) {
410 web_contents_->ExitFullscreen();
413 void WebContentsAndroid::UpdateTopControlsState(
414 JNIEnv* env,
415 jobject obj,
416 bool enable_hiding,
417 bool enable_showing,
418 bool animate) {
419 RenderViewHost* host = web_contents_->GetRenderViewHost();
420 if (!host)
421 return;
422 host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
423 enable_hiding,
424 enable_showing,
425 animate));
428 void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
429 RenderViewHost* host = web_contents_->GetRenderViewHost();
430 if (!host)
431 return;
432 host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
435 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
436 JNIEnv* env,
437 jobject obj) {
438 RenderViewHost* host = web_contents_->GetRenderViewHost();
439 if (!host)
440 return;
441 host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
442 host->GetRoutingID(), gfx::Rect()));
445 void WebContentsAndroid::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
446 RenderViewHost* host = web_contents_->GetRenderViewHost();
447 if (!host)
448 return;
449 host->SelectWordAroundCaret();
452 bool WebContentsAndroid::WillHandleDeferAfterResponseStarted() {
453 JNIEnv* env = AttachCurrentThread();
454 return Java_WebContentsImpl_willHandleDeferAfterResponseStarted(env,
455 obj_.obj());
458 void WebContentsAndroid::DidDeferAfterResponseStarted(
459 const TransitionLayerData& transition_data) {
460 JNIEnv* env = AttachCurrentThread();
461 std::vector<GURL> entering_stylesheets;
462 std::string transition_color;
463 if (transition_data.response_headers.get()) {
464 TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
465 transition_data.response_headers,
466 entering_stylesheets,
467 transition_data.request_url);
469 transition_data.response_headers->EnumerateHeader(
470 NULL, "X-Transition-Entering-Color", &transition_color);
473 ScopedJavaLocalRef<jstring> jstring_markup(
474 ConvertUTF8ToJavaString(env, transition_data.markup));
476 ScopedJavaLocalRef<jstring> jstring_css_selector(
477 ConvertUTF8ToJavaString(env, transition_data.css_selector));
479 ScopedJavaLocalRef<jstring> jstring_transition_color(
480 ConvertUTF8ToJavaString(env, transition_color));
482 Java_WebContentsImpl_didDeferAfterResponseStarted(
483 env,
484 obj_.obj(),
485 jstring_markup.obj(),
486 jstring_css_selector.obj(),
487 jstring_transition_color.obj());
489 std::vector<GURL>::const_iterator iter = entering_stylesheets.begin();
490 for (; iter != entering_stylesheets.end(); ++iter) {
491 ScopedJavaLocalRef<jstring> jstring_url(
492 ConvertUTF8ToJavaString(env, iter->spec()));
493 Java_WebContentsImpl_addEnteringStylesheetToTransition(
494 env, obj_.obj(), jstring_url.obj());
498 void WebContentsAndroid::DidStartNavigationTransitionForFrame(int64 frame_id) {
499 JNIEnv* env = AttachCurrentThread();
500 Java_WebContentsImpl_didStartNavigationTransitionForFrame(
501 env, obj_.obj(), frame_id);
504 void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
505 jobject obj,
506 jstring script,
507 jobject callback) {
508 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
509 DCHECK(rvh);
511 if (!rvh->IsRenderViewLive()) {
512 if (!static_cast<WebContentsImpl*>(web_contents_)->
513 CreateRenderViewForInitialEmptyDocument()) {
514 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
515 return;
519 if (!callback) {
520 // No callback requested.
521 web_contents_->GetMainFrame()->ExecuteJavaScript(
522 ConvertJavaStringToUTF16(env, script));
523 return;
526 // Secure the Java callback in a scoped object and give ownership of it to the
527 // base::Callback.
528 ScopedJavaGlobalRef<jobject> j_callback;
529 j_callback.Reset(env, callback);
530 RenderFrameHost::JavaScriptResultCallback js_callback =
531 base::Bind(&JavaScriptResultCallback, j_callback);
533 web_contents_->GetMainFrame()->ExecuteJavaScript(
534 ConvertJavaStringToUTF16(env, script), js_callback);
537 void WebContentsAndroid::AddMessageToDevToolsConsole(JNIEnv* env,
538 jobject jobj,
539 jint level,
540 jstring message) {
541 DCHECK_GE(level, 0);
542 DCHECK_LE(level, CONSOLE_MESSAGE_LEVEL_LAST);
544 web_contents_->GetMainFrame()->Send(new DevToolsAgentMsg_AddMessageToConsole(
545 web_contents_->GetMainFrame()->GetRoutingID(),
546 static_cast<ConsoleMessageLevel>(level),
547 ConvertJavaStringToUTF8(env, message)));
550 jboolean WebContentsAndroid::HasAccessedInitialDocument(
551 JNIEnv* env,
552 jobject jobj) {
553 return static_cast<WebContentsImpl*>(web_contents_)->
554 HasAccessedInitialDocument();
557 jint WebContentsAndroid::GetThemeColor(JNIEnv* env, jobject obj) {
558 return web_contents_->GetThemeColor();
561 void WebContentsAndroid::RequestAccessibilitySnapshot(JNIEnv* env,
562 jobject obj,
563 jobject callback) {
564 // Secure the Java callback in a scoped object and give ownership of it to the
565 // base::Callback.
566 ScopedJavaGlobalRef<jobject> j_callback;
567 j_callback.Reset(env, callback);
568 WebContentsImpl::AXTreeSnapshotCallback snapshot_callback =
569 base::Bind(&AXTreeSnapshotCallback, j_callback);
571 static_cast<WebContentsImpl*>(web_contents_)->RequestAXTreeSnapshot(
572 snapshot_callback);
575 } // namespace content