Skip to content

Commit d4cd930

Browse files
authored
Merge 872764d into 52db94f
2 parents 52db94f + 872764d commit d4cd930

17 files changed

+564
-69
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ __pycache__/
1717

1818
### IDE generated files
1919
.vscode/
20+
**/.vs/
2021

2122
# Unencrypted secret files
2223
google-services.json

analytics/generate_windows_stubs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def generate_function_pointers(dll_file_path, header_file_path, output_h_path, o
262262
)
263263
parser.add_argument(
264264
"--windows_dll",
265-
default = os.path.join(os.path.dirname(sys.argv[0]), "windows/analytics_win.dll"),
265+
default = os.path.join(os.path.dirname(sys.argv[0]), "windows/google_analytics.dll"),
266266
help="Path to the DLL file to calculate a hash."
267267
)
268268
parser.add_argument(

analytics/integration_test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ else()
211211
)
212212
elseif(MSVC)
213213
set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32)
214-
set(ANALYTICS_WINDOWS_DLL "${FIREBASE_CPP_SDK_DIR}/analytics/windows/analytics_win.dll")
214+
set(ANALYTICS_WINDOWS_DLL "${FIREBASE_CPP_SDK_DIR}/analytics/windows/google_analytics.dll")
215215

216216
# For Windows, check if the Analytics DLL exists, and copy it in if so.
217217
if (EXISTS "${ANALYTICS_WINDOWS_DLL}")

analytics/integration_test/src/integration_test.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
#include <inttypes.h>
1616

1717
#include <algorithm>
18+
#include <chrono>
1819
#include <cstdio>
1920
#include <cstdlib>
2021
#include <cstring>
2122
#include <ctime>
23+
#include <future>
2224

2325
#include "app_framework.h" // NOLINT
2426
#include "firebase/analytics.h"
@@ -242,6 +244,39 @@ TEST_F(FirebaseAnalyticsTest, TestSetProperties) {
242244
InitiateOnDeviceConversionMeasurementWithHashedPhoneNumber(hashed_phone);
243245
}
244246

247+
#if defined(_WIN32)
248+
TEST_F(FirebaseAnalyticsTest, TestSetLogCallback) {
249+
std::promise<void> finishedPromise;
250+
std::future<void> finished = finishedPromise.get_future();
251+
bool log_callback_called = false;
252+
253+
// Save the current log level, and set to verbose for this test.
254+
firebase::LogLevel current_log_level = firebase::GetLogLevel();
255+
firebase::SetLogLevel(firebase::LogLevel::kLogLevelVerbose);
256+
257+
firebase::analytics::SetLogCallback(
258+
[&](firebase::LogLevel log_level, const char* message) {
259+
log_callback_called = true;
260+
finishedPromise.set_value();
261+
});
262+
263+
// Pass kUnknown to trigger a warning log directly from the DLL (on
264+
// Windows),
265+
firebase::analytics::NotifyAppLifecycleChange(firebase::analytics::kUnknown);
266+
267+
if (finished.wait_for(std::chrono::seconds(10)) ==
268+
std::future_status::timeout) {
269+
ADD_FAILURE() << "Timed out waiting for log callback";
270+
} else {
271+
finished.get();
272+
}
273+
274+
EXPECT_TRUE(log_callback_called);
275+
firebase::analytics::SetLogCallback(nullptr);
276+
firebase::SetLogLevel(current_log_level);
277+
}
278+
#endif // defined(_WIN32)
279+
245280
TEST_F(FirebaseAnalyticsTest, TestLogEvents) {
246281
// Log an event with no parameters.
247282
firebase::analytics::LogEvent(firebase::analytics::kEventLogin);
@@ -259,6 +294,14 @@ TEST_F(FirebaseAnalyticsTest, TestLogEvents) {
259294
"spoon_welders");
260295
}
261296

