Skip to content

Commit

Permalink
[Heartbeat Logging] Migrate AppCheck from using FIRHeartbeatInfo to…
Browse files Browse the repository at this point in the history
… `FIRHeartbeatLogger` (#9530)

* Integrate AppCheck with FIRHeartbeatLogger

* Fix comment typo

* Fix CI

* [will revert] debug why HeartbeatLoggingTestUtils.podspec is linted?

* Revert "[will revert] debug why HeartbeatLoggingTestUtils.podspec is linted?"

This reverts commit 25a7987.

* Change visibility of shim class

* Fix CI

* [skip ci] Review
  • Loading branch information
ncooke3 committed Mar 30, 2022
1 parent 1a5399a commit 3d4b0f4
Show file tree
Hide file tree
Showing 20 changed files with 266 additions and 114 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/app_check.yml
Expand Up @@ -21,6 +21,9 @@ jobs:
strategy:
matrix:
target: [ios, tvos, macos]
# TODO(v9): Remove `env` after publishing `HeartbeatLoggingTestUtils`.
env:
POD_LIB_LINT_ONLY: 1
steps:
- uses: actions/checkout@v2
- name: Setup Bundler
Expand All @@ -34,6 +37,9 @@ jobs:
# Don't run on private repo unless it is a PR.
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'
runs-on: macos-11
# TODO(v9): Remove `env` after publishing `HeartbeatLoggingTestUtils`.
env:
POD_LIB_LINT_ONLY: 1
steps:
- uses: actions/checkout@v2
- name: Setup Bundler
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/core.yml
Expand Up @@ -23,6 +23,7 @@ jobs:
strategy:
matrix:
target: [ios, tvos, macos]
# TODO(v9): Remove `env` after publishing `HeartbeatLoggingTestUtils`.
env:
POD_LIB_LINT_ONLY: 1
steps:
Expand Down Expand Up @@ -54,6 +55,7 @@ jobs:
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'

runs-on: macos-11
# TODO(v9): Remove `env` after publishing `HeartbeatLoggingTestUtils`.
env:
POD_LIB_LINT_ONLY: 1
steps:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/core_extension.yml
Expand Up @@ -21,6 +21,7 @@ jobs:
strategy:
matrix:
target: [ios, tvos, macos]
# TODO(v9): Remove `env` after publishing `HeartbeatLoggingTestUtils`.
env:
POD_LIB_LINT_ONLY: 1
steps:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/core_internal.yml
Expand Up @@ -19,6 +19,7 @@ jobs:
strategy:
matrix:
target: [ios, tvos, macos]
# TODO(v9): Remove `env` after publishing `HeartbeatLoggingTestUtils`.
env:
POD_LIB_LINT_ONLY: 1
steps:
Expand Down Expand Up @@ -46,6 +47,7 @@ jobs:
# Don't run on private repo unless it is a PR.
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'
runs-on: macos-11
# TODO(v9): Remove `env` after publishing `HeartbeatLoggingTestUtils`.
env:
POD_LIB_LINT_ONLY: 1
steps:
Expand Down
42 changes: 24 additions & 18 deletions FirebaseAppCheck.podspec
Expand Up @@ -54,24 +54,30 @@ Pod::Spec.new do |s|
'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}"'
}

s.test_spec 'unit' do |unit_tests|
unit_tests.platforms = {
:ios => ios_deployment_target,
:osx => osx_deployment_target,
:tvos => tvos_deployment_target
}
unit_tests.source_files = [
base_dir + 'Tests/Unit/**/*.[mh]',
base_dir + 'Tests/Utils/**/*.[mh]',
'SharedTestUtilities/AppCheckFake/*',
'SharedTestUtilities/AppCheckBackoffWrapperFake/*',
'SharedTestUtilities/Date/*',
'SharedTestUtilities/URLSession/*',
]

