diff options
author | Andreas Gampe | 2014-08-20 00:31:31 -0500 |
---|---|---|
committer | Andreas Gampe | 2014-08-22 03:44:06 -0500 |
commit | 049249ce7addafaa0bd09480cd8858cd2c54138f (patch) | |
tree | d97559db3a4658231163f816ebc05d9e92ad86da /libnativebridge | |
parent | a59b6ac6973b3f5ce1246bf73969094779436892 (diff) | |
download | platform-system-core-049249ce7addafaa0bd09480cd8858cd2c54138f.tar.gz platform-system-core-049249ce7addafaa0bd09480cd8858cd2c54138f.tar.xz platform-system-core-049249ce7addafaa0bd09480cd8858cd2c54138f.zip |
NativeBridge: Tighten security on libnativebridge
Do not allow arbitrary paths for the native bridge - only allow
simple names.
Do not allow re-setup of the native bridge.
Bug: 16404669
(cherry picked from commit cd2ef4c1af69727231b84ebc82864c170ff0e8ad)
Change-Id: Ie22de356d2307fe2758f9094a85d44e61a4098a1
Diffstat (limited to 'libnativebridge')
-rw-r--r-- | libnativebridge/Android.mk | 6 | ||||
-rw-r--r-- | libnativebridge/native_bridge.cc | 101 | ||||
-rw-r--r-- | libnativebridge/tests/Android.mk | 33 | ||||
-rw-r--r-- | libnativebridge/tests/InvalidCharsNativeBridge_test.cpp | 40 | ||||
-rw-r--r-- | libnativebridge/tests/NativeBridgeTest.h | 33 | ||||
-rw-r--r-- | libnativebridge/tests/ReSetupNativeBridge_test.cpp | 32 | ||||
-rw-r--r-- | libnativebridge/tests/UnavailableNativeBridge_test.cpp | 28 | ||||
-rw-r--r-- | libnativebridge/tests/ValidNameNativeBridge_test.cpp | 33 |
8 files changed, 297 insertions, 9 deletions
diff --git a/libnativebridge/Android.mk b/libnativebridge/Android.mk index 017ce0248..9403fd2e1 100644 --- a/libnativebridge/Android.mk +++ b/libnativebridge/Android.mk | |||
@@ -10,10 +10,11 @@ include $(CLEAR_VARS) | |||
10 | LOCAL_MODULE:= libnativebridge | 10 | LOCAL_MODULE:= libnativebridge |
11 | 11 | ||
12 | LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES) | 12 | LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES) |
13 | LOCAL_SHARED_LIBRARIES := liblog | ||
13 | LOCAL_CLANG := true | 14 | LOCAL_CLANG := true |
14 | LOCAL_CPP_EXTENSION := .cc | 15 | LOCAL_CPP_EXTENSION := .cc |
15 | LOCAL_CFLAGS := -Werror | 16 | LOCAL_CFLAGS := -Werror |
16 | LOCAL_CPPFLAGS := -std=gnu++11 | 17 | LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected |
17 | LOCAL_LDFLAGS := -ldl | 18 | LOCAL_LDFLAGS := -ldl |
18 | LOCAL_MULTILIB := both | 19 | LOCAL_MULTILIB := both |
19 | 20 | ||
@@ -26,10 +27,11 @@ include $(CLEAR_VARS) | |||
26 | LOCAL_MODULE:= libnativebridge | 27 | LOCAL_MODULE:= libnativebridge |
27 | 28 | ||
28 | LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES) | 29 | LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES) |
30 | LOCAL_SHARED_LIBRARIES := liblog | ||
29 | LOCAL_CLANG := true | 31 | LOCAL_CLANG := true |
30 | LOCAL_CPP_EXTENSION := .cc | 32 | LOCAL_CPP_EXTENSION := .cc |
31 | LOCAL_CFLAGS := -Werror | 33 | LOCAL_CFLAGS := -Werror |
32 | LOCAL_CPPFLAGS := -std=gnu++11 | 34 | LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected |
33 | LOCAL_LDFLAGS := -ldl | 35 | LOCAL_LDFLAGS := -ldl |
34 | LOCAL_MULTILIB := both | 36 | LOCAL_MULTILIB := both |
35 | 37 | ||
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc index ad4ee73d6..2205f453b 100644 --- a/libnativebridge/native_bridge.cc +++ b/libnativebridge/native_bridge.cc | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include "nativebridge/native_bridge.h" | 17 | #include "nativebridge/native_bridge.h" |
18 | 18 | ||
19 | #include <cutils/log.h> | ||
19 | #include <dlfcn.h> | 20 | #include <dlfcn.h> |
20 | #include <stdio.h> | 21 | #include <stdio.h> |
21 | #include "utils/Mutex.h" | 22 | #include "utils/Mutex.h" |
@@ -28,27 +29,92 @@ static Mutex native_bridge_lock("native bridge lock"); | |||
28 | // The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks. | 29 | // The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks. |
29 | static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf"; | 30 | static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf"; |
30 | 31 | ||
31 | // The path of the library we are supposed to load. | 32 | // The filename of the library we are supposed to load. |
32 | static const char* native_bridge_library_path = nullptr; | 33 | static const char* native_bridge_library_filename = nullptr; |
33 | 34 | ||
34 | // Whether a native bridge is available (loaded and ready). | 35 | // Whether a native bridge is available (loaded and ready). |
35 | static bool available = false; | 36 | static bool available = false; |
36 | // Whether we have already initialized (or tried to). | 37 | // Whether we have already initialized (or tried to). |
37 | static bool initialized = false; | 38 | static bool initialized = false; |
39 | // Whether we had an error at some point. | ||
40 | static bool had_error = false; | ||
38 | 41 | ||
39 | static NativeBridgeCallbacks* callbacks = nullptr; | 42 | static NativeBridgeCallbacks* callbacks = nullptr; |
40 | static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr; | 43 | static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr; |
41 | 44 | ||
42 | void SetupNativeBridge(const char* nb_library_path, | 45 | // Characters allowed in a native bridge filename. The first character must |
46 | // be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-]. | ||
47 | static bool CharacterAllowed(char c, bool first) { | ||
48 | if (first) { | ||
49 | return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); | ||
50 | } else { | ||
51 | return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || | ||
52 | (c == '.') || (c == '_') || (c == '-'); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | // We only allow simple names for the library. It is supposed to be a file in | ||
57 | // /system/lib or /vendor/lib. Only allow a small range of characters, that is | ||
58 | // names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z]. | ||
59 | bool NativeBridgeNameAcceptable(const char* nb_library_filename) { | ||
60 | const char* ptr = nb_library_filename; | ||
61 | if (*ptr == 0) { | ||
62 | // Emptry string. Allowed, means no native bridge. | ||
63 | return true; | ||
64 | } else { | ||
65 | // First character must be [a-zA-Z]. | ||
66 | if (!CharacterAllowed(*ptr, true)) { | ||
67 | // Found an invalid fist character, don't accept. | ||
68 | ALOGE("Native bridge library %s has been rejected for first character %c", nb_library_filename, *ptr); | ||
69 | return false; | ||
70 | } else { | ||
71 | // For the rest, be more liberal. | ||
72 | ptr++; | ||
73 | while (*ptr != 0) { | ||
74 | if (!CharacterAllowed(*ptr, false)) { | ||
75 | // Found an invalid character, don't accept. | ||
76 | ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr); | ||
77 | return false; | ||
78 | } | ||
79 | ptr++; | ||
80 | } | ||
81 | } | ||
82 | return true; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | void SetupNativeBridge(const char* nb_library_filename, | ||
43 | const NativeBridgeRuntimeCallbacks* runtime_cbs) { | 87 | const NativeBridgeRuntimeCallbacks* runtime_cbs) { |
44 | Mutex::Autolock auto_lock(native_bridge_lock); | 88 | Mutex::Autolock auto_lock(native_bridge_lock); |
45 | 89 | ||
46 | native_bridge_library_path = nb_library_path; | 90 | if (initialized || native_bridge_library_filename != nullptr) { |
91 | // Setup has been called before. Ignore this call. | ||
92 | ALOGW("Called SetupNativeBridge for an already set up native bridge."); | ||
93 | // Note: counts as an error, even though the bridge may be functional. | ||
94 | had_error = true; | ||
95 | return; | ||
96 | } | ||
97 | |||
47 | runtime_callbacks = runtime_cbs; | 98 | runtime_callbacks = runtime_cbs; |
48 | 99 | ||
49 | if (native_bridge_library_path == nullptr) { | 100 | if (nb_library_filename == nullptr) { |
50 | initialized = true; | ||
51 | available = false; | 101 | available = false; |
102 | initialized = true; | ||
103 | } else { | ||
104 | // Check whether it's an empty string. | ||
105 | if (*nb_library_filename == 0) { | ||
106 | available = false; | ||
107 | initialized = true; | ||
108 | } else if (!NativeBridgeNameAcceptable(nb_library_filename)) { | ||
109 | available = false; | ||
110 | initialized = true; | ||
111 | had_error = true; | ||
112 | } | ||
113 | |||
114 | if (!initialized) { | ||
115 | // Didn't find a name error or empty string, assign it. | ||
116 | native_bridge_library_filename = nb_library_filename; | ||
117 | } | ||
52 | } | 118 | } |
53 | } | 119 | } |
54 | 120 | ||
@@ -62,7 +128,15 @@ static bool NativeBridgeInitialize() { | |||
62 | 128 | ||
63 | available = false; | 129 | available = false; |
64 | 130 | ||
65 | void* handle = dlopen(native_bridge_library_path, RTLD_LAZY); | 131 | if (native_bridge_library_filename == nullptr) { |
132 | // Called initialize without setup. dlopen has special semantics for nullptr input. | ||
133 | // So just call it a day here. This counts as an error. | ||
134 | initialized = true; | ||
135 | had_error = true; | ||
136 | return false; | ||
137 | } | ||
138 | |||
139 | void* handle = dlopen(native_bridge_library_filename, RTLD_LAZY); | ||
66 | if (handle != nullptr) { | 140 | if (handle != nullptr) { |
67 | callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, | 141 | callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, |
68 | kNativeBridgeInterfaceSymbol)); | 142 | kNativeBridgeInterfaceSymbol)); |
@@ -72,8 +146,13 @@ static bool NativeBridgeInitialize() { | |||
72 | } | 146 | } |
73 | 147 | ||
74 | if (!available) { | 148 | if (!available) { |
149 | // If we fail initialization, this counts as an error. | ||
150 | had_error = true; | ||
75 | dlclose(handle); | 151 | dlclose(handle); |
76 | } | 152 | } |
153 | } else { | ||
154 | // Being unable to open the library counts as an error. | ||
155 | had_error = true; | ||
77 | } | 156 | } |
78 | 157 | ||
79 | initialized = true; | 158 | initialized = true; |
@@ -81,6 +160,14 @@ static bool NativeBridgeInitialize() { | |||
81 | return available; | 160 | return available; |
82 | } | 161 | } |
83 | 162 | ||
163 | bool NativeBridgeError() { | ||
164 | return had_error; | ||
165 | } | ||
166 | |||
167 | bool NativeBridgeAvailable() { | ||
168 | return NativeBridgeInitialize(); | ||
169 | } | ||
170 | |||
84 | void* NativeBridgeLoadLibrary(const char* libpath, int flag) { | 171 | void* NativeBridgeLoadLibrary(const char* libpath, int flag) { |
85 | if (NativeBridgeInitialize()) { | 172 | if (NativeBridgeInitialize()) { |
86 | return callbacks->loadLibrary(libpath, flag); | 173 | return callbacks->loadLibrary(libpath, flag); |
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk new file mode 100644 index 000000000..f58b8f7a9 --- /dev/null +++ b/libnativebridge/tests/Android.mk | |||
@@ -0,0 +1,33 @@ | |||
1 | # Build the unit tests. | ||
2 | LOCAL_PATH := $(call my-dir) | ||
3 | include $(CLEAR_VARS) | ||
4 | |||
5 | # Build the unit tests. | ||
6 | test_src_files := \ | ||
7 | InvalidCharsNativeBridge_test.cpp \ | ||
8 | ReSetupNativeBridge_test.cpp \ | ||
9 | UnavailableNativeBridge_test.cpp \ | ||
10 | ValidNameNativeBridge_test.cpp | ||
11 | |||
12 | shared_libraries := \ | ||
13 | libnativebridge | ||
14 | |||
15 | $(foreach file,$(test_src_files), \ | ||
16 | $(eval include $(CLEAR_VARS)) \ | ||
17 | $(eval LOCAL_CLANG := true) \ | ||
18 | $(eval LOCAL_CPPFLAGS := -std=gnu++11) \ | ||
19 | $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ | ||
20 | $(eval LOCAL_SRC_FILES := $(file)) \ | ||
21 | $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ | ||
22 | $(eval include $(BUILD_NATIVE_TEST)) \ | ||
23 | ) | ||
24 | |||
25 | $(foreach file,$(test_src_files), \ | ||
26 | $(eval include $(CLEAR_VARS)) \ | ||
27 | $(eval LOCAL_CLANG := true) \ | ||
28 | $(eval LOCAL_CPPFLAGS := -std=gnu++11) \ | ||
29 | $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ | ||
30 | $(eval LOCAL_SRC_FILES := $(file)) \ | ||
31 | $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ | ||
32 | $(eval include $(BUILD_HOST_NATIVE_TEST)) \ | ||
33 | ) | ||
diff --git a/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp b/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp new file mode 100644 index 000000000..f37e9c158 --- /dev/null +++ b/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "NativeBridgeTest.h" | ||
18 | |||
19 | namespace android { | ||
20 | |||
21 | static const char* kTestName = "../librandom$@-bridge_not.existing.so"; | ||
22 | |||
23 | TEST_F(NativeBridgeTest, InvalidChars) { | ||
24 | // Do one test actually calling setup. | ||
25 | EXPECT_EQ(false, NativeBridgeError()); | ||
26 | SetupNativeBridge(kTestName, nullptr); | ||
27 | // This should lead to an error for invalid characters. | ||
28 | EXPECT_EQ(true, NativeBridgeError()); | ||
29 | |||
30 | // Further tests need to use NativeBridgeNameAcceptable, as the error | ||
31 | // state can't be changed back. | ||
32 | EXPECT_EQ(false, NativeBridgeNameAcceptable(".")); | ||
33 | EXPECT_EQ(false, NativeBridgeNameAcceptable("..")); | ||
34 | EXPECT_EQ(false, NativeBridgeNameAcceptable("_")); | ||
35 | EXPECT_EQ(false, NativeBridgeNameAcceptable("-")); | ||
36 | EXPECT_EQ(false, NativeBridgeNameAcceptable("lib@.so")); | ||
37 | EXPECT_EQ(false, NativeBridgeNameAcceptable("lib$.so")); | ||
38 | } | ||
39 | |||
40 | } // namespace android | ||
diff --git a/libnativebridge/tests/NativeBridgeTest.h b/libnativebridge/tests/NativeBridgeTest.h new file mode 100644 index 000000000..0d731cb11 --- /dev/null +++ b/libnativebridge/tests/NativeBridgeTest.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef NATIVE_BRIDGE_TEST_H_ | ||
18 | #define NATIVE_BRIDGE_TEST_H_ | ||
19 | |||
20 | #define LOG_TAG "NativeBridge_test" | ||
21 | |||
22 | #include <nativebridge/native_bridge.h> | ||
23 | #include <gtest/gtest.h> | ||
24 | |||
25 | namespace android { | ||
26 | |||
27 | class NativeBridgeTest : public testing::Test { | ||
28 | }; | ||
29 | |||
30 | }; // namespace android | ||
31 | |||
32 | #endif // NATIVE_BRIDGE_H_ | ||
33 | |||
diff --git a/libnativebridge/tests/ReSetupNativeBridge_test.cpp b/libnativebridge/tests/ReSetupNativeBridge_test.cpp new file mode 100644 index 000000000..ef5bfceb8 --- /dev/null +++ b/libnativebridge/tests/ReSetupNativeBridge_test.cpp | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "NativeBridgeTest.h" | ||
18 | |||
19 | namespace android { | ||
20 | |||
21 | static const char* kTestName = "librandom-bridge_not.existing.so"; | ||
22 | |||
23 | TEST_F(NativeBridgeTest, ReSetup) { | ||
24 | EXPECT_EQ(false, NativeBridgeError()); | ||
25 | SetupNativeBridge(kTestName, nullptr); | ||
26 | EXPECT_EQ(false, NativeBridgeError()); | ||
27 | SetupNativeBridge(kTestName, nullptr); | ||
28 | // This should lead to an error for trying to re-setup a native bridge. | ||
29 | EXPECT_EQ(true, NativeBridgeError()); | ||
30 | } | ||
31 | |||
32 | } // namespace android | ||
diff --git a/libnativebridge/tests/UnavailableNativeBridge_test.cpp b/libnativebridge/tests/UnavailableNativeBridge_test.cpp new file mode 100644 index 000000000..27d12336c --- /dev/null +++ b/libnativebridge/tests/UnavailableNativeBridge_test.cpp | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "NativeBridgeTest.h" | ||
18 | |||
19 | namespace android { | ||
20 | |||
21 | TEST_F(NativeBridgeTest, NoNativeBridge) { | ||
22 | EXPECT_EQ(false, NativeBridgeAvailable()); | ||
23 | // This should lead to an error for trying to initialize a not-setup | ||
24 | // native bridge. | ||
25 | EXPECT_EQ(true, NativeBridgeError()); | ||
26 | } | ||
27 | |||
28 | } // namespace android | ||
diff --git a/libnativebridge/tests/ValidNameNativeBridge_test.cpp b/libnativebridge/tests/ValidNameNativeBridge_test.cpp new file mode 100644 index 000000000..3e019232d --- /dev/null +++ b/libnativebridge/tests/ValidNameNativeBridge_test.cpp | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <NativeBridgeTest.h> | ||
18 | |||
19 | namespace android { | ||
20 | |||
21 | static const char* kTestName = "librandom-bridge_not.existing.so"; | ||
22 | |||
23 | TEST_F(NativeBridgeTest, ValidName) { | ||
24 | EXPECT_EQ(false, NativeBridgeError()); | ||
25 | SetupNativeBridge(kTestName, nullptr); | ||
26 | EXPECT_EQ(false, NativeBridgeError()); | ||
27 | EXPECT_EQ(false, NativeBridgeAvailable()); | ||
28 | // This should lead to an error for trying to initialize a not-existing | ||
29 | // native bridge. | ||
30 | EXPECT_EQ(true, NativeBridgeError()); | ||
31 | } | ||
32 | |||
33 | } // namespace android | ||