297+
TEST_F(FirebaseAnalyticsTest, TestNotifyAppLifecycleChange) {
298+
// Can't confirm that these do anything but just run them all to ensure the
299+
// app doesn't crash.
300+
firebase::analytics::NotifyAppLifecycleChange(firebase::analytics::kUnknown);
301+
firebase::analytics::NotifyAppLifecycleChange(
302+
firebase::analytics::kTermination);
303+
}
304+
262305
TEST_F(FirebaseAnalyticsTest, TestLogEventWithMultipleParameters) {
263306
const firebase::analytics::Parameter kLevelUpParameters[] = {
264307
firebase::analytics::Parameter(firebase::analytics::kParameterLevel, 5),

analytics/src/analytics_android.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,12 @@ void ResetAnalyticsData() {
666666
util::CheckAndClearJniExceptions(env);
667667
}
668668

669+
// NO-OP in Android and iOS. Only used in Windows.
670+
void SetLogCallback(const LogCallback&) {}
671+
672+
// NO-OP in Android and iOS. Only used in Windows.
673+
void NotifyAppLifecycleChange(AppLifecycleState) {}
674+
669675
Future<std::string> GetAnalyticsInstanceId() {
670676
FIREBASE_ASSERT_RETURN(GetAnalyticsInstanceIdLastResult(),
671677
internal::IsInitialized());

analytics/src/analytics_desktop.cc

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include <future>
1516
#include <map>
17+
#include <mutex>
1618
#include <sstream>
1719
#include <string>
1820
#include <vector>
@@ -25,6 +27,7 @@
2527
#include "app/src/include/firebase/future.h"
2628
#include "app/src/include/firebase/variant.h"
2729
#include "app/src/log.h"
30+
#include "firebase/log.h"
2831

2932
#if defined(_WIN32)
3033
#include <windows.h>
@@ -36,14 +39,16 @@ namespace firebase {
3639
namespace analytics {
3740

3841
#if defined(_WIN32)
39-
#define ANALYTICS_DLL_FILENAME L"analytics_win.dll"
42+
#define ANALYTICS_DLL_FILENAME L"google_analytics.dll"
4043

4144
static HMODULE g_analytics_module = 0;
4245
#endif // defined(_WIN32)
4346

4447
// Future data for analytics.
4548
// This is initialized in `Initialize()` and cleaned up in `Terminate()`.
4649
static bool g_initialized = false;
50+
static LogCallback g_log_callback;
51+
static std::mutex g_log_callback_mutex;
4752
static int g_fake_instance_id = 0;
4853
static bool g_analytics_collection_enabled = true;
4954
static std::string g_app_id;
@@ -134,6 +139,10 @@ bool IsInitialized() { return g_initialized; }
134139
void Terminate() {
135140
#if defined(_WIN32)
136141
if (g_analytics_module) {
142+
// Make sure to notify the SDK that the analytics is being terminated to
143+
// upload any pending data.
144+
NotifyAppLifecycleChange(AppLifecycleState::kTermination);
145+
137146
FirebaseAnalytics_UnloadDynamicFunctions();
138147
FreeLibrary(g_analytics_module);
139148
g_analytics_module = 0;
@@ -386,6 +395,58 @@ void ResetAnalyticsData() {
386395
g_fake_instance_id++;
387396
}
388397

398+
LogLevel ConvertAnalyticsLogLevelToFirebaseLogLevel(
399+
GoogleAnalytics_LogLevel log_level) {
400+
switch (log_level) {
401+
case kDebug:
402+
return kLogLevelDebug;
403+
case kInfo:
404+
return kLogLevelInfo;
405+
case kWarning:
406+
return kLogLevelWarning;
407+
case kError:
408+
return kLogLevelError;
409+
default:
410+
return kLogLevelInfo;
411+
}
412+
}
413+
414+
415+
extern "C" void GoogleAnalyticsWrapperLogCallback(
416+
GoogleAnalytics_LogLevel log_level, const char* message) {
417+
LogCallback callback_to_call;
418+
419+
{
420+
std::lock_guard<std::mutex> lock(g_log_callback_mutex);
421+
callback_to_call = g_log_callback;
422+
}
423+
424+
if (callback_to_call) {
425+
LogLevel firebase_log_level =
426+
ConvertAnalyticsLogLevelToFirebaseLogLevel(log_level);
427+
callback_to_call(firebase_log_level, message);
428+
}
429+
}
430+
431+
// Allows the passing of a callback to be used when the SDK logs any
432+
// messages regarding its behavior. The callback must be thread-safe.
433+
void SetLogCallback(const LogCallback& callback) {
434+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
435+
// The C API does not support user data, so we must use a global variable.
436+
{
437+
std::lock_guard<std::mutex> lock(g_log_callback_mutex);
438+
g_log_callback = callback;
439+
}
440+
GoogleAnalytics_SetLogCallback(GoogleAnalyticsWrapperLogCallback);
441+
}
442+
443+
// Notify the Analytics SDK about the current state of the app's lifecycle.
444+
void NotifyAppLifecycleChange(AppLifecycleState state) {
445+
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
446+
GoogleAnalytics_NotifyAppLifecycleChange(
447+
static_cast<GoogleAnalytics_AppLifecycleState>(state));
448+
}
449+
389450
// Overloaded versions of LogEvent for convenience.
390451

391452
void LogEvent(const char* name) {

0 commit comments

Comments
 (0)