unit_tests.resources = base_dir + 'Tests/Fixture/**/*'
unit_tests.dependency 'OCMock'
unit_tests.requires_app_host = true
# Using environment variable because of the dependency on the unpublished
# HeartbeatLoggingTestUtils.
# TODO(v9): Remove above comment and below conditional after publishing.
if ENV['POD_LIB_LINT_ONLY'] && ENV['POD_LIB_LINT_ONLY'] == '1' then
s.test_spec 'unit' do |unit_tests|
unit_tests.platforms = {
:ios => ios_deployment_target,
:osx => osx_deployment_target,
:tvos => tvos_deployment_target
}
unit_tests.source_files = [
base_dir + 'Tests/Unit/**/*.[mh]',
base_dir + 'Tests/Utils/**/*.[mh]',
'SharedTestUtilities/AppCheckFake/*',
'SharedTestUtilities/AppCheckBackoffWrapperFake/*',
'SharedTestUtilities/Date/*',
'SharedTestUtilities/URLSession/*',
]

unit_tests.resources = base_dir + 'Tests/Fixture/**/*'
unit_tests.dependency 'OCMock'
unit_tests.dependency 'HeartbeatLoggingTestUtils'
unit_tests.requires_app_host = true
end
end

s.test_spec 'integration' do |integration_tests|
Expand Down
Expand Up @@ -146,8 +146,8 @@ - (nullable instancetype)initWithApp:(FIRApp *)app {
FIRAppCheckAPIService *APIService =
[[FIRAppCheckAPIService alloc] initWithURLSession:URLSession
APIKey:app.options.APIKey
projectID:app.options.projectID
appID:app.options.googleAppID];
appID:app.options.googleAppID
heartbeatLogger:app.heartbeatLogger];

