• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/browser/web_contents/web_contents_android.h"
6 
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/android/browser_media_player_manager.h"
15 #include "content/browser/media/media_web_contents_observer.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/browser/web_contents/web_contents_impl.h"
18 #include "content/common/frame_messages.h"
19 #include "content/common/input_messages.h"
20 #include "content/common/view_messages.h"
21 #include "content/public/browser/browser_context.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/common/content_switches.h"
25 #include "jni/WebContentsImpl_jni.h"
26 
27 using base::android::AttachCurrentThread;
28 using base::android::ConvertJavaStringToUTF8;
29 using base::android::ConvertJavaStringToUTF16;
30 using base::android::ConvertUTF8ToJavaString;
31 using base::android::ScopedJavaGlobalRef;
32 
33 namespace {
34 
JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject> & callback,const base::Value * result)35 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
36                               const base::Value* result) {
37   JNIEnv* env = base::android::AttachCurrentThread();
38   std::string json;
39   base::JSONWriter::Write(result, &json);
40   ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
41   content::Java_WebContentsImpl_onEvaluateJavaScriptResult(
42       env, j_json.obj(), callback.obj());
43 }
44 
45 }  // namespace
46 
47 namespace content {
48 
49 // static
FromJavaWebContents(jobject jweb_contents_android)50 WebContents* WebContents::FromJavaWebContents(
51     jobject jweb_contents_android) {
52   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
53   if (!jweb_contents_android)
54     return NULL;
55 
56   WebContentsAndroid* web_contents_android =
57       reinterpret_cast<WebContentsAndroid*>(
58           Java_WebContentsImpl_getNativePointer(AttachCurrentThread(),
59                                                 jweb_contents_android));
60   if (!web_contents_android)
61     return NULL;
62   return web_contents_android->web_contents();
63 }
64 
65 // static
Register(JNIEnv * env)66 bool WebContentsAndroid::Register(JNIEnv* env) {
67   return RegisterNativesImpl(env);
68 }
69 
WebContentsAndroid(WebContents * web_contents)70 WebContentsAndroid::WebContentsAndroid(WebContents* web_contents)
71     : web_contents_(web_contents),
72       navigation_controller_(&(web_contents->GetController())) {
73   JNIEnv* env = AttachCurrentThread();
74   obj_.Reset(env,
75              Java_WebContentsImpl_create(
76                  env,
77                  reinterpret_cast<intptr_t>(this),
78                  navigation_controller_.GetJavaObject().obj()).obj());
79 }
80 
~WebContentsAndroid()81 WebContentsAndroid::~WebContentsAndroid() {
82   Java_WebContentsImpl_destroy(AttachCurrentThread(), obj_.obj());
83 }
84 
85 base::android::ScopedJavaLocalRef<jobject>
GetJavaObject()86 WebContentsAndroid::GetJavaObject() {
87   return base::android::ScopedJavaLocalRef<jobject>(obj_);
88 }
89 
GetTitle(JNIEnv * env,jobject obj) const90 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetTitle(
91     JNIEnv* env, jobject obj) const {
92   return base::android::ConvertUTF16ToJavaString(env,
93                                                  web_contents_->GetTitle());
94 }
95 
GetVisibleURL(JNIEnv * env,jobject obj) const96 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetVisibleURL(
97     JNIEnv* env, jobject obj) const {
98   return base::android::ConvertUTF8ToJavaString(
99       env, web_contents_->GetVisibleURL().spec());
100 }
101 
Stop(JNIEnv * env,jobject obj)102 void WebContentsAndroid::Stop(JNIEnv* env, jobject obj) {
103   web_contents_->Stop();
104 }
105 
InsertCSS(JNIEnv * env,jobject jobj,jstring jcss)106 void WebContentsAndroid::InsertCSS(
107     JNIEnv* env, jobject jobj, jstring jcss) {
108   web_contents_->InsertCSS(base::android::ConvertJavaStringToUTF8(env, jcss));
109 }
110 
111 RenderWidgetHostViewAndroid*
GetRenderWidgetHostViewAndroid()112     WebContentsAndroid::GetRenderWidgetHostViewAndroid() {
113   RenderWidgetHostView* rwhv = NULL;
114   rwhv = web_contents_->GetRenderWidgetHostView();
115   if (web_contents_->ShowingInterstitialPage()) {
116     rwhv = static_cast<InterstitialPageImpl*>(
117         web_contents_->GetInterstitialPage())->
118             GetRenderViewHost()->GetView();
119   }
120   return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
121 }
122 
GetBackgroundColor(JNIEnv * env,jobject obj)123 jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env, jobject obj) {
124   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
125   if (!rwhva)
126     return SK_ColorWHITE;
127   return rwhva->GetCachedBackgroundColor();
128 }
129 
GetURL(JNIEnv * env,jobject obj) const130 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL(JNIEnv* env,
131                                                        jobject obj) const {
132   return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec());
133 }
134 
IsIncognito(JNIEnv * env,jobject obj)135 jboolean WebContentsAndroid::IsIncognito(JNIEnv* env, jobject obj) {
136   return web_contents_->GetBrowserContext()->IsOffTheRecord();
137 }
138 
ResumeResponseDeferredAtStart(JNIEnv * env,jobject obj)139 void WebContentsAndroid::ResumeResponseDeferredAtStart(JNIEnv* env,
140                                                        jobject obj) {
141   static_cast<WebContentsImpl*>(web_contents_)->ResumeResponseDeferredAtStart();
142 }
143 
SetHasPendingNavigationTransitionForTesting(JNIEnv * env,jobject obj)144 void WebContentsAndroid::SetHasPendingNavigationTransitionForTesting(
145     JNIEnv* env,
146     jobject obj) {
147   CommandLine::ForCurrentProcess()->AppendSwitch(
148       switches::kEnableExperimentalWebPlatformFeatures);
149   RenderFrameHost* frame =
150       static_cast<WebContentsImpl*>(web_contents_)->GetMainFrame();
151   BrowserThread::PostTask(
152       BrowserThread::IO,
153       FROM_HERE,
154       base::Bind(&TransitionRequestManager::AddPendingTransitionRequestData,
155                  base::Unretained(TransitionRequestManager::GetInstance()),
156                  frame->GetProcess()->GetID(),
157                  frame->GetRoutingID(),
158                  "*",
159                  "",
160                  ""));
161 }
162 
SetupTransitionView(JNIEnv * env,jobject jobj,jstring markup)163 void WebContentsAndroid::SetupTransitionView(JNIEnv* env,
164                                              jobject jobj,
165                                              jstring markup) {
166   web_contents_->GetMainFrame()->Send(new FrameMsg_SetupTransitionView(
167       web_contents_->GetMainFrame()->GetRoutingID(),
168       ConvertJavaStringToUTF8(env, markup)));
169 }
170 
BeginExitTransition(JNIEnv * env,jobject jobj,jstring css_selector)171 void WebContentsAndroid::BeginExitTransition(JNIEnv* env,
172                                              jobject jobj,
173                                              jstring css_selector) {
174   web_contents_->GetMainFrame()->Send(new FrameMsg_BeginExitTransition(
175       web_contents_->GetMainFrame()->GetRoutingID(),
176       ConvertJavaStringToUTF8(env, css_selector)));
177 }
178 
OnHide(JNIEnv * env,jobject obj)179 void WebContentsAndroid::OnHide(JNIEnv* env, jobject obj) {
180   web_contents_->WasHidden();
181 }
182 
OnShow(JNIEnv * env,jobject obj)183 void WebContentsAndroid::OnShow(JNIEnv* env, jobject obj) {
184   web_contents_->WasShown();
185 }
186 
ReleaseMediaPlayers(JNIEnv * env,jobject jobj)187 void WebContentsAndroid::ReleaseMediaPlayers(JNIEnv* env, jobject jobj) {
188 #if defined(ENABLE_BROWSER_CDMS)
189   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
190       web_contents_->GetRenderViewHost());
191   if (!rvhi || !rvhi->GetMainFrame())
192     return;
193 
194   BrowserMediaPlayerManager* manager =
195       rvhi->media_web_contents_observer()->GetMediaPlayerManager(
196           rvhi->GetMainFrame());
197   if (manager)
198     manager->ReleaseAllMediaPlayers();
199 #endif // defined(ENABLE_BROWSER_CDMS)
200 }
201 
AddStyleSheetByURL(JNIEnv * env,jobject obj,jstring url)202 void WebContentsAndroid::AddStyleSheetByURL(
203     JNIEnv* env,
204     jobject obj,
205     jstring url) {
206   web_contents_->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
207       web_contents_->GetMainFrame()->GetRoutingID(),
208       ConvertJavaStringToUTF8(env, url)));
209 }
210 
ShowInterstitialPage(JNIEnv * env,jobject obj,jstring jurl,jlong delegate_ptr)211 void WebContentsAndroid::ShowInterstitialPage(
212     JNIEnv* env,
213     jobject obj,
214     jstring jurl,
215     jlong delegate_ptr) {
216   GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
217   InterstitialPageDelegateAndroid* delegate =
218       reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
219   InterstitialPage* interstitial = InterstitialPage::Create(
220       web_contents_, false, url, delegate);
221   delegate->set_interstitial_page(interstitial);
222   interstitial->Show();
223 }
224 
IsShowingInterstitialPage(JNIEnv * env,jobject obj)225 jboolean WebContentsAndroid::IsShowingInterstitialPage(JNIEnv* env,
226                                                         jobject obj) {
227   return web_contents_->ShowingInterstitialPage();
228 }
229 
IsRenderWidgetHostViewReady(JNIEnv * env,jobject obj)230 jboolean WebContentsAndroid::IsRenderWidgetHostViewReady(
231     JNIEnv* env,
232     jobject obj) {
233   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
234   return view && view->HasValidFrame();
235 }
236 
ExitFullscreen(JNIEnv * env,jobject obj)237 void WebContentsAndroid::ExitFullscreen(JNIEnv* env, jobject obj) {
238   RenderViewHost* host = web_contents_->GetRenderViewHost();
239   if (!host)
240     return;
241   host->ExitFullscreen();
242 }
243 
UpdateTopControlsState(JNIEnv * env,jobject obj,bool enable_hiding,bool enable_showing,bool animate)244 void WebContentsAndroid::UpdateTopControlsState(
245     JNIEnv* env,
246     jobject obj,
247     bool enable_hiding,
248     bool enable_showing,
249     bool animate) {
250   RenderViewHost* host = web_contents_->GetRenderViewHost();
251   if (!host)
252     return;
253   host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
254                                                 enable_hiding,
255                                                 enable_showing,
256                                                 animate));
257 }
258 
ShowImeIfNeeded(JNIEnv * env,jobject obj)259 void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
260   RenderViewHost* host = web_contents_->GetRenderViewHost();
261   if (!host)
262     return;
263   host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
264 }
265 
ScrollFocusedEditableNodeIntoView(JNIEnv * env,jobject obj)266 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
267     JNIEnv* env,
268     jobject obj) {
269   RenderViewHost* host = web_contents_->GetRenderViewHost();
270   if (!host)
271     return;
272   host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
273       host->GetRoutingID(), gfx::Rect()));
274 }
275 
SelectWordAroundCaret(JNIEnv * env,jobject obj)276 void WebContentsAndroid::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
277   RenderViewHost* host = web_contents_->GetRenderViewHost();
278   if (!host)
279     return;
280   host->SelectWordAroundCaret();
281 }
282 
WillHandleDeferAfterResponseStarted()283 bool WebContentsAndroid::WillHandleDeferAfterResponseStarted() {
284   JNIEnv* env = AttachCurrentThread();
285   return Java_WebContentsImpl_willHandleDeferAfterResponseStarted(env,
286                                                                   obj_.obj());
287 }
288 
DidDeferAfterResponseStarted(const TransitionLayerData & transition_data)289 void WebContentsAndroid::DidDeferAfterResponseStarted(
290     const TransitionLayerData& transition_data) {
291   JNIEnv* env = AttachCurrentThread();
292   std::vector<GURL> entering_stylesheets;
293   std::string transition_color;
294   if (transition_data.response_headers) {
295     TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
296         transition_data.response_headers,
297         entering_stylesheets,
298         transition_data.request_url);
299 
300     transition_data.response_headers->EnumerateHeader(
301         NULL, "X-Transition-Entering-Color", &transition_color);
302   }
303 
304   ScopedJavaLocalRef<jstring> jstring_markup(
305       ConvertUTF8ToJavaString(env, transition_data.markup));
306 
307   ScopedJavaLocalRef<jstring> jstring_css_selector(
308       ConvertUTF8ToJavaString(env, transition_data.css_selector));
309 
310   ScopedJavaLocalRef<jstring> jstring_transition_color(
311       ConvertUTF8ToJavaString(env, transition_color));
312 
313   Java_WebContentsImpl_didDeferAfterResponseStarted(
314       env,
315       obj_.obj(),
316       jstring_markup.obj(),
317       jstring_css_selector.obj(),
318       jstring_transition_color.obj());
319 
320   std::vector<GURL>::const_iterator iter = entering_stylesheets.begin();
321   for (; iter != entering_stylesheets.end(); ++iter) {
322     ScopedJavaLocalRef<jstring> jstring_url(
323         ConvertUTF8ToJavaString(env, iter->spec()));
324     Java_WebContentsImpl_addEnteringStylesheetToTransition(
325         env, obj_.obj(), jstring_url.obj());
326   }
327 }
328 
DidStartNavigationTransitionForFrame(int64 frame_id)329 void WebContentsAndroid::DidStartNavigationTransitionForFrame(int64 frame_id) {
330   JNIEnv* env = AttachCurrentThread();
331   Java_WebContentsImpl_didStartNavigationTransitionForFrame(
332       env, obj_.obj(), frame_id);
333 }
334 
EvaluateJavaScript(JNIEnv * env,jobject obj,jstring script,jobject callback)335 void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
336                                             jobject obj,
337                                             jstring script,
338                                             jobject callback) {
339   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
340   DCHECK(rvh);
341 
342   if (!rvh->IsRenderViewLive()) {
343     if (!static_cast<WebContentsImpl*>(web_contents_)->
344         CreateRenderViewForInitialEmptyDocument()) {
345       LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
346       return;
347     }
348   }
349 
350   if (!callback) {
351     // No callback requested.
352     web_contents_->GetMainFrame()->ExecuteJavaScript(
353         ConvertJavaStringToUTF16(env, script));
354     return;
355   }
356 
357   // Secure the Java callback in a scoped object and give ownership of it to the
358   // base::Callback.
359   ScopedJavaGlobalRef<jobject> j_callback;
360   j_callback.Reset(env, callback);
361   content::RenderFrameHost::JavaScriptResultCallback js_callback =
362       base::Bind(&JavaScriptResultCallback, j_callback);
363 
364   web_contents_->GetMainFrame()->ExecuteJavaScript(
365       ConvertJavaStringToUTF16(env, script), js_callback);
366 }
367 
368 }  // namespace content
369