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_string.h"
9 #include "base/command_line.h"
10 #include "base/json/json_writer.h"
11 #include "base/logging.h"
12 #include "content/browser/android/interstitial_page_delegate_android.h"
13 #include "content/browser/frame_host/interstitial_page_impl.h"
14 #include "content/browser/media/media_web_contents_observer.h"
15 #include "content/browser/renderer_host/render_view_host_impl.h"
16 #include "content/browser/web_contents/web_contents_impl.h"
17 #include "content/common/frame_messages.h"
18 #include "content/common/input_messages.h"
19 #include "content/common/view_messages.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/common/content_switches.h"
24 #include "jni/WebContentsImpl_jni.h"
26 using base::android::AttachCurrentThread
;
27 using base::android::ConvertJavaStringToUTF8
;
28 using base::android::ConvertJavaStringToUTF16
;
29 using base::android::ConvertUTF8ToJavaString
;
30 using base::android::ScopedJavaGlobalRef
;
34 void JavaScriptResultCallback(const ScopedJavaGlobalRef
<jobject
>& callback
,
35 const base::Value
* result
) {
36 JNIEnv
* env
= base::android::AttachCurrentThread();
38 base::JSONWriter::Write(result
, &json
);
39 ScopedJavaLocalRef
<jstring
> j_json
= ConvertUTF8ToJavaString(env
, json
);
40 content::Java_WebContentsImpl_onEvaluateJavaScriptResult(
41 env
, j_json
.obj(), callback
.obj());
49 WebContents
* WebContents::FromJavaWebContents(
50 jobject jweb_contents_android
) {
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
52 if (!jweb_contents_android
)
55 WebContentsAndroid
* web_contents_android
=
56 reinterpret_cast<WebContentsAndroid
*>(
57 Java_WebContentsImpl_getNativePointer(AttachCurrentThread(),
58 jweb_contents_android
));
59 if (!web_contents_android
)
61 return web_contents_android
->web_contents();
65 bool WebContentsAndroid::Register(JNIEnv
* env
) {
66 return RegisterNativesImpl(env
);
69 WebContentsAndroid::WebContentsAndroid(WebContents
* web_contents
)
70 : web_contents_(web_contents
),
71 navigation_controller_(&(web_contents
->GetController())) {
72 JNIEnv
* env
= AttachCurrentThread();
74 Java_WebContentsImpl_create(
76 reinterpret_cast<intptr_t>(this),
77 navigation_controller_
.GetJavaObject().obj()).obj());
80 WebContentsAndroid::~WebContentsAndroid() {
81 Java_WebContentsImpl_destroy(AttachCurrentThread(), obj_
.obj());
84 base::android::ScopedJavaLocalRef
<jobject
>
85 WebContentsAndroid::GetJavaObject() {
86 return base::android::ScopedJavaLocalRef
<jobject
>(obj_
);
89 ScopedJavaLocalRef
<jstring
> WebContentsAndroid::GetTitle(
90 JNIEnv
* env
, jobject obj
) const {
91 return base::android::ConvertUTF16ToJavaString(env
,
92 web_contents_
->GetTitle());
95 ScopedJavaLocalRef
<jstring
> WebContentsAndroid::GetVisibleURL(
96 JNIEnv
* env
, jobject obj
) const {
97 return base::android::ConvertUTF8ToJavaString(
98 env
, web_contents_
->GetVisibleURL().spec());
101 void WebContentsAndroid::Stop(JNIEnv
* env
, jobject obj
) {
102 web_contents_
->Stop();
105 void WebContentsAndroid::InsertCSS(
106 JNIEnv
* env
, jobject jobj
, jstring jcss
) {
107 web_contents_
->InsertCSS(base::android::ConvertJavaStringToUTF8(env
, jcss
));
110 RenderWidgetHostViewAndroid
*
111 WebContentsAndroid::GetRenderWidgetHostViewAndroid() {
112 RenderWidgetHostView
* rwhv
= NULL
;
113 rwhv
= web_contents_
->GetRenderWidgetHostView();
114 if (web_contents_
->ShowingInterstitialPage()) {
115 rwhv
= static_cast<InterstitialPageImpl
*>(
116 web_contents_
->GetInterstitialPage())->
117 GetRenderViewHost()->GetView();
119 return static_cast<RenderWidgetHostViewAndroid
*>(rwhv
);
122 jint
WebContentsAndroid::GetBackgroundColor(JNIEnv
* env
, jobject obj
) {
123 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
125 return SK_ColorWHITE
;
126 return rwhva
->GetCachedBackgroundColor();
129 ScopedJavaLocalRef
<jstring
> WebContentsAndroid::GetURL(JNIEnv
* env
,
131 return ConvertUTF8ToJavaString(env
, web_contents_
->GetURL().spec());
134 jboolean
WebContentsAndroid::IsIncognito(JNIEnv
* env
, jobject obj
) {
135 return web_contents_
->GetBrowserContext()->IsOffTheRecord();
138 void WebContentsAndroid::ResumeResponseDeferredAtStart(JNIEnv
* env
,
140 static_cast<WebContentsImpl
*>(web_contents_
)->ResumeResponseDeferredAtStart();
143 void WebContentsAndroid::SetHasPendingNavigationTransitionForTesting(
146 CommandLine::ForCurrentProcess()->AppendSwitch(
147 switches::kEnableExperimentalWebPlatformFeatures
);
148 RenderFrameHost
* frame
=
149 static_cast<WebContentsImpl
*>(web_contents_
)->GetMainFrame();
150 BrowserThread::PostTask(
153 base::Bind(&TransitionRequestManager::AddPendingTransitionRequestData
,
154 base::Unretained(TransitionRequestManager::GetInstance()),
155 frame
->GetProcess()->GetID(),
156 frame
->GetRoutingID(),
162 void WebContentsAndroid::SetupTransitionView(JNIEnv
* env
,
165 web_contents_
->GetMainFrame()->Send(new FrameMsg_SetupTransitionView(
166 web_contents_
->GetMainFrame()->GetRoutingID(),
167 ConvertJavaStringToUTF8(env
, markup
)));
170 void WebContentsAndroid::BeginExitTransition(JNIEnv
* env
,
172 jstring css_selector
) {
173 web_contents_
->GetMainFrame()->Send(new FrameMsg_BeginExitTransition(
174 web_contents_
->GetMainFrame()->GetRoutingID(),
175 ConvertJavaStringToUTF8(env
, css_selector
)));
178 void WebContentsAndroid::OnHide(JNIEnv
* env
, jobject obj
) {
179 web_contents_
->WasHidden();
183 void WebContentsAndroid::OnShow(JNIEnv
* env
, jobject obj
) {
184 web_contents_
->WasShown();
187 void WebContentsAndroid::PauseVideo() {
188 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
189 web_contents_
->GetRenderViewHost());
191 rvhi
->media_web_contents_observer()->PauseVideo();
194 void WebContentsAndroid::AddStyleSheetByURL(
198 web_contents_
->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
199 web_contents_
->GetMainFrame()->GetRoutingID(),
200 ConvertJavaStringToUTF8(env
, url
)));
203 void WebContentsAndroid::ShowInterstitialPage(
207 jlong delegate_ptr
) {
208 GURL
url(base::android::ConvertJavaStringToUTF8(env
, jurl
));
209 InterstitialPageDelegateAndroid
* delegate
=
210 reinterpret_cast<InterstitialPageDelegateAndroid
*>(delegate_ptr
);
211 InterstitialPage
* interstitial
= InterstitialPage::Create(
212 web_contents_
, false, url
, delegate
);
213 delegate
->set_interstitial_page(interstitial
);
214 interstitial
->Show();
217 jboolean
WebContentsAndroid::IsShowingInterstitialPage(JNIEnv
* env
,
219 return web_contents_
->ShowingInterstitialPage();
222 jboolean
WebContentsAndroid::IsRenderWidgetHostViewReady(
225 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
226 return view
&& view
->HasValidFrame();
229 void WebContentsAndroid::ExitFullscreen(JNIEnv
* env
, jobject obj
) {
230 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
233 host
->ExitFullscreen();
236 void WebContentsAndroid::UpdateTopControlsState(
242 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
245 host
->Send(new ViewMsg_UpdateTopControlsState(host
->GetRoutingID(),
251 void WebContentsAndroid::ShowImeIfNeeded(JNIEnv
* env
, jobject obj
) {
252 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
255 host
->Send(new ViewMsg_ShowImeIfNeeded(host
->GetRoutingID()));
258 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
261 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
264 host
->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
265 host
->GetRoutingID(), gfx::Rect()));
268 void WebContentsAndroid::SelectWordAroundCaret(JNIEnv
* env
, jobject obj
) {
269 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
272 host
->SelectWordAroundCaret();
275 bool WebContentsAndroid::WillHandleDeferAfterResponseStarted() {
276 JNIEnv
* env
= AttachCurrentThread();
277 return Java_WebContentsImpl_willHandleDeferAfterResponseStarted(env
,
281 void WebContentsAndroid::DidDeferAfterResponseStarted(
282 const TransitionLayerData
& transition_data
) {
283 JNIEnv
* env
= AttachCurrentThread();
284 std::vector
<GURL
> entering_stylesheets
;
285 std::string transition_color
;
286 if (transition_data
.response_headers
) {
287 TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
288 transition_data
.response_headers
,
289 entering_stylesheets
,
290 transition_data
.request_url
);
292 transition_data
.response_headers
->EnumerateHeader(
293 NULL
, "X-Transition-Entering-Color", &transition_color
);
296 ScopedJavaLocalRef
<jstring
> jstring_markup(
297 ConvertUTF8ToJavaString(env
, transition_data
.markup
));
299 ScopedJavaLocalRef
<jstring
> jstring_css_selector(
300 ConvertUTF8ToJavaString(env
, transition_data
.css_selector
));
302 ScopedJavaLocalRef
<jstring
> jstring_transition_color(
303 ConvertUTF8ToJavaString(env
, transition_color
));
305 Java_WebContentsImpl_didDeferAfterResponseStarted(
308 jstring_markup
.obj(),
309 jstring_css_selector
.obj(),
310 jstring_transition_color
.obj());
312 std::vector
<GURL
>::const_iterator iter
= entering_stylesheets
.begin();
313 for (; iter
!= entering_stylesheets
.end(); ++iter
) {
314 ScopedJavaLocalRef
<jstring
> jstring_url(
315 ConvertUTF8ToJavaString(env
, iter
->spec()));
316 Java_WebContentsImpl_addEnteringStylesheetToTransition(
317 env
, obj_
.obj(), jstring_url
.obj());
321 void WebContentsAndroid::DidStartNavigationTransitionForFrame(int64 frame_id
) {
322 JNIEnv
* env
= AttachCurrentThread();
323 Java_WebContentsImpl_didStartNavigationTransitionForFrame(
324 env
, obj_
.obj(), frame_id
);
327 void WebContentsAndroid::EvaluateJavaScript(JNIEnv
* env
,
331 jboolean start_renderer
) {
332 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
335 if (start_renderer
&& !rvh
->IsRenderViewLive()) {
336 if (!static_cast<WebContentsImpl
*>(web_contents_
)->
337 CreateRenderViewForInitialEmptyDocument()) {
338 LOG(ERROR
) << "Failed to create RenderView in EvaluateJavaScript";
344 // No callback requested.
345 web_contents_
->GetMainFrame()->ExecuteJavaScript(
346 ConvertJavaStringToUTF16(env
, script
));
350 // Secure the Java callback in a scoped object and give ownership of it to the
352 ScopedJavaGlobalRef
<jobject
> j_callback
;
353 j_callback
.Reset(env
, callback
);
354 content::RenderFrameHost::JavaScriptResultCallback js_callback
=
355 base::Bind(&JavaScriptResultCallback
, j_callback
);
357 web_contents_
->GetMainFrame()->ExecuteJavaScript(
358 ConvertJavaStringToUTF16(env
, script
), js_callback
);
361 } // namespace content