FIRAppAttestAPIService *appAttestAPIService =
[[FIRAppAttestAPIService alloc] initWithAPIService:APIService
Expand Down
13 changes: 11 additions & 2 deletions FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h
Expand Up @@ -20,6 +20,8 @@
@class GULURLSessionDataResponse;
@class FIRAppCheckToken;

@protocol FIRHeartbeatLoggerProtocol;

NS_ASSUME_NONNULL_BEGIN

@protocol FIRAppCheckAPIServiceProtocol <NSObject>
Expand All @@ -39,10 +41,17 @@ NS_ASSUME_NONNULL_BEGIN

@interface FIRAppCheckAPIService : NSObject <FIRAppCheckAPIServiceProtocol>

/**
* The default initializer.
* @param session The URL session used to make network requests.
* @param APIKey The Firebase project API key (see `FIROptions.APIKey`).
* @param appID The Firebase app ID (see `FIROptions.googleAppID`).
* @param heartbeatLogger The heartbeat logger used to populate heartbeat data in request headers.
*/
- (instancetype)initWithURLSession:(NSURLSession *)session
APIKey:(NSString *)APIKey
projectID:(NSString *)projectID
appID:(NSString *)appID;
appID:(NSString *)appID
heartbeatLogger:(id<FIRHeartbeatLoggerProtocol>)heartbeatLogger;

@end

Expand Down
22 changes: 9 additions & 13 deletions FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.m
Expand Up @@ -33,9 +33,7 @@
NS_ASSUME_NONNULL_BEGIN

static NSString *const kAPIKeyHeaderKey = @"X-Goog-Api-Key";
static NSString *const kHeartbeatKey = @"X-firebase-client-log-type";
static NSString *const kHeartbeatStorageTag = @"fire-app-check";
static NSString *const kUserAgentKey = @"X-firebase-client";
static NSString *const kHeartbeatKey = @"X-firebase-client";
static NSString *const kBundleIdKey = @"X-Ios-Bundle-Identifier";

static NSString *const kDefaultBaseURL = @"https://firebaseappcheck.googleapis.com/v1beta";
Expand All @@ -44,8 +42,8 @@ @interface FIRAppCheckAPIService ()

@property(nonatomic, readonly) NSURLSession *URLSession;
@property(nonatomic, readonly) NSString *APIKey;
@property(nonatomic, readonly) NSString *projectID;
@property(nonatomic, readonly) NSString *appID;
@property(nonatomic, readonly) id<FIRHeartbeatLoggerProtocol> heartbeatLogger;

@end

Expand All @@ -56,26 +54,26 @@ @implementation FIRAppCheckAPIService

- (instancetype)initWithURLSession:(NSURLSession *)session
APIKey:(NSString *)APIKey
projectID:(NSString *)projectID
appID:(NSString *)appID {
appID:(NSString *)appID
heartbeatLogger:(id<FIRHeartbeatLoggerProtocol>)heartbeatLogger {
return [self initWithURLSession:session
APIKey:APIKey
projectID:projectID
appID:appID
heartbeatLogger:heartbeatLogger
baseURL:kDefaultBaseURL];
}

- (instancetype)initWithURLSession:(NSURLSession *)session
APIKey:(NSString *)APIKey
projectID:(NSString *)projectID
appID:(NSString *)appID
heartbeatLogger:(id<FIRHeartbeatLoggerProtocol>)heartbeatLogger
baseURL:(NSString *)baseURL {
self = [super init];
if (self) {
_URLSession = session;
_APIKey = APIKey;
_projectID = projectID;
_appID = appID;
_heartbeatLogger = heartbeatLogger;
_baseURL = baseURL;
}
return self;
Expand Down Expand Up @@ -112,10 +110,8 @@ - (instancetype)initWithURLSession:(NSURLSession *)session

[request setValue:self.APIKey forHTTPHeaderField:kAPIKeyHeaderKey];

[request setValue:[FIRApp firebaseUserAgent] forHTTPHeaderField:kUserAgentKey];

[request setValue:@([FIRHeartbeatInfo heartbeatCodeForTag:kHeartbeatStorageTag])
.stringValue
[request setValue:FIRHeaderValueFromHeartbeatsPayload(
[self.heartbeatLogger flushHeartbeatsIntoPayload])
forHTTPHeaderField:kHeartbeatKey];

[request setValue:[[NSBundle mainBundle] bundleIdentifier]
Expand Down
Expand Up @@ -66,8 +66,8 @@ - (nullable instancetype)initWithApp:(FIRApp *)app {
FIRAppCheckAPIService *APIService =
[[FIRAppCheckAPIService alloc] initWithURLSession:URLSession
APIKey:app.options.APIKey
projectID:app.options.projectID
appID:app.options.googleAppID];
appID:app.options.googleAppID
heartbeatLogger:app.heartbeatLogger];

FIRAppCheckDebugProviderAPIService *debugAPIService =
[[FIRAppCheckDebugProviderAPIService alloc] initWithAPIService:APIService
Expand Down
Expand Up @@ -91,8 +91,8 @@ - (nullable instancetype)initWithApp:(FIRApp *)app {
FIRAppCheckAPIService *APIService =
[[FIRAppCheckAPIService alloc] initWithURLSession:URLSession
APIKey:app.options.APIKey
projectID:app.options.projectID
appID:app.options.googleAppID];
appID:app.options.googleAppID
heartbeatLogger:app.heartbeatLogger];

FIRDeviceCheckAPIService *deviceCheckAPIService =
[[FIRDeviceCheckAPIService alloc] initWithAPIService:APIService
Expand Down
Expand Up @@ -24,22 +24,29 @@
#import "FirebaseAppCheck/Sources/DeviceCheckProvider/API/FIRDeviceCheckAPIService.h"
#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckToken.h"

#import "FirebaseCore/Extension/FirebaseCoreInternal.h"

@interface FIRDeviceCheckAPIServiceE2ETests : XCTestCase
@property(nonatomic) FIRDeviceCheckAPIService *deviceCheckAPIService;
@property(nonatomic) FIRAppCheckAPIService *APIService;
@property(nonatomic) NSURLSession *URLSession;
@end

// TODO(ncooke3): Fix these tests up and get them running on CI.

@implementation FIRDeviceCheckAPIServiceE2ETests

- (void)setUp {
self.URLSession = [NSURLSession
sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
FIROptions *options = [self firebaseTestOptions];
FIRHeartbeatLogger *heartbeatLogger =
[[FIRHeartbeatLogger alloc] initWithAppID:options.googleAppID];

self.APIService = [[FIRAppCheckAPIService alloc] initWithURLSession:self.URLSession
APIKey:options.APIKey
projectID:options.projectID
appID:options.googleAppID];
appID:options.googleAppID
heartbeatLogger:heartbeatLogger];
self.deviceCheckAPIService =
[[FIRDeviceCheckAPIService alloc] initWithAPIService:self.APIService
projectID:options.projectID
Expand Down

0 comments on commit 3d4b0f4

Please sign in to comment.