Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: content/browser/android/content_view_client.cc

Issue 10536066: android content shell bringup. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more jam feedback Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/android/content_view_client.h"
6
7 #include <android/keycodes.h>
8
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "content/browser/android/content_util.h"
12 #include "content/browser/android/download_controller.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/common/find_match_rect_android.h"
15 #include "content/public/browser/android/content_view.h"
jam 2012/06/14 01:31:41 nit: content_view_impl
16 #include "content/public/browser/render_widget_host_view.h"
17 #include "content/public/browser/download_item.h"
18 #include "content/public/browser/invalidate_type.h"
19 #include "content/public/browser/page_navigator.h"
20 #include "content/public/browser/navigation_controller.h"
21 #include "content/public/browser/navigation_entry.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/common/page_transition_types.h"
24 #include "content/public/common/referrer.h"
25 #include "jni/content_view_client_jni.h"
26 #include "net/http/http_request_headers.h"
27 #include "ui/gfx/rect.h"
28 #include "webkit/glue/window_open_disposition.h"
29
30 using base::android::AttachCurrentThread;
31 using base::android::CheckException;
32 using base::android::ConvertUTF8ToJavaString;
33 using base::android::ConvertUTF16ToJavaString;
34 using base::android::GetClass;
35 using base::android::GetMethodID;
36 using base::android::HasClass;
37 using base::android::ScopedJavaLocalRef;
38 using content::DownloadItem;
39 using content::RenderViewHost;
40 using content::WebContents;
41
42 using namespace net;
jam 2012/06/14 01:31:41 this is against the style guide (just saw this). y
43
44 namespace content {
45
46 ContentViewClient::ContentViewClient(JNIEnv* env, jobject obj)
47 : weak_java_client_(env, obj),
48 find_helper_(NULL),
49 javascript_dialog_creator_(NULL) {
50 }
51
52 ContentViewClient::~ContentViewClient() {
53 }
54
55 // static
56 ContentViewClient* ContentViewClient::CreateNativeContentViewClient(
57 JNIEnv* env, jobject obj) {
58 DCHECK(obj);
59 return new ContentViewClient(env, obj);
60 }
61
62 void ContentViewClient::OnInternalPageLoadRequest(
63 content::WebContents* source, const GURL& url) {
jam 2012/06/14 01:31:41 nit: get rid of content:: in this file, and also u
64 last_requested_navigation_url_ = url;
65 }
66
67
68 void ContentViewClient::OnPageStarted(const GURL& url) {
69 JNIEnv* env = AttachCurrentThread();
70 ScopedJavaLocalRef<jstring> jstring_url =
71 ConvertUTF8ToJavaString(env, url.spec());
72 Java_ContentViewClient_onPageStarted(env, weak_java_client_.get(env).obj(),
73 jstring_url.obj());
74 }
75
76 void ContentViewClient::OnPageFinished(const GURL& url) {
77 if (url == last_requested_navigation_url_)
78 last_requested_navigation_url_ = GURL::EmptyGURL();
79
80 JNIEnv* env = AttachCurrentThread();
81 ScopedJavaLocalRef<jstring> jstring_url =
82 ConvertUTF8ToJavaString(env, url.spec());
83
84 Java_ContentViewClient_onPageFinished(env, weak_java_client_.get(env).obj(),
85 jstring_url.obj());
86 CheckException(env);
87 }
88
89 void ContentViewClient::OnReceivedError(int error_code,
90 const string16& description,
91 const GURL& url) {
92 JNIEnv* env = AttachCurrentThread();
93 ScopedJavaLocalRef<jstring> jstring_error_description =
94 ConvertUTF8ToJavaString(env, url.spec());
95 ScopedJavaLocalRef<jstring> jstring_url =
96 ConvertUTF8ToJavaString(env, url.spec());
97
98 Java_ContentViewClient_onReceivedError(
99 env, weak_java_client_.get(env).obj(),
100 ToContentViewClientError(error_code),
101 jstring_error_description.obj(), jstring_url.obj());
102 }
103
104 void ContentViewClient::OnReceivedHttpAuthRequest(
105 jobject auth_handler,
106 const string16& host,
107 const string16& realm) {
108 /* TODO(jrg): upstream this once ContentHttpAuthHandler.java is
109 upstreamed, and onReceivedHttpAuthRequest() is upstreamed in
110 ContentViewClient.java */
111 NOTREACHED();
112 }
113
114 void ContentViewClient::OnDidCommitMainFrame(const GURL& url,
115 const GURL& base_url) {
116 JNIEnv* env = AttachCurrentThread();
117 ScopedJavaLocalRef<jstring> jstring_url =
118 ConvertUTF8ToJavaString(env, url.spec());
119 ScopedJavaLocalRef<jstring> jstring_base_url =
120 ConvertUTF8ToJavaString(env, base_url.spec());
121
122 Java_ContentViewClient_onMainFrameCommitted(
123 env, weak_java_client_.get(env).obj(),
124 jstring_url.obj(), jstring_base_url.obj());
125 }
126
127 void ContentViewClient::OnInterstitialShown() {
128 JNIEnv* env = AttachCurrentThread();
129 Java_ContentViewClient_onInterstitialShown(
130 env, weak_java_client_.get(env).obj());
131 }
132
133 void ContentViewClient::OnInterstitialHidden() {
134 JNIEnv* env = AttachCurrentThread();
135 Java_ContentViewClient_onInterstitialHidden(
136 env, weak_java_client_.get(env).obj());
137 }
138
139 void ContentViewClient::SetFindHelper(FindHelper* find_helper) {
140 find_helper_ = find_helper;
141 }
142
143 void ContentViewClient::SetJavaScriptDialogCreator(
144 content::JavaScriptDialogCreator* javascript_dialog_creator) {
145 javascript_dialog_creator_ = javascript_dialog_creator;
146 }
147
148 bool ContentViewClient::OnJSModalDialog(content::JavaScriptMessageType type,
149 bool is_before_unload_dialog,
150 const GURL& url,
151 const string16& message,
152 const string16& default_value) {
153 JNIEnv* env = AttachCurrentThread();
154 ScopedJavaLocalRef<jstring> jurl(ConvertUTF8ToJavaString(env, url.spec()));
155 ScopedJavaLocalRef<jstring> jmessage(ConvertUTF16ToJavaString(env, message));
156
157 // Special case for beforeunload dialogs, as that isn't encoded in the
158 // |type| of the dialog.
159 if (is_before_unload_dialog) {
160 return Java_ContentViewClient_onJsBeforeUnload(env,
161 weak_java_client_.get(env).obj(),
162 jurl.obj(),
163 jmessage.obj());
164 }
165
166 switch (type) {
167 case content::JAVASCRIPT_MESSAGE_TYPE_ALERT:
168 return Java_ContentViewClient_onJsAlert(env,
169 weak_java_client_.get(env).obj(),
170 jurl.obj(),
171 jmessage.obj());
172
173 case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
174 return Java_ContentViewClient_onJsConfirm(env,
175 weak_java_client_.get(env).obj(),
176 jurl.obj(),
177 jmessage.obj());
178
179 case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT: {
180 ScopedJavaLocalRef<jstring> jdefault_value(
181 ConvertUTF16ToJavaString(env, default_value));
182 return Java_ContentViewClient_onJsPrompt(env,
183 weak_java_client_.get(env).obj(),
184 jurl.obj(),
185 jmessage.obj(),
186 jdefault_value.obj());
187 }
188
189 default:
190 NOTREACHED();
191 return false;
192 }
193 }
194
195 // ----------------------------------------------------------------------------
196 // WebContentsDelegate methods
197 // ----------------------------------------------------------------------------
198
199 // OpenURLFromTab() will be called when we're performing a browser-intiated
200 // navigation. The most common scenario for this is opening new tabs (see
201 // RenderViewImpl::decidePolicyForNavigation for more details).
202 WebContents* ContentViewClient::OpenURLFromTab(
203 WebContents* source,
204 const content::OpenURLParams& params) {
205 const GURL& url = params.url;
206 WindowOpenDisposition disposition = params.disposition;
207 content::PageTransition transition(
208 content::PageTransitionFromInt(params.transition));
209
210 if (!source || (disposition != CURRENT_TAB &&
211 disposition != NEW_FOREGROUND_TAB &&
212 disposition != NEW_BACKGROUND_TAB &&
213 disposition != OFF_THE_RECORD)) {
214 NOTIMPLEMENTED();
215 return NULL;
216 }
217
218 if (disposition == NEW_FOREGROUND_TAB ||
219 disposition == NEW_BACKGROUND_TAB ||
220 disposition == OFF_THE_RECORD) {
221 JNIEnv* env = AttachCurrentThread();
222 ScopedJavaLocalRef<jstring> java_url =
223 ConvertUTF8ToJavaString(env, url.spec());
224 Java_ContentViewClient_openNewTab(env,
225 weak_java_client_.get(env).obj(),
226 java_url.obj(),
227 disposition == OFF_THE_RECORD);
228 return NULL;
229 }
230
231 // TODO(mkosiba): This should be in platform_utils OpenExternal, b/6174564.
232 if (transition == content::PAGE_TRANSITION_LINK &&
233 ShouldOverrideLoading(url))
234 return NULL;
235
236 source->GetController().LoadURL(url, params.referrer, transition,
237 std::string());
238 return source;
239 }
240
241 // ShouldIgnoreNavigation will be called for every non-local top level
242 // navigation made by the renderer. If true is returned the renderer will
243 // not perform the navigation. This is done by using synchronous IPC so we
244 // should avoid blocking calls from this method.
245 bool ContentViewClient::ShouldIgnoreNavigation(
246 WebContents* source,
247 const GURL& url,
248 const content::Referrer& referrer,
249 WindowOpenDisposition disposition,
250 content::PageTransition transition_type) {
251
252 // Don't override new tabs.
253 if (disposition == NEW_FOREGROUND_TAB ||
254 disposition == NEW_BACKGROUND_TAB ||
255 disposition == OFF_THE_RECORD)
256 return false;
257
258 // Don't override the navigation that has just been requested via the
259 // ContentView.loadUrl method.
260 if (url == last_requested_navigation_url_) {
261 last_requested_navigation_url_ = GURL::EmptyGURL();
262 return false;
263 }
264
265 return ShouldOverrideLoading(url);
266 }
267
268 void ContentViewClient::NavigationStateChanged(
269 const WebContents* source, unsigned changed_flags) {
270 if (changed_flags & (
271 content::INVALIDATE_TYPE_TAB | content::INVALIDATE_TYPE_TITLE)) {
272 JNIEnv* env = AttachCurrentThread();
273 Java_ContentViewClient_onTabHeaderStateChanged(
274 env, weak_java_client_.get(env).obj());
275 }
276 }
277
278 void ContentViewClient::AddNewContents(WebContents* source,
279 WebContents* new_contents,
280 WindowOpenDisposition disposition,
281 const gfx::Rect& initial_pos,
282 bool user_gesture) {
283 JNIEnv* env = AttachCurrentThread();
284 bool handled = Java_ContentViewClient_addNewContents(
285 env,
286 weak_java_client_.get(env).obj(),
287 reinterpret_cast<jint>(source),
288 reinterpret_cast<jint>(new_contents),
289 static_cast<jint>(disposition),
290 NULL,
291 user_gesture);
292 if (!handled)
293 delete new_contents;
294 }
295
296 void ContentViewClient::ActivateContents(WebContents* contents) {
297 // TODO(dtrainor) When doing the merge I came across this. Should we be
298 // activating this tab here?
299 }
300
301 void ContentViewClient::DeactivateContents(WebContents* contents) {
302 // Do nothing.
303 }
304
305 void ContentViewClient::LoadingStateChanged(WebContents* source) {
306 JNIEnv* env = AttachCurrentThread();
307 bool has_stopped = source == NULL || !source->IsLoading();
308
309 if (has_stopped)
310 Java_ContentViewClient_onLoadStopped(
311 env, weak_java_client_.get(env).obj());
312 else
313 Java_ContentViewClient_onLoadStarted(
314 env, weak_java_client_.get(env).obj());
315 }
316
317 void ContentViewClient::LoadProgressChanged(double progress) {
318 JNIEnv* env = AttachCurrentThread();
319 Java_ContentViewClient_onLoadProgressChanged(
320 env,
321 weak_java_client_.get(env).obj(),
322 progress);
323 }
324
325 void ContentViewClient::CloseContents(WebContents* source) {
326 JNIEnv* env = AttachCurrentThread();
327 Java_ContentViewClient_closeContents(env, weak_java_client_.get(env).obj());
328 }
329
330 void ContentViewClient::MoveContents(WebContents* source,
331 const gfx::Rect& pos) {
332 // Do nothing.
333 }
334
335 // TODO(merge): WARNING! method no longer available on the base class.
336 // See http://b/issue?id=5862108
337 void ContentViewClient::URLStarredChanged(WebContents* source, bool starred) {
338 JNIEnv* env = AttachCurrentThread();
339 Java_ContentViewClient_onUrlStarredChanged(env,
340 weak_java_client_.get(env).obj(),
341 starred);
342 }
343
344 // This is either called from TabContents::DidNavigateMainFramePostCommit() with
345 // an empty GURL or responding to RenderViewHost::OnMsgUpateTargetURL(). In
346 // Chrome, the latter is not always called, especially not during history
347 // navigation. So we only handle the first case and pass the source TabContents'
348 // url to Java to update the UI.
349 void ContentViewClient::UpdateTargetURL(WebContents* source,
350 int32 page_id,
351 const GURL& url) {
352 if (url.is_empty()) {
353 JNIEnv* env = AttachCurrentThread();
354 ScopedJavaLocalRef<jstring> java_url =
355 ConvertUTF8ToJavaString(env, source->GetURL().spec());
356 Java_ContentViewClient_onUpdateUrl(env,
357 weak_java_client_.get(env).obj(),
358 java_url.obj());
359 }
360 }
361
362 bool ContentViewClient::CanDownload(RenderViewHost* source,
363 int request_id,
364 const std::string& request_method) {
365 if (request_method == net::HttpRequestHeaders::kGetMethod) {
366 content::DownloadController::GetInstance()->CreateGETDownload(
367 source, request_id);
368 return false;
369 }
370 return true;
371 }
372
373 void ContentViewClient::OnStartDownload(WebContents* source,
374 DownloadItem* download) {
375 content::DownloadController::GetInstance()->OnPostDownloadStarted(
376 source, download);
377 }
378
379 void ContentViewClient::FindReply(WebContents* web_contents,
380 int request_id,
381 int number_of_matches,
382 const gfx::Rect& selection_rect,
383 int active_match_ordinal,
384 bool final_update) {
385 /* TODO(jrg): upstream this; requires
386 content/browser/android/find_helper.h to be upstreamed */
387 }
388
389 void ContentViewClient::OnReceiveFindMatchRects(
390 int version, const std::vector<FindMatchRect>& rects,
391 const FindMatchRect& active_rect) {
392 JNIEnv* env = AttachCurrentThread();
393
394 // Constructs an float[] of (left, top, right, bottom) tuples and passes it on
395 // to the Java onReceiveFindMatchRects handler which will use it to create
396 // RectF objects equivalent to the std::vector<FindMatchRect>.
397 ScopedJavaLocalRef<jfloatArray> rect_data(env,
398 env->NewFloatArray(rects.size() * 4));
399 jfloat* rect_data_floats = env->GetFloatArrayElements(rect_data.obj(), NULL);
400 for (size_t i = 0; i < rects.size(); ++i) {
401 rect_data_floats[4 * i] = rects[i].left;
402 rect_data_floats[4 * i + 1] = rects[i].top;
403 rect_data_floats[4 * i + 2] = rects[i].right;
404 rect_data_floats[4 * i + 3] = rects[i].bottom;
405 }
406 env->ReleaseFloatArrayElements(rect_data.obj(), rect_data_floats, 0);
407
408 ScopedJavaLocalRef<jobject> active_rect_object;
409 if (active_rect.left < active_rect.right &&
410 active_rect.top < active_rect.bottom) {
411 ScopedJavaLocalRef<jclass> rect_clazz =
412 GetClass(env, "android/graphics/RectF");
413 jmethodID rect_constructor =
414 GetMethodID(env, rect_clazz, "<init>", "(FFFF)V");
415 active_rect_object.Reset(env, env->NewObject(rect_clazz.obj(),
416 rect_constructor,
417 active_rect.left,
418 active_rect.top,
419 active_rect.right,
420 active_rect.bottom));
421 DCHECK(!active_rect_object.is_null());
422 }
423
424
425 Java_ContentViewClient_onReceiveFindMatchRects(
426 env,
427 weak_java_client_.get(env).obj(),
428 version, rect_data.obj(),
429 active_rect_object.obj());
430 }
431
432 bool ContentViewClient::ShouldOverrideLoading(const GURL& url) {
433 if (!url.is_valid())
434 return false;
435
436 JNIEnv* env = AttachCurrentThread();
437 ScopedJavaLocalRef<jstring> jstring_url =
438 ConvertUTF8ToJavaString(env, url.spec());
439 bool ret = Java_ContentViewClient_shouldOverrideUrlLoading(
440 env, weak_java_client_.get(env).obj(), jstring_url.obj());
441 return ret;
442 }
443
444 void ContentViewClient::HandleKeyboardEvent(
445 const NativeWebKeyboardEvent& event) {
446 /* TODO(jrg): to upstream this implementation, we need these files as well:
447 browser/android/ime_helper.cc
448 browser/android/ime_helper.h
449 browser/renderer_host/native_web_keyboard_event_android.h
450 browser/renderer_host/native_web_keyboard_event_android.cc
451 Also the @CalledByNative handleKeyboardEvent() in ContentViewClient.java.
452 */
453 NOTREACHED();
454 }
455
456 bool ContentViewClient::TakeFocus(bool reverse) {
457 JNIEnv* env = AttachCurrentThread();
458 return Java_ContentViewClient_takeFocus(env,
459 weak_java_client_.get(env).obj(),
460 reverse);
461 }
462
463 ContentViewClientError ContentViewClient::ToContentViewClientError(
464 int net_error) {
465 // Note: many net::Error constants don't have an obvious mapping.
466 // These will be handled by the default case, ERROR_UNKNOWN.
467 switch(net_error) {
468 case ERR_UNSUPPORTED_AUTH_SCHEME:
469 return CONTENT_VIEW_CLIENT_ERROR_UNSUPPORTED_AUTH_SCHEME;
470
471 case ERR_INVALID_AUTH_CREDENTIALS:
472 case ERR_MISSING_AUTH_CREDENTIALS:
473 case ERR_MISCONFIGURED_AUTH_ENVIRONMENT:
474 return CONTENT_VIEW_CLIENT_ERROR_AUTHENTICATION;
475
476 case ERR_TOO_MANY_REDIRECTS:
477 return CONTENT_VIEW_CLIENT_ERROR_REDIRECT_LOOP;
478
479 case ERR_UPLOAD_FILE_CHANGED:
480 return CONTENT_VIEW_CLIENT_ERROR_FILE_NOT_FOUND;
481
482 case ERR_INVALID_URL:
483 return CONTENT_VIEW_CLIENT_ERROR_BAD_URL;
484
485 case ERR_DISALLOWED_URL_SCHEME:
486 case ERR_UNKNOWN_URL_SCHEME:
487 return CONTENT_VIEW_CLIENT_ERROR_UNSUPPORTED_SCHEME;
488
489 case ERR_IO_PENDING:
490 case ERR_NETWORK_IO_SUSPENDED:
491 return CONTENT_VIEW_CLIENT_ERROR_IO;
492
493 case ERR_CONNECTION_TIMED_OUT:
494 case ERR_TIMED_OUT:
495 return CONTENT_VIEW_CLIENT_ERROR_TIMEOUT;
496
497 case ERR_FILE_TOO_BIG:
498 return CONTENT_VIEW_CLIENT_ERROR_FILE;
499
500 case ERR_HOST_RESOLVER_QUEUE_TOO_LARGE:
501 case ERR_INSUFFICIENT_RESOURCES:
502 case ERR_OUT_OF_MEMORY:
503 return CONTENT_VIEW_CLIENT_ERROR_TOO_MANY_REQUESTS;
504
505 case ERR_CONNECTION_CLOSED:
506 case ERR_CONNECTION_RESET:
507 case ERR_CONNECTION_REFUSED:
508 case ERR_CONNECTION_ABORTED:
509 case ERR_CONNECTION_FAILED:
510 case ERR_SOCKET_NOT_CONNECTED:
511 return CONTENT_VIEW_CLIENT_ERROR_CONNECT;
512
513 case ERR_INTERNET_DISCONNECTED:
514 case ERR_ADDRESS_INVALID:
515 case ERR_ADDRESS_UNREACHABLE:
516 case ERR_NAME_NOT_RESOLVED:
517 case ERR_NAME_RESOLUTION_FAILED:
518 return CONTENT_VIEW_CLIENT_ERROR_HOST_LOOKUP;
519
520 case ERR_SSL_PROTOCOL_ERROR:
521 case ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
522 case ERR_TUNNEL_CONNECTION_FAILED:
523 case ERR_NO_SSL_VERSIONS_ENABLED:
524 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
525 case ERR_SSL_RENEGOTIATION_REQUESTED:
526 case ERR_CERT_ERROR_IN_SSL_RENEGOTIATION:
527 case ERR_BAD_SSL_CLIENT_AUTH_CERT:
528 case ERR_SSL_NO_RENEGOTIATION:
529 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
530 case ERR_SSL_BAD_RECORD_MAC_ALERT:
531 case ERR_SSL_UNSAFE_NEGOTIATION:
532 case ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
533 case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
534 case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
535 return CONTENT_VIEW_CLIENT_ERROR_FAILED_SSL_HANDSHAKE;
536
537 case ERR_PROXY_AUTH_UNSUPPORTED:
538 case ERR_PROXY_AUTH_REQUESTED:
539 case ERR_PROXY_CONNECTION_FAILED:
540 case ERR_UNEXPECTED_PROXY_AUTH:
541 return CONTENT_VIEW_CLIENT_ERROR_PROXY_AUTHENTICATION;
542
543 /* The certificate errors are handled by onReceivedSslError
544 * and don't need to be reported here.
545 */
546 case ERR_CERT_COMMON_NAME_INVALID:
547 case ERR_CERT_DATE_INVALID:
548 case ERR_CERT_AUTHORITY_INVALID:
549 case ERR_CERT_CONTAINS_ERRORS:
550 case ERR_CERT_NO_REVOCATION_MECHANISM:
551 case ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
552 case ERR_CERT_REVOKED:
553 case ERR_CERT_INVALID:
554 case ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
555 case ERR_CERT_NOT_IN_DNS:
556 case ERR_CERT_NON_UNIQUE_NAME:
557 return CONTENT_VIEW_CLIENT_ERROR_OK;
558
559 default:
560 VLOG(1) << "ContentViewClient::ToContentViewClientError: Unknown "
561 << "chromium error: "
562 << net_error;
563 return CONTENT_VIEW_CLIENT_ERROR_UNKNOWN;
564 }
565 }
566
567 content::JavaScriptDialogCreator*
568 ContentViewClient::GetJavaScriptDialogCreator() {
569 return javascript_dialog_creator_;
570 }
571
572 void ContentViewClient::RunFileChooser(
573 WebContents* tab, const content::FileChooserParams& params) {
574 JNIEnv* env = AttachCurrentThread();
575 ScopedJavaLocalRef<jobject> jparams = ToJavaFileChooserParams(env, params);
576 Java_ContentViewClient_runFileChooser(env, weak_java_client_.get(env).obj(),
577 jparams.obj());
578 }
579
580 // ----------------------------------------------------------------------------
581 // Native JNI methods
582 // ----------------------------------------------------------------------------
583
584 // Register native methods
585
586 bool RegisterContentViewClient(JNIEnv* env) {
587 if (!HasClass(env, kContentViewClientClassPath)) {
588 DLOG(ERROR) << "Unable to find class ContentViewClient!";
589 return false;
590 }
591 return RegisterNativesImpl(env);
592 }
593
594 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698