OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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/dialog_android_overlay.h" |
| 6 |
| 7 #include "content/browser/frame_host/render_frame_host_impl.h" |
| 8 #include "content/public/browser/render_process_host.h" |
| 9 #include "content/public/browser/web_contents.h" |
| 10 #include "jni/DialogAndroidOverlay_jni.h" |
| 11 #include "ui/android/window_android.h" |
| 12 |
| 13 using base::android::AttachCurrentThread; |
| 14 using base::android::JavaParamRef; |
| 15 using base::android::ScopedJavaLocalRef; |
| 16 |
| 17 namespace content { |
| 18 |
| 19 // static |
| 20 bool DialogAndroidOverlay::RegisterDialogAndroidOverlay(JNIEnv* env) { |
| 21 return RegisterNativesImpl(env); |
| 22 } |
| 23 |
| 24 static jlong Init(JNIEnv* env, |
| 25 const JavaParamRef<jobject>& obj, |
| 26 jint renderer_pid, |
| 27 jint render_frame_id) { |
| 28 return reinterpret_cast<jlong>( |
| 29 new DialogAndroidOverlay(obj, renderer_pid, render_frame_id)); |
| 30 } |
| 31 |
| 32 static void Shutdown(JNIEnv* env, |
| 33 const JavaParamRef<jobject>& obj, |
| 34 jlong handle) { |
| 35 content::BrowserThread::DeleteSoon( |
| 36 content::BrowserThread::UI, FROM_HERE, |
| 37 reinterpret_cast<DialogAndroidOverlay*>(handle)); |
| 38 } |
| 39 |
| 40 DialogAndroidOverlay::DialogAndroidOverlay( |
| 41 const JavaParamRef<jobject>& receiver, |
| 42 int renderer_pid, |
| 43 int render_frame_id) |
| 44 : receiver_(receiver), |
| 45 renderer_pid_(renderer_pid), |
| 46 render_frame_id_(render_frame_id), |
| 47 cvc_(nullptr) { |
| 48 // This is called from a random thread, so post to the right one. |
| 49 // Note that it's safe for |this| to be unretained, since java can't destroy |
| 50 // us until we return, and that will post too. |
| 51 content::BrowserThread::PostTask( |
| 52 content::BrowserThread::UI, FROM_HERE, |
| 53 base::Bind(&DialogAndroidOverlay::CompleteInitialization, |
| 54 base::Unretained(this))); |
| 55 } |
| 56 |
| 57 DialogAndroidOverlay::~DialogAndroidOverlay() { |
| 58 if (cvc_) |
| 59 cvc_->RemoveObserver(this); |
| 60 } |
| 61 |
| 62 void DialogAndroidOverlay::OnContentViewCoreDestroyed() { |
| 63 cvc_ = nullptr; |
| 64 |
| 65 JNIEnv* env = AttachCurrentThread(); |
| 66 Java_DialogAndroidOverlay_onDismissed(env, receiver_.obj()); |
| 67 // |this| might be destroyed. |
| 68 } |
| 69 |
| 70 void DialogAndroidOverlay::OnAttachedToWindow() { |
| 71 JNIEnv* env = AttachCurrentThread(); |
| 72 |
| 73 ScopedJavaLocalRef<jobject> token; |
| 74 |
| 75 if (ui::WindowAndroid* window = cvc_->GetWindowAndroid()) |
| 76 token = window->GetWindowToken(); |
| 77 |
| 78 Java_DialogAndroidOverlay_onWindowToken(env, receiver_.obj(), token); |
| 79 } |
| 80 |
| 81 void DialogAndroidOverlay::OnDetachedFromWindow() { |
| 82 JNIEnv* env = AttachCurrentThread(); |
| 83 Java_DialogAndroidOverlay_onWindowToken(env, receiver_.obj(), nullptr); |
| 84 } |
| 85 |
| 86 void DialogAndroidOverlay::CompleteInitialization() { |
| 87 cvc_ = GetContentViewCore(); |
| 88 |
| 89 // If there's no CVC, then just post a null token immediately. |
| 90 if (!cvc_) { |
| 91 JNIEnv* env = AttachCurrentThread(); |
| 92 Java_DialogAndroidOverlay_onDismissed(env, receiver_.obj()); |
| 93 // |this| might be destroyed. |
| 94 return; |
| 95 } |
| 96 |
| 97 cvc_->AddObserver(this); |
| 98 |
| 99 // Also send the initial token, since we'll only get changes. |
| 100 if (ui::WindowAndroid* window = cvc_->GetWindowAndroid()) { |
| 101 ScopedJavaLocalRef<jobject> token = window->GetWindowToken(); |
| 102 if (!token.is_null()) { |
| 103 JNIEnv* env = AttachCurrentThread(); |
| 104 Java_DialogAndroidOverlay_onWindowToken(env, receiver_.obj(), token); |
| 105 } |
| 106 } |
| 107 } |
| 108 |
| 109 ContentViewCoreImpl* DialogAndroidOverlay::GetContentViewCore() { |
| 110 // Get the id from the handle. On android, the handle is the pid. |
| 111 content::RenderProcessHost::iterator it = |
| 112 content::RenderProcessHost::AllHostsIterator(); |
| 113 int render_process_id = 0; |
| 114 while (!it.IsAtEnd()) { |
| 115 if (it.GetCurrentValue()->GetHandle() == renderer_pid_) { |
| 116 render_process_id = it.GetCurrentValue()->GetID(); |
| 117 break; |
| 118 } |
| 119 it.Advance(); |
| 120 } |
| 121 if (!render_process_id) { |
| 122 DVLOG(1) << "Cannot find render process for renderer_pid " << renderer_pid_; |
| 123 return nullptr; |
| 124 } |
| 125 |
| 126 // Get the frame from the id. |
| 127 content::RenderFrameHostImpl* frame = |
| 128 content::RenderFrameHostImpl::FromID(render_process_id, render_frame_id_); |
| 129 if (!frame) { |
| 130 DVLOG(1) << "Cannot find frame for renderer_pid " << renderer_pid_ |
| 131 << " render_frame_id " << render_frame_id_; |
| 132 return nullptr; |
| 133 } |
| 134 |
| 135 content::WebContents* web_contents = |
| 136 content::WebContents::FromRenderFrameHost(frame); |
| 137 if (!web_contents) { |
| 138 DVLOG(1) << "Cannot find web_contents for renderer_pid " << renderer_pid_ |
| 139 << " render_frame_id " << render_frame_id_; |
| 140 return nullptr; |
| 141 } |
| 142 |
| 143 content::ContentViewCoreImpl* cvc = |
| 144 content::ContentViewCoreImpl::FromWebContents(web_contents); |
| 145 if (!cvc) { |
| 146 DVLOG(1) << "Cannot find cvc for renderer_pid " << renderer_pid_ |
| 147 << " render_frame_id " << render_frame_id_; |
| 148 return nullptr; |
| 149 } |
| 150 |
| 151 return cvc; |
| 152 } |
| 153 |
| 154 } // namespace content |
OLD | NEW |