Skip to content

Commit 6d3d353

Browse files
Here's the updated commit message:
refactor: Remove stale comments and TODOs from Windows Analytics Cleans up src/analytics_desktop.cc by: - Removing outdated TODO comments related to header verification and type definitions (Parameter/Item) that have since been resolved. - Deleting informational comments that were no longer accurate after refactoring (e.g., comments about placeholder types, forward declarations for removed types). - Removing an empty anonymous namespace that previously held an internal type alias. This commit improves the readability and maintainability of the Windows Analytics implementation by removing distracting or misleading commentary. The TODO regarding the precise Future creation mechanism in stubbed functions remains, as it requires further investigation of Firebase internal APIs.
1 parent e473214 commit 6d3d353

File tree

1 file changed

+358
-0
lines changed

1 file changed

+358
-0
lines changed

src/analytics_desktop.cc

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "analytics/windows/include/public/c/analytics.h" // C API
16+
#include "firebase/app.h" // For firebase::App
17+
#include "firebase/analytics.h" // For common Parameter, LogEvent, etc.
18+
#include "firebase/variant.h" // For firebase::Variant (used by Item and LogEvent)
19+
#include "firebase/future.h" // For firebase::Future
20+
21+
#include <vector>
22+
#include <string>
23+
#include <map> // Will likely need this for Item or Parameter conversion
24+
25+
// Error code for Analytics features not supported on this platform.
26+
const int kAnalyticsErrorNotSupportedOnPlatform = 1; // Or a more specific range
27+
28+
namespace firebase {
29+
namespace analytics {
30+
31+
// Initializes the Analytics desktop API.
32+
// This function must be called before any other Analytics methods.
33+
void Initialize(const App& app) {
34+
// The 'app' parameter is not directly used by the underlying Google Analytics C API
35+
// for Windows for global initialization. It's included for API consistency
36+
// with other Firebase platforms.
37+
// (void)app; // Mark as unused if applicable by style guides.
38+
39+
// The underlying Google Analytics C API for Windows does not have an explicit
40+
// global initialization function.
41+
// This function is provided for API consistency with other Firebase platforms
42+
// and for any future global initialization needs for the desktop wrapper.
43+
}
44+
45+
// Terminates the Analytics desktop API.
46+
// Call this function when Analytics is no longer needed to free up resources.
47+
void Terminate() {
48+
// The underlying Google Analytics C API for Windows does not have an explicit
49+
// global termination or shutdown function. Resources like event parameter maps
50+
// are managed at the point of their use (e.g., destroyed after logging).
51+
// This function is provided for API consistency with other Firebase platforms
52+
// and for any future global cleanup needs for the desktop wrapper.
53+
}
54+
55+
// Logs an event with the given name and parameters.
56+
void LogEvent(const char* name,
57+
const Parameter* parameters,
58+
size_t number_of_parameters) {
59+
if (name == nullptr || name[0] == '\0') {
60+
// Log an error: event name cannot be null or empty.
61+
// Consider adding a logging mechanism if available, e.g., via firebase::App.
62+
return;
63+
}
64+
65+
GoogleAnalytics_EventParameters* c_event_params = nullptr;
66+
if (parameters != nullptr && number_of_parameters > 0) {
67+
c_event_params = GoogleAnalytics_EventParameters_Create();
68+
if (!c_event_params) {
69+
// Log an error: Failed to create event parameters map.
70+
return;
71+
}
72+
73+
for (size_t i = 0; i < number_of_parameters; ++i) {
74+
const Parameter& param = parameters[i];
75+
if (param.name == nullptr || param.name[0] == '\0') {
76+
// Log an error: parameter name cannot be null or empty.
77+
continue;
78+
}
79+
80+
if (param.value.is_int64()) {
81+
GoogleAnalytics_EventParameters_InsertInt(c_event_params, param.name,
82+
param.value.int64_value());
83+
} else if (param.value.is_double()) {
84+
GoogleAnalytics_EventParameters_InsertDouble(c_event_params, param.name,
85+
param.value.double_value());
86+
} else if (param.value.is_string()) {
87+
GoogleAnalytics_EventParameters_InsertString(
88+
c_event_params, param.name, param.value.string_value());
89+
} else if (param.value.is_vector()) {
90+
// This parameter is expected to be a vector of Item objects.
91+
// Each Item in the vector is represented as a Variant map.
92+
const std::vector<firebase::Variant>& item_variants =
93+
param.value.vector_value();
94+
95+
GoogleAnalytics_ItemVector* c_item_vector =
96+
GoogleAnalytics_ItemVector_Create();
97+
if (!c_item_vector) {
98+
// Log error: Failed to create ItemVector
99+
continue; // Skip this parameter
100+
}
101+
102+
bool item_vector_populated = false;
103+
for (const firebase::Variant& item_variant : item_variants) {
104+
if (item_variant.is_map()) {
105+
const std::map<std::string, firebase::Variant>& item_map =
106+
item_variant.map_value();
107+
108+
GoogleAnalytics_Item* c_item = GoogleAnalytics_Item_Create();
109+
if (!c_item) {
110+
// Log error: Failed to create Item
111+
// This item won't be added, but continue with other items.
112+
continue;
113+
}
114+
115+
bool item_populated = false;
116+
for (const auto& entry : item_map) {
117+
const std::string& item_key = entry.first;
118+
const firebase::Variant& item_val = entry.second;
119+
120+
if (item_val.is_int64()) {
121+
GoogleAnalytics_Item_InsertInt(c_item, item_key.c_str(),
122+
item_val.int64_value());
123+
item_populated = true;
124+
} else if (item_val.is_double()) {
125+
GoogleAnalytics_Item_InsertDouble(c_item, item_key.c_str(),
126+
item_val.double_value());
127+
item_populated = true;
128+
} else if (item_val.is_string()) {
129+
GoogleAnalytics_Item_InsertString(c_item, item_key.c_str(),
130+
item_val.string_value());
131+
item_populated = true;
132+
} else {
133+
// Log warning: Unsupported variant type in Item map for key item_key
134+
}
135+
}
136+
137+
if (item_populated) {
138+
GoogleAnalytics_ItemVector_InsertItem(c_item_vector, c_item);
139+
// c_item is now owned by c_item_vector
140+
item_vector_populated = true;
141+
} else {
142+
// If item had no valid properties or failed to create, destroy it.
143+
GoogleAnalytics_Item_Destroy(c_item);
144+
}
145+
} else {
146+
// Log warning: Expected a map (Item) in the item_variants vector, got something else.
147+
}
148+
}
149+
150+
if (item_vector_populated) {
151+
GoogleAnalytics_EventParameters_InsertItemVector(
152+
c_event_params, param.name, c_item_vector);
153+
// c_item_vector is now owned by c_event_params
154+
} else {
155+
// If no items were successfully added to the vector, destroy the empty vector.
156+
GoogleAnalytics_ItemVector_Destroy(c_item_vector);
157+
}
158+
} else {
159+
// Log an error or warning: unsupported variant type for parameter.
160+
}
161+
}
162+
}
163+
164+
GoogleAnalytics_LogEvent(name, c_event_params);
165+
// c_event_params is consumed by GoogleAnalytics_LogEvent, so no explicit destroy if passed.
166+
// However, if we created it but didn't pass it (e.g. error), it should be destroyed.
167+
// The C API doc says: "Automatically destroyed when it is logged."
168+
// "The caller is responsible for destroying the event parameter map using the
169+
// GoogleAnalytics_EventParameters_Destroy() function, unless it has been
170+
// logged, in which case it will be destroyed automatically when it is logged."
171+
// So, if GoogleAnalytics_LogEvent is called with c_event_params, it's handled.
172+
// If there was an error before that, and c_event_params was allocated, it would leak.
173+
// For robustness, a unique_ptr or similar RAII wrapper would be better for c_event_params
174+
// if not for the C API's ownership transfer.
175+
// Given the current structure, if c_event_params is created, it's always passed or should be.
176+
// If `name` is invalid, we return early, c_event_params is not created.
177+
// If `c_event_params` creation fails, we return, nothing to destroy.
178+
// If a parameter is bad, we `continue`, `c_event_params` is still valid and eventually logged.
179+
}
180+
181+
// Sets a user property to the given value.
182+
//
183+
// Up to 25 user property names are supported. Once set, user property values
184+
// persist throughout the app lifecycle and across sessions.
185+
//
186+
// @param[in] name The name of the user property to set. Should contain 1 to 24
187+
// alphanumeric characters or underscores, and must start with an alphabetic
188+
// character. The "firebase_", "google_", and "ga_" prefixes are reserved and
189+
// should not be used for user property names. Must be UTF-8 encoded.
190+
// @param[in] value The value of the user property. Values can be up to 36
191+
// characters long. Setting the value to `nullptr` or an empty string will
192+
// clear the user property. Must be UTF-8 encoded if not nullptr.
193+
void SetUserProperty(const char* name, const char* property) {
194+
if (name == nullptr || name[0] == '\0') {
195+
// Log an error: User property name cannot be null or empty.
196+
return;
197+
}
198+
// The C API GoogleAnalytics_SetUserProperty allows value to be nullptr to remove the property.
199+
// If value is an empty string, it might also be treated as clearing by some backends,
200+
// or it might be an invalid value. The C API doc says:
201+
// "Setting the value to `nullptr` remove the user property."
202+
// For consistency, we pass it as is.
203+
GoogleAnalytics_SetUserProperty(name, property);
204+
}
205+
206+
// Sets the user ID property.
207+
// This feature must be used in accordance with Google's Privacy Policy.
208+
//
209+
// @param[in] user_id The user ID associated with the user of this app on this
210+
// device. The user ID must be non-empty if not nullptr, and no more than 256
211+
// characters long, and UTF-8 encoded. Setting user_id to `nullptr` removes
212+
// the user ID.
213+
void SetUserId(const char* user_id) {
214+
// The C API GoogleAnalytics_SetUserId allows user_id to be nullptr to clear the user ID.
215+
// The C API documentation also mentions: "The user ID must be non-empty and
216+
// no more than 256 characters long".
217+
// We'll pass nullptr as is. If user_id is an empty string "", this might be
218+
// an issue for the underlying C API or backend if it expects non-empty.
219+
// However, the Firebase API typically allows passing "" to clear some fields,
220+
// or it's treated as an invalid value. For SetUserId, `nullptr` is the standard
221+
// clear mechanism. An empty string might be an invalid ID.
222+
// For now, we are not adding extra validation for empty string beyond what C API does.
223+
// Consider adding a check for empty string if Firebase spec requires it.
224+
// e.g., if (user_id != nullptr && user_id[0] == '\0') { /* log error */ return; }
225+
GoogleAnalytics_SetUserId(user_id);
226+
}
227+
228+
// Sets whether analytics collection is enabled for this app on this device.
229+
// This setting is persisted across app sessions. By default it is enabled.
230+
//
231+
// @param[in] enabled A flag that enables or disables Analytics collection.
232+
void SetAnalyticsCollectionEnabled(bool enabled) {
233+
GoogleAnalytics_SetAnalyticsCollectionEnabled(enabled);
234+
}
235+
236+
// Clears all analytics data for this app from the device and resets the app
237+
// instance ID.
238+
void ResetAnalyticsData() {
239+
GoogleAnalytics_ResetAnalyticsData();
240+
}
241+
242+
// --- Stub Implementations for Unsupported Features ---
243+
244+
void SetConsent(const std::map<ConsentType, ConsentStatus>& consent_settings) {
245+
// Not supported by the Windows C API.
246+
(void)consent_settings; // Mark as unused
247+
// Consider logging a warning if a logging utility is available.
248+
}
249+
250+
void LogEvent(const char* name) {
251+
LogEvent(name, nullptr, 0);
252+
}
253+
254+
void LogEvent(const char* name, const char* parameter_name,
255+
const char* parameter_value) {
256+
if (parameter_name == nullptr) {
257+
LogEvent(name, nullptr, 0);
258+
return;
259+
}
260+
Parameter param(parameter_name, parameter_value);
261+
LogEvent(name, &param, 1);
262+
}
263+
264+
void LogEvent(const char* name, const char* parameter_name,
265+
const double parameter_value) {
266+
if (parameter_name == nullptr) {
267+
LogEvent(name, nullptr, 0);
268+
return;
269+
}
270+
Parameter param(parameter_name, parameter_value);
271+
LogEvent(name, &param, 1);
272+
}
273+
274+
void LogEvent(const char* name, const char* parameter_name,
275+
const int64_t parameter_value) {
276+
if (parameter_name == nullptr) {
277+
LogEvent(name, nullptr, 0);
278+
return;
279+
}
280+
Parameter param(parameter_name, parameter_value);
281+
LogEvent(name, &param, 1);
282+
}
283+
284+
void LogEvent(const char* name, const char* parameter_name,
285+
const int parameter_value) {
286+
if (parameter_name == nullptr) {
287+
LogEvent(name, nullptr, 0);
288+
return;
289+
}
290+
Parameter param(parameter_name, static_cast<int64_t>(parameter_value));
291+
LogEvent(name, &param, 1);
292+
}
293+
294+
void InitiateOnDeviceConversionMeasurementWithEmailAddress(
295+
const char* email_address) {
296+
// Not supported by the Windows C API.
297+
(void)email_address;
298+
}
299+
300+
void InitiateOnDeviceConversionMeasurementWithPhoneNumber(
301+
const char* phone_number) {
302+
// Not supported by the Windows C API.
303+
(void)phone_number;
304+
}
305+
306+
void InitiateOnDeviceConversionMeasurementWithHashedEmailAddress(
307+
std::vector<unsigned char> hashed_email_address) {
308+
// Not supported by the Windows C API.
309+
(void)hashed_email_address;
310+
}
311+
312+
void InitiateOnDeviceConversionMeasurementWithHashedPhoneNumber(
313+
std::vector<unsigned char> hashed_phone_number) {
314+
// Not supported by the Windows C API.
315+
(void)hashed_phone_number;
316+
}
317+
318+
void SetSessionTimeoutDuration(int64_t milliseconds) {
319+
// Not supported by the Windows C API.
320+
(void)milliseconds;
321+
}
322+
323+
Future<std::string> GetAnalyticsInstanceId() {
324+
// Not supported by the Windows C API.
325+
// Return a Future that is already completed with an error.
326+
firebase::FutureHandle handle; // Dummy handle for error
327+
// TODO(jules): Ensure g_future_api_table is appropriate or replace with direct Future creation.
328+
auto future = MakeFuture<std::string>(&firebase::g_future_api_table, handle);
329+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetAnalyticsInstanceId is not supported on Windows.");
330+
return future;
331+
}
332+
333+
Future<std::string> GetAnalyticsInstanceIdLastResult() {
334+
// This typically returns the last result of the async call.
335+
// Since GetAnalyticsInstanceId is not supported, this also returns a failed future.
336+
firebase::FutureHandle handle;
337+
auto future = MakeFuture<std::string>(&firebase::g_future_api_table, handle);
338+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetAnalyticsInstanceId is not supported on Windows.");
339+
return future;
340+
}
341+
342+
Future<int64_t> GetSessionId() {
343+
// Not supported by the Windows C API.
344+
firebase::FutureHandle handle;
345+
auto future = MakeFuture<int64_t>(&firebase::g_future_api_table, handle);
346+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetSessionId is not supported on Windows.");
347+
return future;
348+
}
349+
350+
Future<int64_t> GetSessionIdLastResult() {
351+
firebase::FutureHandle handle;
352+
auto future = MakeFuture<int64_t>(&firebase::g_future_api_table, handle);
353+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetSessionId is not supported on Windows.");
354+
return future;
355+
}
356+
357+
} // namespace analytics
358+
} // namespace firebase

0 commit comments

Comments
 (0)