Skip to content

Commit af9a3d6

Browse files
committed
Introduce ScopedJNIEnv with default PushLocalFrame (see issue chromiumembedded#167)
PushLocalFrame creates a new local reference frame, in which at least a given number of local references can be created. Note that local references already created in previous local frames are still valid in the current local frame.
1 parent ebd7474 commit af9a3d6

37 files changed

+280
-194
lines changed

native/browser_process_handler.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ void BrowserProcessHandler::OnContextInitialized() {
3131
if (!handle_)
3232
return;
3333

34-
BEGIN_ENV(env)
34+
ScopedJNIEnv env;
35+
if (!env)
36+
return;
37+
3538
JNI_CALL_VOID_METHOD(env, handle_, "onContextInitialized", "()V");
36-
END_ENV(env)
3739
}
3840

3941
void BrowserProcessHandler::OnRenderProcessThreadCreated(
@@ -54,7 +56,10 @@ void BrowserProcessHandler::OnRenderProcessThreadCreated(
5456

5557
CefRefPtr<CefPrintHandler> BrowserProcessHandler::GetPrintHandler() {
5658
CefRefPtr<CefPrintHandler> result;
57-
BEGIN_ENV(env)
59+
ScopedJNIEnv env;
60+
if (!env)
61+
return nullptr;
62+
5863
ScopedJNIObjectResult jresult(env);
5964
JNI_CALL_METHOD(env, handle_, "getPrintHandler",
6065
"()Lorg/cef/handler/CefPrintHandler;", Object, jresult);
@@ -64,18 +69,20 @@ CefRefPtr<CefPrintHandler> BrowserProcessHandler::GetPrintHandler() {
6469
env, jresult.Release(), true /* should_delete */, "CefPrintHandler");
6570
result = jprintHandler.GetOrCreateCefObject();
6671
}
67-
END_ENV(env)
72+
6873
return result;
6974
}
7075

7176
void BrowserProcessHandler::OnScheduleMessagePumpWork(int64 delay_ms) {
7277
if (!handle_)
7378
return;
7479

75-
BEGIN_ENV(env)
80+
ScopedJNIEnv env;
81+
if (!env)
82+
return;
83+
7684
JNI_CALL_VOID_METHOD(env, handle_, "onScheduleMessagePumpWork", "(J)V",
7785
delay_ms);
78-
END_ENV(env)
7986
}
8087

8188
void BrowserProcessHandler::AddMessageRouterConfig(

native/client_app.cpp

+10-8
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ void ClientApp::OnBeforeCommandLineProcessing(
3232
// the commandline processing to it before we append the essential
3333
// switches "locale_pak" and "use-core-animation".
3434
if (handle_ && process_type.empty()) {
35-
BEGIN_ENV(env)
35+
ScopedJNIEnv env;
36+
if (!env)
37+
return;
3638

3739
ScopedJNIString jprocessType(env, process_type);
3840
ScopedJNIObject<CefCommandLine> jcommandLine(
@@ -44,8 +46,6 @@ void ClientApp::OnBeforeCommandLineProcessing(
4446
env, handle_, "onBeforeCommandLineProcessing",
4547
"(Ljava/lang/String;Lorg/cef/callback/CefCommandLine;)V",
4648
jprocessType.get(), jcommandLine.get());
47-
48-
END_ENV(env)
4949
}
5050

5151
if (process_type.empty()) {
@@ -71,7 +71,9 @@ void ClientApp::OnRegisterCustomSchemes(
7171
if (!handle_)
7272
return;
7373

74-
BEGIN_ENV(env)
74+
ScopedJNIEnv env;
75+
if (!env)
76+
return;
7577

7678
ScopedJNIObject<CefSchemeRegistrar, CefRawPtr<CefSchemeRegistrar>> jregistrar(
7779
env, registrar, "org/cef/callback/CefSchemeRegistrar_N",
@@ -81,8 +83,6 @@ void ClientApp::OnRegisterCustomSchemes(
8183
JNI_CALL_VOID_METHOD(env, handle_, "onRegisterCustomSchemes",
8284
"(Lorg/cef/callback/CefSchemeRegistrar;)V",
8385
jregistrar.get());
84-
85-
END_ENV(env)
8686
}
8787

8888
CefRefPtr<CefBrowserProcessHandler> ClientApp::GetBrowserProcessHandler() {
@@ -91,7 +91,10 @@ CefRefPtr<CefBrowserProcessHandler> ClientApp::GetBrowserProcessHandler() {
9191

9292
#if defined(OS_MACOSX)
9393
bool ClientApp::HandleTerminate() {
94-
BEGIN_ENV(env)
94+
ScopedJNIEnv env;
95+
if (!env)
96+
return;
97+
9598
ScopedJNIClass jcls(env, "org/cef/CefApp");
9699
if (!jcls) {
97100
return false;
@@ -110,7 +113,6 @@ bool ClientApp::HandleTerminate() {
110113
}
111114

112115
JNI_CALL_VOID_METHOD(env, jcefApp, "handleBeforeTerminate", "()V");
113-
END_ENV(env)
114116
return true;
115117
}
116118
#endif // defined(OS_MACOSX)

native/client_handler.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@ CefRefPtr<T> ClientHandler::GetHandler(const char* class_name) {
7575
ss << "()Lorg/cef/handler/" << className << ";";
7676
methodSig = ss.str();
7777

78+
ScopedJNIEnv env;
79+
if (!env)
80+
return nullptr;
81+
7882
CefRefPtr<T> result = NULL;
79-
BEGIN_ENV(env)
8083
ScopedJNIObjectResult jresult(env);
8184
JNI_CALL_METHOD(env, handle_, methodName.c_str(), methodSig.c_str(), Object,
8285
jresult);
@@ -85,7 +88,7 @@ CefRefPtr<T> ClientHandler::GetHandler(const char* class_name) {
8588
true /* should_delete */, className.c_str());
8689
result = jhandler.GetOrCreateCefObject();
8790
}
88-
END_ENV(env)
91+
8992
return result;
9093
}
9194

native/completion_callback.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ CompletionCallback::CompletionCallback(JNIEnv* env, jobject jhandler)
1212
: handle_(env, jhandler) {}
1313

1414
void CompletionCallback::OnComplete() {
15-
JNIEnv* env = GetJNIEnv();
15+
ScopedJNIEnv env;
1616
if (!env)
1717
return;
1818
JNI_CALL_VOID_METHOD(env, handle_, "onComplete", "()V");

native/context_menu_handler.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void ContextMenuHandler::OnBeforeContextMenu(
3030
CefRefPtr<CefFrame> frame,
3131
CefRefPtr<CefContextMenuParams> params,
3232
CefRefPtr<CefMenuModel> model) {
33-
JNIEnv* env = GetJNIEnv();
33+
ScopedJNIEnv env;
3434
if (!env)
3535
return;
3636

@@ -56,7 +56,7 @@ bool ContextMenuHandler::OnContextMenuCommand(
5656
CefRefPtr<CefContextMenuParams> params,
5757
int command_id,
5858
EventFlags event_flags) {
59-
JNIEnv* env = GetJNIEnv();
59+
ScopedJNIEnv env;
6060
if (!env)
6161
return false;
6262

@@ -79,7 +79,7 @@ bool ContextMenuHandler::OnContextMenuCommand(
7979

8080
void ContextMenuHandler::OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
8181
CefRefPtr<CefFrame> frame) {
82-
JNIEnv* env = GetJNIEnv();
82+
ScopedJNIEnv env;
8383
if (!env)
8484
return;
8585

native/cookie_access_filter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ bool CookieAccessFilter::CanSendCookie(CefRefPtr<CefBrowser> browser,
1414
CefRefPtr<CefFrame> frame,
1515
CefRefPtr<CefRequest> request,
1616
const CefCookie& cookie) {
17-
JNIEnv* env = GetJNIEnv();
17+
ScopedJNIEnv env;
1818
if (!env)
1919
return true;
2020

@@ -40,7 +40,7 @@ bool CookieAccessFilter::CanSaveCookie(CefRefPtr<CefBrowser> browser,
4040
CefRefPtr<CefRequest> request,
4141
CefRefPtr<CefResponse> response,
4242
const CefCookie& cookie) {
43-
JNIEnv* env = GetJNIEnv();
43+
ScopedJNIEnv env;
4444
if (!env)
4545
return true;
4646

native/cookie_visitor.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ bool CookieVisitor::Visit(const CefCookie& cookie,
1515
int count,
1616
int total,
1717
bool& deleteCookie) {
18-
JNIEnv* env = GetJNIEnv();
18+
ScopedJNIEnv env;
1919
if (!env)
2020
return false;
2121

native/dialog_handler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ bool DialogHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
3434
const std::vector<CefString>& accept_filters,
3535
int selected_accept_filter,
3636
CefRefPtr<CefFileDialogCallback> callback) {
37-
JNIEnv* env = GetJNIEnv();
37+
ScopedJNIEnv env;
3838
if (!env)
3939
return false;
4040

native/display_handler.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ DisplayHandler::DisplayHandler(JNIEnv* env, jobject handler)
1212
void DisplayHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
1313
CefRefPtr<CefFrame> frame,
1414
const CefString& url) {
15-
JNIEnv* env = GetJNIEnv();
15+
ScopedJNIEnv env;
1616
if (!env)
1717
return;
1818

@@ -29,7 +29,7 @@ void DisplayHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
2929

3030
void DisplayHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
3131
const CefString& title) {
32-
JNIEnv* env = GetJNIEnv();
32+
ScopedJNIEnv env;
3333
if (!env)
3434
return;
3535

@@ -42,7 +42,7 @@ void DisplayHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
4242
}
4343

4444
bool DisplayHandler::OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text) {
45-
JNIEnv* env = GetJNIEnv();
45+
ScopedJNIEnv env;
4646
if (!env)
4747
return false;
4848

@@ -59,7 +59,7 @@ bool DisplayHandler::OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text) {
5959

6060
void DisplayHandler::OnStatusMessage(CefRefPtr<CefBrowser> browser,
6161
const CefString& value) {
62-
JNIEnv* env = GetJNIEnv();
62+
ScopedJNIEnv env;
6363
if (!env)
6464
return;
6565

@@ -76,7 +76,7 @@ bool DisplayHandler::OnConsoleMessage(CefRefPtr<CefBrowser> browser,
7676
const CefString& message,
7777
const CefString& source,
7878
int line) {
79-
JNIEnv* env = GetJNIEnv();
79+
ScopedJNIEnv env;
8080
if (!env)
8181
return false;
8282

native/download_handler.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void DownloadHandler::OnBeforeDownload(
5454
CefRefPtr<CefDownloadItem> download_item,
5555
const CefString& suggested_name,
5656
CefRefPtr<CefBeforeDownloadCallback> callback) {
57-
JNIEnv* env = GetJNIEnv();
57+
ScopedJNIEnv env;
5858
if (!env)
5959
return;
6060

@@ -76,7 +76,7 @@ void DownloadHandler::OnDownloadUpdated(
7676
CefRefPtr<CefBrowser> browser,
7777
CefRefPtr<CefDownloadItem> download_item,
7878
CefRefPtr<CefDownloadItemCallback> callback) {
79-
JNIEnv* env = GetJNIEnv();
79+
ScopedJNIEnv env;
8080
if (!env)
8181
return;
8282

native/drag_handler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ DragHandler::DragHandler(JNIEnv* env, jobject handler)
1212
bool DragHandler::OnDragEnter(CefRefPtr<CefBrowser> browser,
1313
CefRefPtr<CefDragData> dragData,
1414
CefDragHandler::DragOperationsMask mask) {
15-
JNIEnv* env = GetJNIEnv();
15+
ScopedJNIEnv env;
1616
if (!env)
1717
return false;
1818

native/focus_handler.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ FocusHandler::FocusHandler(JNIEnv* env, jobject handler)
1414
: handle_(env, handler) {}
1515

1616
void FocusHandler::OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) {
17-
JNIEnv* env = GetJNIEnv();
17+
ScopedJNIEnv env;
1818
if (!env)
1919
return;
2020

@@ -26,7 +26,7 @@ void FocusHandler::OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) {
2626

2727
bool FocusHandler::OnSetFocus(CefRefPtr<CefBrowser> browser,
2828
FocusSource source) {
29-
JNIEnv* env = GetJNIEnv();
29+
ScopedJNIEnv env;
3030
if (!env)
3131
return false;
3232

@@ -49,7 +49,7 @@ bool FocusHandler::OnSetFocus(CefRefPtr<CefBrowser> browser,
4949
}
5050

5151
void FocusHandler::OnGotFocus(CefRefPtr<CefBrowser> browser) {
52-
JNIEnv* env = GetJNIEnv();
52+
ScopedJNIEnv env;
5353
if (!env)
5454
return;
5555

native/jni_scoped_helpers.cpp

+73-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,37 @@
99

1010
namespace {
1111

12+
// Retrieves the JNIEnv for the current thread. Attaches the VM to the current
13+
// thread if necessary. Sets |mustDetach| to true if DetachJNIEnv must be
14+
// called.
15+
jint GetJNIEnv(JNIEnv** env, bool* mustDetach) {
16+
*env = nullptr;
17+
*mustDetach = false;
18+
19+
JavaVM* jvm = GetJVM();
20+
if (!jvm)
21+
return JNI_ERR;
22+
23+
jint result = jvm->GetEnv((void**)env, JNI_VERSION_1_6);
24+
if (result == JNI_EDETACHED) {
25+
result = jvm->AttachCurrentThreadAsDaemon((void**)env, NULL);
26+
if (result == JNI_OK) {
27+
*mustDetach = true;
28+
}
29+
}
30+
31+
return result;
32+
}
33+
34+
// Detaches the current thread from the VM. Should only be called if
35+
// |mustDetach| was set to true by GetJNIEnv.
36+
void DetachJNIEnv() {
37+
JavaVM* jvm = GetJVM();
38+
if (jvm) {
39+
jvm->DetachCurrentThread();
40+
}
41+
}
42+
1243
// Returns a class with the given fully qualified |class_name| (with '/' as
1344
// separator).
1445
jclass FindClass(JNIEnv* env, const char* class_name) {
@@ -139,6 +170,45 @@ jobject GetJNIBrowser(JNIEnv* env, CefRefPtr<CefBrowser> browser) {
139170

140171
} // namespace
141172

173+
// static
174+
const int ScopedJNIEnv::kDefaultLocalCapacity = 1024;
175+
176+
ScopedJNIEnv::ScopedJNIEnv(jint local_capacity)
177+
: ScopedJNIEnv(nullptr, local_capacity) {}
178+
179+
ScopedJNIEnv::ScopedJNIEnv(JNIEnv* env, jint local_capacity)
180+
: jenv_(env), local_capacity_(local_capacity) {
181+
if (!jenv_) {
182+
if (GetJNIEnv(&jenv_, &should_detach_) != JNI_OK || !jenv_) {
183+
NOTREACHED() << "Failed to retrieve JNIEnv";
184+
return;
185+
}
186+
}
187+
if (local_capacity_ > 0) {
188+
if (jenv_->EnsureLocalCapacity(local_capacity_) != JNI_OK ||
189+
jenv_->PushLocalFrame(local_capacity_) != JNI_OK) {
190+
LOG(WARNING) << "Failed to create local frame with capacity "
191+
<< local_capacity_;
192+
local_capacity_ = 0;
193+
}
194+
}
195+
}
196+
197+
ScopedJNIEnv::~ScopedJNIEnv() {
198+
if (!jenv_)
199+
return;
200+
if (local_capacity_ > 0) {
201+
if (export_result_) {
202+
*export_result_ = jenv_->PopLocalFrame(*export_result_);
203+
} else {
204+
jenv_->PopLocalFrame(NULL);
205+
}
206+
}
207+
if (should_detach_) {
208+
DetachJNIEnv();
209+
}
210+
}
211+
142212
ScopedJNIObjectGlobal::ScopedJNIObjectGlobal(JNIEnv* env, jobject handle)
143213
: jhandle_(NULL) {
144214
if (handle) {
@@ -149,9 +219,9 @@ ScopedJNIObjectGlobal::ScopedJNIObjectGlobal(JNIEnv* env, jobject handle)
149219

150220
ScopedJNIObjectGlobal::~ScopedJNIObjectGlobal() {
151221
if (jhandle_) {
152-
BEGIN_ENV(env);
153-
env->DeleteGlobalRef(jhandle_);
154-
END_ENV(env);
222+
ScopedJNIEnv env;
223+
if (env)
224+
env->DeleteGlobalRef(jhandle_);
155225
}
156226
}
157227

0 commit comments

Comments
 (0)