Skip to content

Commit f55c43c

Browse files
cynthiajoanCynthia Jiang
and
Cynthia Jiang
authored
add UseEmulator api to auth (#1437)
* add auth emulator support * fix ios number parse * update the documentation part * reduce lint warning * more lint warnings * code format * use environment to decide using emulator or not * fix a typo * add readme entry for FirebaseApp.GetApps() * update for review comment * add missing ` * make json request always do restrict json * add readme info * prepare for review * some minor tweak * code format * update review comments * update the unit test after request json change * remove platform logging v1 code * add useEmulator api * test with emulator * clean up for review * tweak for review * update with comments * put back necessary heartbeat blocks --------- Co-authored-by: Cynthia Jiang <cynthiajiang@google.com>
1 parent ca5cdee commit f55c43c

File tree

7 files changed

+73
-53
lines changed

7 files changed

+73
-53
lines changed

auth/src/android/auth_android.cc

+15-8
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,19 @@ void UpdateCurrentUser(AuthData* auth_data) {
188188
}
189189
}
190190

191+
void SetEmulatorJni(AuthData* auth_data, const char* host, uint32_t port) {
192+
JNIEnv* env = Env(auth_data);
193+
194+
jstring j_host = env->NewStringUTF(host);
195+
env->CallVoidMethod(AuthImpl(auth_data),
196+
auth::GetMethodId(auth::kUseEmulator), j_host, port);
197+
env->DeleteLocalRef(j_host);
198+
firebase::util::CheckAndClearJniExceptions(env);
199+
}
200+
191201
const char* const kEmulatorLocalHost = "10.0.2.2";
192202
const char* const kEmulatorPort = "9099";
193203
void CheckEmulator(AuthData* auth_data) {
194-
JNIEnv* env = Env(auth_data);
195-
196204
// Use emulator as long as this env variable is set, regardless its value.
197205
if (std::getenv("USE_AUTH_EMULATOR") == nullptr) {
198206
LogInfo("Using Auth Prod for testing.");
@@ -207,12 +215,7 @@ void CheckEmulator(AuthData* auth_data) {
207215
if (std::getenv("AUTH_EMULATOR_PORT") != nullptr) {
208216
port = std::stoi(std::getenv("AUTH_EMULATOR_PORT"));
209217
}
210-
211-
jstring j_host = env->NewStringUTF(kEmulatorLocalHost);
212-
env->CallVoidMethod(AuthImpl(auth_data),
213-
auth::GetMethodId(auth::kUseEmulator), j_host, port);
214-
env->DeleteLocalRef(j_host);
215-
firebase::util::CheckAndClearJniExceptions(env);
218+
SetEmulatorJni(auth_data, kEmulatorLocalHost, port);
216219
}
217220

218221
// Release cached Java classes.
@@ -828,6 +831,10 @@ Future<void> Auth::SendPasswordResetEmail(const char* email) {
828831
return MakeFuture(&futures, handle);
829832
}
830833

834+
void Auth::UseEmulator(std::string host, uint32_t port) {
835+
SetEmulatorJni(auth_data_, host.c_str(), port);
836+
}
837+
831838
// Not implemented for Android.
832839
void EnableTokenAutoRefresh(AuthData* auth_data) {}
833840
void DisableTokenAutoRefresh(AuthData* auth_data) {}

auth/src/desktop/auth_desktop.cc

+8
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,14 @@ void Auth::UseAppLanguage() {
715715
auth_impl->language_code.assign(empty_string);
716716
}
717717

718+
void Auth::UseEmulator(std::string host, uint32_t port) {
719+
auto auth_impl = static_cast<AuthImpl*>(auth_data_->auth_impl);
720+
auth_impl->assigned_emulator_url = "";
721+
auth_impl->assigned_emulator_url.append(host);
722+
auth_impl->assigned_emulator_url.append(":");
723+
auth_impl->assigned_emulator_url.append(std::to_string(port));
724+
}
725+
718726
void InitializeTokenRefresher(AuthData* auth_data) {
719727
auto auth_impl = static_cast<AuthImpl*>(auth_data->auth_impl);
720728
auth_impl->token_refresh_thread.Initialize(auth_data);

auth/src/desktop/auth_desktop.h

+2
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ struct AuthImpl {
188188
// The current user language code. This can be set to the app’s current
189189
// language by calling SetLanguageCode.
190190
std::string language_code;
191+
192+
std::string assigned_emulator_url;
191193
};
192194

193195
// Constant, describing how often we automatically fetch a new auth token.

auth/src/desktop/rpcs/auth_request.cc

+25-41
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "app/src/heartbeat/heartbeat_controller_desktop.h"
2424
#include "app/src/include/firebase/app.h"
2525
#include "app/src/include/firebase/internal/mutex.h"
26+
#include "auth/src/desktop/auth_desktop.h"
27+
#include "auth/src/include/firebase/auth.h"
2628
#include "firebase/log.h"
2729

2830
namespace firebase {
@@ -33,39 +35,9 @@ const char* kHeaderFirebaseLocale = "X-Firebase-Locale";
3335

3436
AuthRequest::AuthRequest(::firebase::App& app, const char* schema,
3537
bool deliver_heartbeat)
36-
: RequestJson(schema) {
37-
// The user agent strings are cached in static variables here to avoid
38-
// dependencies upon other parts of this library. This complication is due to
39-
// the way the tests are currently configured where each library has minimal
40-
// dependencies.
38+
: RequestJson(schema), app(app) {
39+
CheckEnvEmulator();
4140

42-
CheckEmulator();
43-
static std::string auth_user_agent; // NOLINT
44-
static std::string extended_auth_user_agent; // NOLINT
45-
static Mutex* user_agent_mutex = new Mutex();
46-
MutexLock lock(*user_agent_mutex);
47-
if (auth_user_agent.empty()) {
48-
std::string sdk;
49-
std::string version;
50-
app_common::GetOuterMostSdkAndVersion(&sdk, &version);
51-
// Set the user agent similar to the iOS SDK. Format:
52-
// FirebaseAuth.<platform>/<sdk_version>
53-
assert(!(sdk.empty() || version.empty()));
54-
std::string sdk_type(sdk.substr(sizeof(FIREBASE_USER_AGENT_PREFIX) - 1));
55-
auth_user_agent = std::string("FirebaseAuth.") + sdk_type + "/" + version;
56-
// Generage the extended header to set the format specified by b/28531026
57-
// and b/64693042 to include the platform and framework.
58-
// <environment>/<sdk_implementation>/<sdk_version>/<framework>
59-
// where <framework> is '(FirebaseCore|FirebaseUI)'.
60-
extended_auth_user_agent = std::string(app_common::kOperatingSystem) + "/" +
61-
sdk + "/" + version + "/" + "FirebaseCore-" +
62-
sdk_type;
63-
}
64-
// TODO(b/244643516): Remove the User-Agent and X-Client-Version headers.
65-
if (!auth_user_agent.empty()) {
66-
add_header("User-Agent", auth_user_agent.c_str());
67-
add_header("X-Client-Version", extended_auth_user_agent.c_str());
68-
}
6941
if (deliver_heartbeat) {
7042
std::shared_ptr<heartbeat::HeartbeatController> heartbeat_controller =
7143
app.GetHeartbeatController();
@@ -81,6 +53,17 @@ AuthRequest::AuthRequest(::firebase::App& app, const char* schema,
8153
}
8254

8355
std::string AuthRequest::GetUrl() {
56+
std::string emulator_url;
57+
Auth* auth_ptr = Auth::GetAuth(&app);
58+
std::string assigned_emulator_url =
59+
static_cast<AuthImpl*>(auth_ptr->auth_data_->auth_impl)
60+
->assigned_emulator_url;
61+
if (assigned_emulator_url.empty()) {
62+
emulator_url = env_emulator_url;
63+
} else {
64+
emulator_url = assigned_emulator_url;
65+
}
66+
8467
if (emulator_url.empty()) {
8568
std::string url(kHttps);
8669
url += kServerURL;
@@ -94,25 +77,26 @@ std::string AuthRequest::GetUrl() {
9477
}
9578
}
9679

97-
void AuthRequest::CheckEmulator() {
98-
if (!emulator_url.empty()) {
99-
LogInfo("Emulator Url already set: %s", emulator_url.c_str());
80+
void AuthRequest::CheckEnvEmulator() {
81+
if (!env_emulator_url.empty()) {
82+
LogInfo("Environment Emulator Url already set: %s",
83+
env_emulator_url.c_str());
10084
return;
10185
}
86+
10287
// Use emulator as long as this env variable is set, regardless its value.
10388
if (std::getenv("USE_AUTH_EMULATOR") == nullptr) {
104-
LogInfo("Using Auth Prod for testing.");
89+
LogInfo("USE_AUTH_EMULATOR not set.");
10590
return;
10691
}
107-
LogInfo("Using Auth Emulator.");
108-
emulator_url.append(kEmulatorLocalHost);
109-
emulator_url.append(":");
92+
env_emulator_url.append(kEmulatorLocalHost);
93+
env_emulator_url.append(":");
11094
// Use AUTH_EMULATOR_PORT if it is set to non empty string,
11195
// otherwise use the default port.
11296
if (std::getenv("AUTH_EMULATOR_PORT") == nullptr) {
113-
emulator_url.append(kEmulatorPort);
97+
env_emulator_url.append(kEmulatorPort);
11498
} else {
115-
emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
99+
env_emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
116100
}
117101
}
118102

auth/src/desktop/rpcs/auth_request.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ class AuthRequest
5555
std::string GetUrl();
5656

5757
private:
58-
void CheckEmulator();
59-
std::string emulator_url;
58+
void CheckEnvEmulator();
59+
std::string env_emulator_url;
60+
::firebase::App& app;
6061
};
6162

6263
} // namespace auth

auth/src/include/firebase/auth.h

+10
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct AuthData;
4545
class AuthStateListener;
4646
class IdTokenListener;
4747
class PhoneAuthProvider;
48+
class AuthRequest;
4849
struct AuthCompletionHandle;
4950
struct AuthResultCompletionHandle;
5051
class FederatedAuthProvider;
@@ -631,6 +632,14 @@ class Auth {
631632
void RemoveIdTokenListener(IdTokenListener* listener);
632633
#endif // not SWIG
633634

635+
#if !defined(DOXYGEN) && !defined(SWIG)
636+
///
637+
/// Modify this Auth instance to communicate with the Firebase Authentication
638+
/// emulator.
639+
///
640+
void UseEmulator(std::string host, uint32_t port);
641+
#endif //! defined(DOXYGEN), to hide the api from public documentation.
642+
634643
/// Gets the App this auth object is connected to.
635644
App& app();
636645

@@ -653,6 +662,7 @@ class Auth {
653662
/// @cond FIREBASE_APP_INTERNAL
654663
friend class ::firebase::App;
655664
friend class ::firebase::auth::PhoneAuthProvider;
665+
friend class ::firebase::auth::AuthRequest;
656666
friend class IdTokenRefreshListener;
657667
friend class IdTokenRefreshThread;
658668
friend class UserDataPersist;

auth/src/ios/auth_ios.mm

+10-2
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ void UpdateCurrentUser(AuthData *auth_data) {
157157
SetUserImpl(auth_data, user);
158158
}
159159

160+
void SetEmulatorJni(AuthData *auth_data, const char *host, uint32_t port) {
161+
NSUInteger ns_port = port;
162+
[AuthImpl(auth_data) useEmulatorWithHost:@(host) port:ns_port];
163+
}
164+
160165
void CheckEmulator(AuthData *auth_data) {
161166
// Use emulator as long as this env variable is set, regardless its value.
162167
if (std::getenv("USE_AUTH_EMULATOR") == nullptr) {
@@ -171,8 +176,7 @@ void CheckEmulator(AuthData *auth_data) {
171176
port = std::stoi(std::getenv("AUTH_EMULATOR_PORT"));
172177
}
173178

174-
NSUInteger ns_port = port;
175-
[AuthImpl(auth_data) useEmulatorWithHost:@(kEmulatorLocalHost) port:ns_port];
179+
SetEmulatorJni(auth_data, kEmulatorLocalHost, port);
176180
}
177181

178182
// Platform-specific method to initialize AuthData.
@@ -699,6 +703,10 @@ void SignInResultCallback(FIRAuthDataResult *_Nullable auth_result, NSError *_Nu
699703
return MakeFuture(&futures, handle);
700704
}
701705

706+
void Auth::UseEmulator(std::string host, uint32_t port) {
707+
SetEmulatorJni(auth_data_, host.c_str(), port);
708+
}
709+
702710
// Remap iOS SDK errors reported by the UIDelegate. While these errors seem like
703711
// user interaction errors, they are actually caused by bad provider ids.
704712
NSError *RemapBadProviderIDErrors(NSError *_Nonnull error) {

0 commit comments

Comments
 (0)