├── .clang-format
├── .github
├── ISSUE_TEMPLATE
│ ├── config.yml
│ └── issue_report.md
└── workflows
│ ├── check.yml
│ ├── google-utilities.yml
│ └── test_coverage.yml
├── .gitignore
├── .ruby-version
├── .swiftformat
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gemfile
├── Gemfile.lock
├── GoogleUtilities.podspec
├── GoogleUtilities
├── AppDelegateSwizzler
│ ├── GULAppDelegateSwizzler.m
│ ├── GULSceneDelegateSwizzler.m
│ ├── Internal
│ │ ├── GULAppDelegateSwizzler_Private.h
│ │ └── GULSceneDelegateSwizzler_Private.h
│ ├── Public
│ │ └── GoogleUtilities
│ │ │ ├── GULAppDelegateSwizzler.h
│ │ │ ├── GULApplication.h
│ │ │ └── GULSceneDelegateSwizzler.h
│ ├── README.md
│ └── Resources
│ │ └── PrivacyInfo.xcprivacy
├── Common
│ └── GULLoggerCodes.h
├── Environment
│ ├── GULAppEnvironmentUtil.m
│ ├── NetworkInfo
│ │ └── GULNetworkInfo.m
│ ├── Public
│ │ └── GoogleUtilities
│ │ │ ├── GULAppEnvironmentUtil.h
│ │ │ ├── GULKeychainStorage.h
│ │ │ ├── GULKeychainUtils.h
│ │ │ └── GULNetworkInfo.h
│ ├── Resources
│ │ └── PrivacyInfo.xcprivacy
│ └── SecureStorage
│ │ ├── GULKeychainStorage.m
│ │ └── GULKeychainUtils.m
├── Logger
│ ├── GULLogger.m
│ ├── Public
│ │ └── GoogleUtilities
│ │ │ ├── GULLogger.h
│ │ │ └── GULLoggerLevel.h
│ └── Resources
│ │ └── PrivacyInfo.xcprivacy
├── MethodSwizzler
│ ├── GULSwizzler.m
│ ├── Public
│ │ └── GoogleUtilities
│ │ │ ├── GULOriginalIMPConvenienceMacros.h
│ │ │ └── GULSwizzler.h
│ └── Resources
│ │ └── PrivacyInfo.xcprivacy
├── NSData+zlib
│ ├── GULNSData+zlib.m
│ ├── Public
│ │ └── GoogleUtilities
│ │ │ └── GULNSData+zlib.h
│ └── Resources
│ │ └── PrivacyInfo.xcprivacy
├── Network
│ ├── GULMutableDictionary.m
│ ├── GULNetwork.m
│ ├── GULNetworkConstants.m
│ ├── GULNetworkInternal.h
│ ├── GULNetworkURLSession.m
│ ├── Public
│ │ └── GoogleUtilities
│ │ │ ├── GULMutableDictionary.h
│ │ │ ├── GULNetwork.h
│ │ │ ├── GULNetworkConstants.h
│ │ │ ├── GULNetworkLoggerProtocol.h
│ │ │ ├── GULNetworkMessageCode.h
│ │ │ └── GULNetworkURLSession.h
│ └── Resources
│ │ └── PrivacyInfo.xcprivacy
├── Privacy
│ ├── Empty.swift
│ └── Resources
│ │ └── PrivacyInfo.xcprivacy
├── Reachability
│ ├── GULReachabilityChecker+Internal.h
│ ├── GULReachabilityChecker.m
│ ├── GULReachabilityMessageCode.h
│ ├── Public
│ │ └── GoogleUtilities
│ │ │ └── GULReachabilityChecker.h
│ └── Resources
│ │ └── PrivacyInfo.xcprivacy
├── SwizzlerTestHelpers
│ ├── GULRuntimeClassDiff.h
│ ├── GULRuntimeClassDiff.m
│ ├── GULRuntimeClassSnapshot.h
│ ├── GULRuntimeClassSnapshot.m
│ ├── GULRuntimeDiff.h
│ ├── GULRuntimeDiff.m
│ ├── GULRuntimeSnapshot.h
│ ├── GULRuntimeSnapshot.m
│ ├── GULRuntimeStateHelper.h
│ ├── GULRuntimeStateHelper.m
│ ├── GULSwizzler+Unswizzle.m
│ ├── GULSwizzlingCache.h
│ ├── GULSwizzlingCache.m
│ ├── GULSwizzlingCache_Private.h
│ └── Public
│ │ └── GoogleUtilities
│ │ └── GULSwizzler+Unswizzle.h
├── Tests
│ ├── SwiftUnit
│ │ └── GULAppEnvironmentUtilTest.swift
│ └── Unit
│ │ ├── Environment
│ │ ├── GULAppEnvironmentUtilTest.m
│ │ └── GULKeychainStorageTests.m
│ │ ├── Logger
│ │ └── GULLoggerTest.m
│ │ ├── Network
│ │ ├── GULMutableDictionaryTest.m
│ │ ├── GULNetworkTest.m
│ │ └── third_party
│ │ │ ├── GTMHTTPServer.h
│ │ │ ├── GTMHTTPServer.m
│ │ │ └── LICENSE
│ │ ├── Reachability
│ │ └── GULReachabilityCheckerTest.m
│ │ ├── Shared
│ │ └── URLSession
│ │ │ ├── FIRURLSessionOCMockStub.h
│ │ │ └── FIRURLSessionOCMockStub.m
│ │ ├── Swizzler
│ │ ├── GULAppDelegateSwizzlerTest.m
│ │ ├── GULRuntimeClassDiffTests.m
│ │ ├── GULRuntimeClassSnapshotTests.m
│ │ ├── GULRuntimeDiffTests.m
│ │ ├── GULRuntimeSnapshotTests.m
│ │ ├── GULRuntimeStateHelperTests.m
│ │ ├── GULSceneDelegateSwizzlerTest.m
│ │ ├── GULSwizzlerInheritedMethodsSwizzlingTest.m
│ │ ├── GULSwizzlerTest.m
│ │ └── GULSwizzlingCacheTest.m
│ │ ├── UserDefaults
│ │ └── GULUserDefaultsTests.m
│ │ └── Utils
│ │ ├── GULTestKeychain.h
│ │ └── GULTestKeychain.m
└── UserDefaults
│ ├── GULUserDefaults.m
│ ├── Public
│ └── GoogleUtilities
│ │ └── GULUserDefaults.h
│ └── Resources
│ └── PrivacyInfo.xcprivacy
├── LICENSE
├── Mintfile
├── Package.swift
├── README.md
├── SwiftPMTests
├── objc-import-test
│ ├── objc-header.m
│ └── objc-module.m
└── swift-test
│ └── main.swift
├── setup-scripts.sh
└── third_party
└── IsAppEncrypted
├── IsAppEncrypted.m
├── LICENSE
└── Public
└── IsAppEncrypted.h
/.clang-format:
--------------------------------------------------------------------------------
1 | BasedOnStyle: Google
2 | ColumnLimit: 100
3 | BinPackParameters: false
4 | AllowAllParametersOfDeclarationOnNextLine: true
5 | ObjCSpaceBeforeProtocolList: true
6 | SpacesInContainerLiterals: true
7 | PointerAlignment: Right
8 | AllowShortFunctionsOnASingleLine: None
9 | IncludeBlocks: Preserve
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Google Utilities
4 | url: https://github.com/firebase/firebase-ios-sdk/issues/new/choose
5 | about: Google Utilities is not supported for direct usage. Please file with the product library that depends on Google Utilities.
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/issue_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐞 Internal Issue
3 | about: Googlers may file issues here or to track with [Firebase](https://github.com/firebase/firebase-ios-sdk/issues/new/choose)
4 | ---
5 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/check.yml:
--------------------------------------------------------------------------------
1 | name: check
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches: main
7 |
8 | concurrency:
9 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
10 | cancel-in-progress: true
11 |
12 | jobs:
13 | check:
14 | runs-on: macos-latest
15 | env:
16 | MINT_PATH: ${{ github.workspace }}/mint
17 | steps:
18 | - uses: actions/checkout@v4
19 |
20 | - uses: actions/setup-python@v2
21 | with:
22 | python-version: '3.10'
23 |
24 | - name: Cache Mint packages
25 | uses: actions/cache@v4
26 | with:
27 | path: ${{ env.MINT_PATH }}
28 | key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }}
29 | restore-keys: ${{ runner.os }}-mint-
30 |
31 | - name: Setup Scripts Directory
32 | run: ./setup-scripts.sh
33 |
34 | - name: Setup check
35 | run: scripts/setup_check.sh
36 |
37 | - name: Style
38 | run: scripts/style.sh test-only
39 |
40 | - name: Whitespace
41 | run: scripts/check_whitespace.sh
42 |
43 | - name: Filename spaces
44 | run: scripts/check_filename_spaces.sh
45 |
46 | - name: Copyrights
47 | run: scripts/check_copyright.sh
48 |
49 | - name: Imports
50 | run: scripts/check_imports.swift
51 |
--------------------------------------------------------------------------------
/.github/workflows/google-utilities.yml:
--------------------------------------------------------------------------------
1 | name: google-utilities
2 |
3 | on:
4 | pull_request:
5 | schedule:
6 | # Run every day at 11pm (PST) - cron uses UTC times
7 | - cron: '0 7 * * *'
8 |
9 | concurrency:
10 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
11 | cancel-in-progress: true
12 |
13 | jobs:
14 | changed_today:
15 | runs-on: ubuntu-latest
16 | name: Check if the repo was updated today
17 | outputs:
18 | WAS_CHANGED: ${{ steps.check_changed.outputs.WAS_CHANGED }}
19 | steps:
20 | - uses: actions/checkout@v4
21 | - id: check_changed
22 | name: Check
23 | if: ${{ github.event_name == 'schedule' }}
24 | run: echo '::set-output name=WAS_CHANGED::'$(test -n "$(git log --format=%H --since='24 hours ago')" && echo 'true' || echo 'false')
25 |
26 | pod-lib-lint:
27 | needs: changed_today
28 | if: ${{ github.event_name == 'pull_request' || needs.changed_today.outputs.WAS_CHANGED == 'true' }}
29 |
30 | runs-on: macOS-latest
31 | strategy:
32 | matrix:
33 | target: [ios, tvos, macos]
34 | steps:
35 | - uses: ruby/setup-ruby@v1
36 | with:
37 | ruby-version: "2.7"
38 | - uses: actions/checkout@v3
39 | - name: Setup Scripts Directory
40 | run: ./setup-scripts.sh
41 | - name: Setup Bundler
42 | run: scripts/setup_bundler.sh
43 | - name: Build and test
44 | run: |
45 | scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb GoogleUtilities.podspec \
46 | --platforms=${{ matrix.target }} --analyze
47 |
48 | catalyst:
49 | needs: changed_today
50 | if: ${{ github.event_name == 'pull_request' || needs.changed_today.outputs.WAS_CHANGED == 'true' }}
51 |
52 | runs-on: macOS-latest
53 | steps:
54 | - uses: ruby/setup-ruby@v1
55 | with:
56 | ruby-version: "2.7"
57 | - uses: actions/checkout@v3
58 | - name: Setup Scripts Directory
59 | run: ./setup-scripts.sh
60 | - name: Setup Bundler
61 | run: scripts/setup_bundler.sh
62 | - name: Setup project and Build for Catalyst
63 | run: |
64 | scripts/third_party/travis/retry.sh scripts/test_catalyst.sh GoogleUtilities test \
65 | GoogleUtilities-Unit-unit
66 |
67 | spm:
68 | needs: changed_today
69 | if: ${{ github.event_name == 'pull_request' || needs.changed_today.outputs.WAS_CHANGED == 'true' }}
70 |
71 | runs-on: macOS-latest
72 | strategy:
73 | matrix:
74 | target: [iOS, tvOS, macOS, catalyst]
75 | steps:
76 | - uses: actions/checkout@v3
77 | - name: Setup Scripts Directory
78 | run: ./setup-scripts.sh
79 | - name: Initialize xcodebuild
80 | run: |
81 | sudo xcode-select -s '/Applications/Xcode_16.2.app/Contents/Developer'
82 | xcodebuild -list
83 | - name: iOS Unit Tests
84 | run: scripts/third_party/travis/retry.sh scripts/build.sh GoogleUtilities-Package ${{ matrix.target }} spm
85 |
86 | utilities-cocoapods-option-matrix:
87 | needs: pod-lib-lint
88 | runs-on: macos-latest
89 | strategy:
90 | matrix:
91 | target: [ios, tvos, macos]
92 | flags: [
93 | '--use-static-frameworks',
94 | '--use-libraries --skip-tests'
95 | ]
96 | steps:
97 | - uses: ruby/setup-ruby@v1
98 | with:
99 | ruby-version: "2.7"
100 | - uses: actions/checkout@v3
101 | - name: Setup Scripts Directory
102 | run: ./setup-scripts.sh
103 | - name: Setup Bundler
104 | run: scripts/setup_bundler.sh
105 | - name: PodLibLint GoogleUtilities Cron
106 | run: |
107 | scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb \
108 | GoogleUtilities.podspec --platforms=${{ matrix.target }} ${{ matrix.flags }} --analyze
109 |
--------------------------------------------------------------------------------
/.github/workflows/test_coverage.yml:
--------------------------------------------------------------------------------
1 | name: test_coverage
2 |
3 | on:
4 | pull_request:
5 | # open will be triggered when a pull request is created.
6 | # synchronize will be triggered when a pull request has new commits.
7 | # closed will be triggered when a pull request is closed.
8 | types: [opened, synchronize, closed]
9 |
10 | env:
11 | METRICS_SERVICE_SECRET: ${{ secrets.GHASecretsGPGPassphrase1 }}
12 |
13 | concurrency:
14 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
15 | cancel-in-progress: true
16 |
17 | jobs:
18 | pod_lib_lint:
19 | if: github.repository == 'google/GoogleUtilities' && (github.event.action == 'synchronize' || github.event.action == 'opened' || github.event.pull_request.merged)
20 | runs-on: macos-latest
21 | strategy:
22 | matrix:
23 | target: [ios]
24 | steps:
25 | - uses: ruby/setup-ruby@v1
26 | with:
27 | ruby-version: "2.7"
28 | - uses: actions/checkout@v4
29 | - name: Setup Scripts Directory
30 | run: ./setup-scripts.sh
31 | - name: Setup Bundler
32 | run: ./scripts/setup_bundler.sh
33 | - name: PodLibLint DataTransport
34 | run: |
35 | scripts/health_metrics/pod_test_code_coverage_report.sh --sdk=GoogleUtilities --platform=${{ matrix.target }} --test_spec=unit,unit-swift --output_path="/Users/runner/GoogleUtilities-ios-unit.xcresult"
36 | - uses: actions/upload-artifact@v4
37 | with:
38 | name: codecoverage
39 | path: /Users/runner/*.xcresult
40 | manage_test_results:
41 | if: github.repository == 'google/GoogleUtilities' && (github.event.action == 'synchronize' || github.event.action == 'opened' || github.event.pull_request.merged)
42 | needs: pod_lib_lint
43 | runs-on: macOS-latest
44 | steps:
45 | - uses: actions/checkout@v4
46 | with:
47 | fetch-depth: 0
48 | - uses: actions/download-artifact@v4.1.7
49 | id: download
50 | with:
51 | path: /Users/runner/test
52 | - name: Setup Scripts Directory
53 | run: ./setup-scripts.sh
54 | - name: Access to Metrics Service
55 | if: ${{ env.METRICS_SERVICE_SECRET }}
56 | run: |
57 | # Install gcloud sdk
58 | curl https://sdk.cloud.google.com > install.sh
59 | bash install.sh --disable-prompts
60 | echo "${HOME}/google-cloud-sdk/bin/" >> $GITHUB_PATH
61 | export PATH="${HOME}/google-cloud-sdk/bin/:${PATH}"
62 |
63 | # Activate the service account for Metrics Service.
64 | scripts/decrypt_gha_secret.sh scripts/gha-encrypted/metrics_service_access.json.gpg \
65 | metrics-access.json "${{ env.METRICS_SERVICE_SECRET }}"
66 | gcloud auth activate-service-account --key-file metrics-access.json
67 | - name: Build code coverage tool
68 | run: swift build --package-path firebase-ios-sdk/scripts/health_metrics/generate_code_coverage_report/
69 | - name: Generate report
70 | if: github.event.pull_request.merged != true && env.METRICS_SERVICE_SECRET
71 | env:
72 | pr_branch: ${{ github.event.pull_request.head.ref }}
73 | run: |
74 | common_commit=$(git merge-base remotes/origin/${pr_branch} remotes/origin/main)
75 | GITHUB_SHA=$(cat $GITHUB_EVENT_PATH | jq -r .pull_request.head.sha)
76 | if [ -d "${{steps.download.outputs.download-path}}" ]; then
77 | firebase-ios-sdk/scripts/health_metrics/generate_code_coverage_report/.build/debug/CoverageReportGenerator --presubmit "google/GoogleUtilities" --head-commit "${GITHUB_SHA}" --token $(gcloud auth print-identity-token) --xcresult-dir "${{steps.download.outputs.download-path}}/codecoverage" --log-link "https://github.com/google/GoogleUtilities/actions/runs/${GITHUB_RUN_ID}" --pull-request-num ${{github.event.pull_request.number}} --base-commit "$common_commit"
78 | fi
79 | - name: Update New Coverage Data
80 | if: github.event.pull_request.merged == true && env.METRICS_SERVICE_SECRET
81 | run: |
82 | if [ -d "${{steps.download.outputs.download-path}}" ]; then
83 | firebase-ios-sdk/scripts/health_metrics/generate_code_coverage_report/.build/debug/CoverageReportGenerator --merge "google/GoogleUtilities" --head-commit "${GITHUB_SHA}" --token $(gcloud auth print-identity-token) --xcresult-dir "${{steps.download.outputs.download-path}}/codecoverage" --log-link "https://github.com/google/GoogleUtilities/actions/runs/${GITHUB_RUN_ID}" --source-branch "${{ github.base_ref }}"
84 | fi
85 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata/
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Swift Package Manager
23 | */.build
24 | Package.resolved
25 |
26 | # Mint package manager
27 | Mint
28 |
29 | # IntelliJ
30 | .idea
31 |
32 | # Vim
33 | *.swo
34 | *.swp
35 | *~
36 |
37 | # Bundler
38 | /.bundle
39 | /vendor
40 |
41 | # Pods
42 | Pods/
43 | Podfile.lock
44 | *.xcworkspace
45 |
46 | # CocoaPods generate
47 | gen/
48 |
49 | #firebase-ios-sdk clone
50 | firebase-ios-sdk/
51 |
52 | #scripts link
53 | scripts
54 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | ruby-2.7
2 |
--------------------------------------------------------------------------------
/.swiftformat:
--------------------------------------------------------------------------------
1 | # Formatting Options - Mimic Google style
2 | --indent 2
3 | --maxwidth 100
4 | --wrapparameters afterfirst
5 |
6 | # Disabled Rules
7 |
8 | # Too many of our swift files have simplistic examples. While technically
9 | # it's correct to remove the unused argument labels, it makes our examples
10 | # look wrong.
11 | --disable unusedArguments
12 |
13 | # We prefer trailing braces.
14 | --disable wrapMultilineStatementBraces
15 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult [GitHub Help] for more
22 | information on using pull requests.
23 |
24 | [GitHub Help]: https://help.github.com/articles/about-pull-requests/
25 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # To update, change version below, run bundle install, test,
2 | # commit Gemfile and Gemfile.lock.
3 | source 'https://rubygems.org'
4 |
5 | gem 'cocoapods', '1.15.2'
6 | gem 'cocoapods-generate', '2.0.1'
7 | gem 'danger', '8.4.5'
8 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.7)
5 | base64
6 | nkf
7 | rexml
8 | activesupport (7.1.3.2)
9 | base64
10 | bigdecimal
11 | concurrent-ruby (~> 1.0, >= 1.0.2)
12 | connection_pool (>= 2.2.5)
13 | drb
14 | i18n (>= 1.6, < 2)
15 | minitest (>= 5.1)
16 | mutex_m
17 | tzinfo (~> 2.0)
18 | addressable (2.8.4)
19 | public_suffix (>= 2.0.2, < 6.0)
20 | algoliasearch (1.27.5)
21 | httpclient (~> 2.8, >= 2.8.3)
22 | json (>= 1.5.1)
23 | atomos (0.1.3)
24 | base64 (0.2.0)
25 | bigdecimal (3.1.7)
26 | claide (1.1.0)
27 | claide-plugins (0.9.2)
28 | cork
29 | nap
30 | open4 (~> 1.3)
31 | cocoapods (1.15.2)
32 | addressable (~> 2.8)
33 | claide (>= 1.0.2, < 2.0)
34 | cocoapods-core (= 1.15.2)
35 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
36 | cocoapods-downloader (>= 2.1, < 3.0)
37 | cocoapods-plugins (>= 1.0.0, < 2.0)
38 | cocoapods-search (>= 1.0.0, < 2.0)
39 | cocoapods-trunk (>= 1.6.0, < 2.0)
40 | cocoapods-try (>= 1.1.0, < 2.0)
41 | colored2 (~> 3.1)
42 | escape (~> 0.0.4)
43 | fourflusher (>= 2.3.0, < 3.0)
44 | gh_inspector (~> 1.0)
45 | molinillo (~> 0.8.0)
46 | nap (~> 1.0)
47 | ruby-macho (>= 2.3.0, < 3.0)
48 | xcodeproj (>= 1.23.0, < 2.0)
49 | cocoapods-core (1.15.2)
50 | activesupport (>= 5.0, < 8)
51 | addressable (~> 2.8)
52 | algoliasearch (~> 1.0)
53 | concurrent-ruby (~> 1.1)
54 | fuzzy_match (~> 2.0.4)
55 | nap (~> 1.0)
56 | netrc (~> 0.11)
57 | public_suffix (~> 4.0)
58 | typhoeus (~> 1.0)
59 | cocoapods-deintegrate (1.0.5)
60 | cocoapods-disable-podfile-validations (0.1.1)
61 | cocoapods-downloader (2.1)
62 | cocoapods-generate (2.0.1)
63 | cocoapods-disable-podfile-validations (~> 0.1.1)
64 | cocoapods-plugins (1.0.0)
65 | nap
66 | cocoapods-search (1.0.1)
67 | cocoapods-trunk (1.6.0)
68 | nap (>= 0.8, < 2.0)
69 | netrc (~> 0.11)
70 | cocoapods-try (1.2.0)
71 | colored2 (3.1.2)
72 | concurrent-ruby (1.2.3)
73 | connection_pool (2.4.1)
74 | cork (0.3.0)
75 | colored2 (~> 3.1)
76 | danger (8.4.5)
77 | claide (~> 1.0)
78 | claide-plugins (>= 0.9.2)
79 | colored2 (~> 3.1)
80 | cork (~> 0.1)
81 | faraday (>= 0.9.0, < 2.0)
82 | faraday-http-cache (~> 2.0)
83 | git (~> 1.7)
84 | kramdown (~> 2.3)
85 | kramdown-parser-gfm (~> 1.0)
86 | no_proxy_fix
87 | octokit (~> 4.7)
88 | terminal-table (>= 1, < 4)
89 | drb (2.2.1)
90 | escape (0.0.4)
91 | ethon (0.16.0)
92 | ffi (>= 1.15.0)
93 | faraday (1.10.2)
94 | faraday-em_http (~> 1.0)
95 | faraday-em_synchrony (~> 1.0)
96 | faraday-excon (~> 1.1)
97 | faraday-httpclient (~> 1.0)
98 | faraday-multipart (~> 1.0)
99 | faraday-net_http (~> 1.0)
100 | faraday-net_http_persistent (~> 1.0)
101 | faraday-patron (~> 1.0)
102 | faraday-rack (~> 1.0)
103 | faraday-retry (~> 1.0)
104 | ruby2_keywords (>= 0.0.4)
105 | faraday-em_http (1.0.0)
106 | faraday-em_synchrony (1.0.0)
107 | faraday-excon (1.1.0)
108 | faraday-http-cache (2.4.1)
109 | faraday (>= 0.8)
110 | faraday-httpclient (1.0.1)
111 | faraday-multipart (1.0.4)
112 | multipart-post (~> 2)
113 | faraday-net_http (1.0.1)
114 | faraday-net_http_persistent (1.2.0)
115 | faraday-patron (1.0.0)
116 | faraday-rack (1.0.0)
117 | faraday-retry (1.0.3)
118 | ffi (1.16.3)
119 | fourflusher (2.3.1)
120 | fuzzy_match (2.0.4)
121 | gh_inspector (1.1.3)
122 | git (1.18.0)
123 | addressable (~> 2.8)
124 | rchardet (~> 1.8)
125 | httpclient (2.8.3)
126 | i18n (1.14.4)
127 | concurrent-ruby (~> 1.0)
128 | json (2.7.2)
129 | kramdown (2.4.0)
130 | rexml
131 | kramdown-parser-gfm (1.1.0)
132 | kramdown (~> 2.0)
133 | minitest (5.22.3)
134 | molinillo (0.8.0)
135 | multipart-post (2.2.3)
136 | mutex_m (0.2.0)
137 | nanaimo (0.3.0)
138 | nap (1.1.0)
139 | netrc (0.11.0)
140 | nkf (0.2.0)
141 | no_proxy_fix (0.1.2)
142 | octokit (4.25.1)
143 | faraday (>= 1, < 3)
144 | sawyer (~> 0.9)
145 | open4 (1.3.4)
146 | public_suffix (4.0.7)
147 | rchardet (1.8.0)
148 | rexml (3.3.9)
149 | ruby-macho (2.5.1)
150 | ruby2_keywords (0.0.5)
151 | sawyer (0.9.2)
152 | addressable (>= 2.3.5)
153 | faraday (>= 0.17.3, < 3)
154 | terminal-table (3.0.2)
155 | unicode-display_width (>= 1.1.1, < 3)
156 | typhoeus (1.4.1)
157 | ethon (>= 0.9.0)
158 | tzinfo (2.0.6)
159 | concurrent-ruby (~> 1.0)
160 | unicode-display_width (2.3.0)
161 | xcodeproj (1.25.0)
162 | CFPropertyList (>= 2.3.3, < 4.0)
163 | atomos (~> 0.1.3)
164 | claide (>= 1.0.2, < 2.0)
165 | colored2 (~> 3.1)
166 | nanaimo (~> 0.3.0)
167 | rexml (>= 3.3.2, < 4.0)
168 |
169 | PLATFORMS
170 | ruby
171 |
172 | DEPENDENCIES
173 | cocoapods (= 1.15.2)
174 | cocoapods-generate (= 2.0.1)
175 | danger (= 8.4.5)
176 |
177 | BUNDLED WITH
178 | 2.1.4
179 |
--------------------------------------------------------------------------------
/GoogleUtilities.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'GoogleUtilities'
3 | s.version = '8.1.0'
4 | s.summary = 'Google Utilities for Apple platform SDKs'
5 |
6 | s.description = <<-DESC
7 | Internal Google Utilities including Network, Reachability Environment, Logger and Swizzling for
8 | other Google CocoaPods. They're not intended for direct public usage.
9 | DESC
10 |
11 | s.homepage = 'https://github.com/google/GoogleUtilities'
12 | s.license = { :type => 'Apache-2.0', :file => 'LICENSE' }
13 | s.authors = 'Google, Inc.'
14 |
15 | s.source = {
16 | :git => 'https://github.com/google/GoogleUtilities.git',
17 | :tag => 'CocoaPods-' + s.version.to_s
18 | }
19 |
20 | ios_deployment_target = '12.0'
21 | osx_deployment_target = '10.15'
22 | tvos_deployment_target = '13.0'
23 | watchos_deployment_target = '7.0'
24 |
25 | s.ios.deployment_target = ios_deployment_target
26 | s.osx.deployment_target = osx_deployment_target
27 | s.tvos.deployment_target = tvos_deployment_target
28 | s.watchos.deployment_target = watchos_deployment_target
29 |
30 | s.cocoapods_version = '>= 1.4.0'
31 | s.prefix_header_file = false
32 |
33 | s.pod_target_xcconfig = {
34 | 'GCC_C_LANGUAGE_STANDARD' => 'c99',
35 | 'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}"',
36 | }
37 |
38 | s.subspec 'Privacy' do |cs|
39 | cs.resource_bundles = {
40 | "GoogleUtilities_Privacy" => 'GoogleUtilities/Privacy/Resources/PrivacyInfo.xcprivacy'
41 | }
42 | end
43 |
44 | s.subspec 'Environment' do |es|
45 | es.source_files = [
46 | 'GoogleUtilities/Environment/**/*.[mh]',
47 | 'third_party/IsAppEncrypted/**/*.[mh]'
48 | ]
49 | es.public_header_files = 'GoogleUtilities/Environment/Public/GoogleUtilities/*.h'
50 | es.dependency 'GoogleUtilities/Privacy'
51 | es.frameworks = [
52 | 'Security'
53 | ]
54 | end
55 |
56 | s.subspec 'Logger' do |ls|
57 | ls.source_files = 'GoogleUtilities/Logger/**/*.[mh]'
58 | ls.public_header_files = 'GoogleUtilities/Logger/Public/GoogleUtilities/*.h'
59 | ls.dependency 'GoogleUtilities/Environment'
60 | ls.dependency 'GoogleUtilities/Privacy'
61 | end
62 |
63 |
64 | s.subspec 'Network' do |ns|
65 | ns.source_files = 'GoogleUtilities/Network/**/*.[mh]'
66 | ns.public_header_files = 'GoogleUtilities/Network/Public/GoogleUtilities/*.h'
67 | ns.dependency 'GoogleUtilities/NSData+zlib'
68 | ns.dependency 'GoogleUtilities/Logger'
69 | ns.dependency 'GoogleUtilities/Reachability'
70 | ns.dependency 'GoogleUtilities/Privacy'
71 | ns.frameworks = [
72 | 'Security'
73 | ]
74 | end
75 |
76 | s.subspec 'NSData+zlib' do |ns|
77 | ns.source_files = 'GoogleUtilities/NSData+zlib/**/*.[mh]'
78 | ns.public_header_files = 'GoogleUtilities/NSData+zlib/Public/GoogleUtilities/*.h'
79 | ns.dependency 'GoogleUtilities/Privacy'
80 | ns.libraries = [
81 | 'z'
82 | ]
83 | end
84 |
85 | s.subspec 'Reachability' do |rs|
86 | rs.source_files = 'GoogleUtilities/Reachability/**/*.[mh]'
87 | rs.public_header_files = 'GoogleUtilities/Reachability/Public/GoogleUtilities/*.h'
88 | rs.dependency 'GoogleUtilities/Privacy'
89 | rs.ios.frameworks = [
90 | 'SystemConfiguration'
91 | ]
92 | rs.osx.frameworks = [
93 | 'SystemConfiguration'
94 | ]
95 | rs.tvos.frameworks = [
96 | 'SystemConfiguration'
97 | ]
98 | rs.dependency 'GoogleUtilities/Logger'
99 | end
100 |
101 | s.subspec 'AppDelegateSwizzler' do |adss|
102 | adss.source_files = [
103 | 'GoogleUtilities/AppDelegateSwizzler/Internal/*.h',
104 | 'GoogleUtilities/AppDelegateSwizzler/Public/**/*.h',
105 | 'GoogleUtilities/AppDelegateSwizzler/*.m',
106 | 'GoogleUtilities/Common/*.h',
107 | ]
108 | adss.public_header_files = [
109 | 'GoogleUtilities/AppDelegateSwizzler/Public/GoogleUtilities/*.h',
110 | ]
111 | adss.dependency 'GoogleUtilities/Privacy'
112 | adss.dependency 'GoogleUtilities/Logger'
113 | adss.dependency 'GoogleUtilities/Network'
114 | adss.dependency 'GoogleUtilities/Environment'
115 | end
116 |
117 | s.subspec 'MethodSwizzler' do |mss|
118 | mss.source_files = 'GoogleUtilities/MethodSwizzler/**/*.[mh]', 'GoogleUtilities/Common/*.h'
119 | mss.public_header_files = 'GoogleUtilities/MethodSwizzler/Public/GoogleUtilities/*.h'
120 | mss.dependency 'GoogleUtilities/Logger'
121 | mss.dependency 'GoogleUtilities/Privacy'
122 | end
123 |
124 | s.subspec 'SwizzlerTestHelpers' do |sths|
125 | sths.source_files = 'GoogleUtilities/SwizzlerTestHelpers/**/*.[hm]'
126 | sths.public_header_files = 'GoogleUtilities/SwizzlerTestHelpers/Public/GoogleUtilities/*.h'
127 | sths.dependency 'GoogleUtilities/MethodSwizzler'
128 | end
129 |
130 | s.subspec 'UserDefaults' do |ud|
131 | ud.source_files = 'GoogleUtilities/UserDefaults/**/*.[hm]'
132 | ud.public_header_files = 'GoogleUtilities/UserDefaults/Public/GoogleUtilities/*.h'
133 | ud.dependency 'GoogleUtilities/Logger'
134 | ud.dependency 'GoogleUtilities/Privacy'
135 | end
136 |
137 | s.test_spec 'unit' do |unit_tests|
138 | unit_tests.scheme = { :code_coverage => true }
139 |
140 | unit_tests.platforms = {
141 | :ios => ios_deployment_target,
142 | :osx => osx_deployment_target,
143 | :tvos => tvos_deployment_target
144 | }
145 | unit_tests.source_files = [
146 | 'GoogleUtilities/Tests/Unit/**/*.[mh]',
147 | ]
148 |
149 | # All tests require arc except Tests/Network/third_party/GTMHTTPServer.m
150 | unit_tests.requires_arc = [
151 | 'GoogleUtilities/Tests/Unit/*/*.[mh]',
152 | 'GoogleUtilities/Tests/Unit/Environment/**/*.[mh]'
153 | ]
154 | unit_tests.requires_app_host = true
155 | unit_tests.dependency 'OCMock'
156 | end
157 |
158 | s.test_spec 'unit-swift' do |unit_tests_swift|
159 | unit_tests_swift.scheme = { :code_coverage => true }
160 | unit_tests_swift.platforms = {
161 | :ios => ios_deployment_target,
162 | :osx => osx_deployment_target,
163 | :tvos => tvos_deployment_target
164 | }
165 | unit_tests_swift.source_files = 'GoogleUtilities/Tests/SwiftUnit/**/*.swift',
166 | 'GoogleUtilities/Tests/SwiftUnit/**/*.h'
167 | unit_tests_swift.requires_app_host = true
168 | end
169 | end
170 |
--------------------------------------------------------------------------------
/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 | #import "GoogleUtilities/AppDelegateSwizzler/Public/GoogleUtilities/GULAppDelegateSwizzler.h"
19 | #import "GoogleUtilities/Network/Public/GoogleUtilities/GULMutableDictionary.h"
20 |
21 | @class GULApplication;
22 |
23 | NS_ASSUME_NONNULL_BEGIN
24 |
25 | @interface GULAppDelegateSwizzler ()
26 |
27 | /** ISA Swizzles the given appDelegate as the original app delegate would be.
28 | *
29 | * @param appDelegate The object that needs to be isa swizzled. This should conform to the
30 | * application delegate protocol.
31 | */
32 | + (void)proxyAppDelegate:(id)appDelegate;
33 |
34 | /** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer.
35 | *
36 | * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is
37 | * the interceptorID.
38 | */
39 | + (GULMutableDictionary *)interceptors;
40 |
41 | /** Deletes all the registered interceptors. */
42 | + (void)clearInterceptors;
43 |
44 | /** Resets the token that prevents the app delegate proxy from being isa swizzled multiple times. */
45 | + (void)resetProxyOriginalDelegateOnceToken;
46 |
47 | /** Returns the original app delegate that was proxied.
48 | *
49 | * @return The original app delegate instance that was proxied.
50 | */
51 | + (id)originalDelegate;
52 |
53 | @end
54 |
55 | NS_ASSUME_NONNULL_END
56 |
--------------------------------------------------------------------------------
/GoogleUtilities/AppDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google LLC
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 | #import
18 | #import "GoogleUtilities/AppDelegateSwizzler/Public/GoogleUtilities/GULSceneDelegateSwizzler.h"
19 | #import "GoogleUtilities/Network/Public/GoogleUtilities/GULMutableDictionary.h"
20 |
21 | NS_ASSUME_NONNULL_BEGIN
22 |
23 | @interface GULSceneDelegateSwizzler ()
24 |
25 | #if UISCENE_SUPPORTED
26 |
27 | /** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer.
28 | *
29 | * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is
30 | * the interceptorID.
31 | */
32 | + (GULMutableDictionary *)interceptors;
33 |
34 | /** Deletes all the registered interceptors. */
35 | + (void)clearInterceptors;
36 |
37 | /** ISA Swizzles the given appDelegate as the original app delegate would be.
38 | *
39 | * @param scene The scene whose delegate needs to be isa swizzled. This should conform to the
40 | * scene delegate protocol.
41 | */
42 | + (void)proxySceneDelegateIfNeeded:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0));
43 |
44 | #endif // UISCENE_SUPPORTED
45 |
46 | @end
47 |
48 | NS_ASSUME_NONNULL_END
49 |
--------------------------------------------------------------------------------
/GoogleUtilities/AppDelegateSwizzler/Public/GoogleUtilities/GULAppDelegateSwizzler.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | #import "GULApplication.h"
20 |
21 | NS_ASSUME_NONNULL_BEGIN
22 |
23 | typedef NSString *const GULAppDelegateInterceptorID;
24 |
25 | /** This class contains methods that isa swizzle the app delegate. */
26 | @interface GULAppDelegateSwizzler : NSProxy
27 |
28 | /** Registers an app delegate interceptor whose methods will be invoked as they're invoked on the
29 | * original app delegate.
30 | *
31 | * @param interceptor An instance of a class that conforms to the application delegate protocol.
32 | * The interceptor is NOT retained.
33 | * @return A unique GULAppDelegateInterceptorID if interceptor was successfully registered; nil
34 | * if it fails.
35 | */
36 | + (nullable GULAppDelegateInterceptorID)registerAppDelegateInterceptor:
37 | (id)interceptor;
38 |
39 | /** Unregisters an interceptor with the given ID if it exists.
40 | *
41 | * @param interceptorID The object that was generated when the interceptor was registered.
42 | */
43 | + (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID;
44 |
45 | /** This method ensures that the original app delegate has been proxied. Call this before
46 | * registering your interceptor. This method is safe to call multiple times (but it only proxies
47 | * the app delegate once).
48 | *
49 | * This method doesn't proxy APNS related methods:
50 | * @code
51 | * - application:didRegisterForRemoteNotificationsWithDeviceToken:
52 | * - application:didFailToRegisterForRemoteNotificationsWithError:
53 | * - application:didReceiveRemoteNotification:fetchCompletionHandler:
54 | * - application:didReceiveRemoteNotification:
55 | * @endcode
56 | *
57 | * To proxy these methods use +[GULAppDelegateSwizzler
58 | * proxyOriginalDelegateIncludingAPNSMethods]. The methods have to be proxied separately to
59 | * avoid potential warnings from Apple review about missing Push Notification Entitlement (e.g.
60 | * https://github.com/firebase/firebase-ios-sdk/issues/2807)
61 | *
62 | * The method has no effect for extensions.
63 | *
64 | * @see proxyOriginalDelegateIncludingAPNSMethods
65 | */
66 | + (void)proxyOriginalDelegate;
67 |
68 | /** This method ensures that the original app delegate has been proxied including APNS related
69 | * methods. Call this before registering your interceptor. This method is safe to call multiple
70 | * times (but it only proxies the app delegate once) or
71 | * after +[GULAppDelegateSwizzler proxyOriginalDelegate]
72 | *
73 | * This method calls +[GULAppDelegateSwizzler proxyOriginalDelegate] under the hood.
74 | * After calling this method the following App Delegate methods will be proxied in addition to
75 | * the methods proxied by proxyOriginalDelegate:
76 | * @code
77 | * - application:didRegisterForRemoteNotificationsWithDeviceToken:
78 | * - application:didFailToRegisterForRemoteNotificationsWithError:
79 | * - application:didReceiveRemoteNotification:fetchCompletionHandler:
80 | * - application:didReceiveRemoteNotification:
81 | * @endcode
82 | *
83 | * The method has no effect for extensions.
84 | *
85 | * @see proxyOriginalDelegate
86 | */
87 | + (void)proxyOriginalDelegateIncludingAPNSMethods;
88 |
89 | /** Indicates whether app delegate proxy is explicitly disabled or enabled. Enabled by default.
90 | *
91 | * @return YES if AppDelegateProxy is Enabled, NO otherwise.
92 | */
93 | + (BOOL)isAppDelegateProxyEnabled;
94 |
95 | /** Returns the current sharedApplication.
96 | *
97 | * @return the current application instance if in an app, or nil if in extension or if it doesn't
98 | * exist.
99 | */
100 | + (nullable GULApplication *)sharedApplication;
101 |
102 | /** Do not initialize this class. */
103 | - (instancetype)init NS_UNAVAILABLE;
104 |
105 | NS_ASSUME_NONNULL_END
106 |
107 | @end
108 |
--------------------------------------------------------------------------------
/GoogleUtilities/AppDelegateSwizzler/Public/GoogleUtilities/GULApplication.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google LLC
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 | #import
18 |
19 | #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
20 |
21 | #import
22 |
23 | #define GULApplication UIApplication
24 | #define GULApplicationDelegate UIApplicationDelegate
25 | #define GULUserActivityRestoring UIUserActivityRestoring
26 |
27 | static NSString *const kGULApplicationClassName = @"UIApplication";
28 |
29 | #elif TARGET_OS_OSX
30 |
31 | #import
32 |
33 | #define GULApplication NSApplication
34 | #define GULApplicationDelegate NSApplicationDelegate
35 | #define GULUserActivityRestoring NSUserActivityRestoring
36 |
37 | static NSString *const kGULApplicationClassName = @"NSApplication";
38 |
39 | #elif TARGET_OS_WATCH
40 |
41 | #import
42 |
43 | // We match the according watchOS API but swizzling should not work in watch
44 | #define GULApplication WKExtension
45 | #define GULApplicationDelegate WKExtensionDelegate
46 | #define GULUserActivityRestoring NSUserActivityRestoring
47 |
48 | static NSString *const kGULApplicationClassName = @"WKExtension";
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/GoogleUtilities/AppDelegateSwizzler/Public/GoogleUtilities/GULSceneDelegateSwizzler.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google LLC
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 | #import
18 | #import
19 |
20 | #if __has_include()
21 | #import
22 | #endif
23 |
24 | #if TARGET_OS_IOS || TARGET_OS_TV
25 | #define UISCENE_SUPPORTED 1
26 | #endif
27 |
28 | NS_ASSUME_NONNULL_BEGIN
29 |
30 | typedef NSString *const GULSceneDelegateInterceptorID;
31 |
32 | /** This class contains methods that isa swizzle the scene delegate. */
33 | @interface GULSceneDelegateSwizzler : NSProxy
34 |
35 | #if UISCENE_SUPPORTED
36 |
37 | /** Registers a scene delegate interceptor whose methods will be invoked as they're invoked on the
38 | * original scene delegate.
39 | *
40 | * @param interceptor An instance of a class that conforms to the application delegate protocol.
41 | * The interceptor is NOT retained.
42 | * @return A unique GULSceneDelegateInterceptorID if interceptor was successfully registered; nil
43 | * if it fails.
44 | */
45 | + (nullable GULSceneDelegateInterceptorID)registerSceneDelegateInterceptor:
46 | (id)interceptor API_AVAILABLE(ios(13.0), tvos(13.0));
47 |
48 | /** Unregisters an interceptor with the given ID if it exists.
49 | *
50 | * @param interceptorID The object that was generated when the interceptor was registered.
51 | */
52 | + (void)unregisterSceneDelegateInterceptorWithID:(GULSceneDelegateInterceptorID)interceptorID
53 | API_AVAILABLE(ios(13.0), tvos(13.0));
54 |
55 | /** Do not initialize this class. */
56 | - (instancetype)init NS_UNAVAILABLE;
57 |
58 | #endif // UISCENE_SUPPORTED
59 |
60 | /** This method ensures that the original scene delegate has been proxied. Call this before
61 | * registering your interceptor. This method is safe to call multiple times (but it only proxies
62 | * the scene delegate once).
63 | *
64 | * The method has no effect for extensions.
65 | */
66 | + (void)proxyOriginalSceneDelegate;
67 |
68 | /** Indicates whether scene delegate proxy is explicitly disabled or enabled. Enabled by default.
69 | *
70 | * @return YES if SceneDelegateProxy is Enabled, NO otherwise.
71 | */
72 | + (BOOL)isSceneDelegateProxyEnabled;
73 |
74 | @end
75 |
76 | NS_ASSUME_NONNULL_END
77 |
--------------------------------------------------------------------------------
/GoogleUtilities/AppDelegateSwizzler/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/GoogleUtilities/Common/GULLoggerCodes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | typedef NS_ENUM(NSInteger, GULSwizzlerMessageCode) {
20 | // App Delegate Swizzling.
21 | kGULSwizzlerMessageCodeAppDelegateSwizzling000 = 1000, // I-SWZ001000
22 | kGULSwizzlerMessageCodeAppDelegateSwizzling001 = 1001, // I-SWZ001001
23 | kGULSwizzlerMessageCodeAppDelegateSwizzling002 = 1002, // I-SWZ001002
24 | kGULSwizzlerMessageCodeAppDelegateSwizzling003 = 1003, // I-SWZ001003
25 | kGULSwizzlerMessageCodeAppDelegateSwizzling004 = 1004, // I-SWZ001004
26 | kGULSwizzlerMessageCodeAppDelegateSwizzling005 = 1005, // I-SWZ001005
27 | kGULSwizzlerMessageCodeAppDelegateSwizzling006 = 1006, // I-SWZ001006
28 | kGULSwizzlerMessageCodeAppDelegateSwizzling007 = 1007, // I-SWZ001007
29 | kGULSwizzlerMessageCodeAppDelegateSwizzling008 = 1008, // I-SWZ001008
30 | kGULSwizzlerMessageCodeAppDelegateSwizzling009 = 1009, // I-SWZ001009
31 | kGULSwizzlerMessageCodeAppDelegateSwizzling010 = 1010, // I-SWZ001010
32 | kGULSwizzlerMessageCodeAppDelegateSwizzling011 = 1011, // I-SWZ001011
33 | kGULSwizzlerMessageCodeAppDelegateSwizzling012 = 1012, // I-SWZ001012
34 | kGULSwizzlerMessageCodeAppDelegateSwizzling013 = 1013, // I-SWZ001013
35 | kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate = 1014, // I-SWZ001014
36 |
37 | // Scene Delegate Swizzling.
38 | kGULSwizzlerMessageCodeSceneDelegateSwizzling000 = 1100, // I-SWZ001100
39 | kGULSwizzlerMessageCodeSceneDelegateSwizzling001 = 1101, // I-SWZ001101
40 | kGULSwizzlerMessageCodeSceneDelegateSwizzling002 = 1102, // I-SWZ001102
41 | kGULSwizzlerMessageCodeSceneDelegateSwizzling003 = 1103, // I-SWZ001103
42 | kGULSwizzlerMessageCodeSceneDelegateSwizzling004 = 1104, // I-SWZ001104
43 | kGULSwizzlerMessageCodeSceneDelegateSwizzling005 = 1105, // I-SWZ001105
44 | kGULSwizzlerMessageCodeSceneDelegateSwizzling006 = 1106, // I-SWZ001106
45 | kGULSwizzlerMessageCodeSceneDelegateSwizzling007 = 1107, // I-SWZ001107
46 | kGULSwizzlerMessageCodeSceneDelegateSwizzling008 = 1108, // I-SWZ001108
47 | kGULSwizzlerMessageCodeSceneDelegateSwizzling009 = 1109, // I-SWZ001109
48 | kGULSwizzlerMessageCodeSceneDelegateSwizzling010 = 1110, // I-SWZ001110
49 | kGULSwizzlerMessageCodeSceneDelegateSwizzling011 = 1111, // I-SWZ001111
50 | kGULSwizzlerMessageCodeSceneDelegateSwizzling012 = 1112, // I-SWZ001112
51 | kGULSwizzlerMessageCodeSceneDelegateSwizzling013 = 1113, // I-SWZ001113
52 | kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate = 1114, // I-SWZ001114
53 |
54 | // Method Swizzling.
55 | kGULSwizzlerMessageCodeMethodSwizzling000 = 2000, // I-SWZ002000
56 | };
57 |
--------------------------------------------------------------------------------
/GoogleUtilities/Environment/NetworkInfo/GULNetworkInfo.m:
--------------------------------------------------------------------------------
1 | // Copyright 2022 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 | #import "GoogleUtilities/Environment/Public/GoogleUtilities/GULNetworkInfo.h"
16 |
17 | #import
18 |
19 | #import
20 | #if __has_include("CoreTelephony/CTTelephonyNetworkInfo.h") && !TARGET_OS_MACCATALYST && \
21 | !TARGET_OS_OSX && !TARGET_OS_TV && !TARGET_OS_WATCH
22 | #define TARGET_HAS_MOBILE_CONNECTIVITY
23 | #import
24 | #import
25 | #endif
26 |
27 | @implementation GULNetworkInfo
28 |
29 | #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
30 | + (CTTelephonyNetworkInfo *)getNetworkInfo {
31 | static CTTelephonyNetworkInfo *networkInfo;
32 | static dispatch_once_t onceToken;
33 | dispatch_once(&onceToken, ^{
34 | networkInfo = [[CTTelephonyNetworkInfo alloc] init];
35 | });
36 | return networkInfo;
37 | }
38 | #endif
39 |
40 | + (GULNetworkType)getNetworkType {
41 | GULNetworkType networkType = GULNetworkTypeNone;
42 |
43 | #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
44 | static SCNetworkReachabilityRef reachabilityRef = 0;
45 | static dispatch_once_t onceToken;
46 | dispatch_once(&onceToken, ^{
47 | reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorSystemDefault, "google.com");
48 | });
49 |
50 | if (!reachabilityRef) {
51 | return GULNetworkTypeNone;
52 | }
53 |
54 | SCNetworkReachabilityFlags reachabilityFlags = 0;
55 | SCNetworkReachabilityGetFlags(reachabilityRef, &reachabilityFlags);
56 |
57 | // Parse the network flags to set the network type.
58 | if (reachabilityFlags & kSCNetworkReachabilityFlagsReachable) {
59 | if (reachabilityFlags & kSCNetworkReachabilityFlagsIsWWAN) {
60 | networkType = GULNetworkTypeMobile;
61 | } else {
62 | networkType = GULNetworkTypeWIFI;
63 | }
64 | }
65 | #endif
66 |
67 | return networkType;
68 | }
69 |
70 | + (NSString *)getNetworkRadioType {
71 | #ifdef TARGET_HAS_MOBILE_CONNECTIVITY
72 | CTTelephonyNetworkInfo *networkInfo = [GULNetworkInfo getNetworkInfo];
73 | if (networkInfo.serviceCurrentRadioAccessTechnology.count) {
74 | return networkInfo.serviceCurrentRadioAccessTechnology.allValues[0] ?: @"";
75 | }
76 | #endif
77 | return @"";
78 | }
79 |
80 | @end
81 |
--------------------------------------------------------------------------------
/GoogleUtilities/Environment/Public/GoogleUtilities/GULAppEnvironmentUtil.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | @interface GULAppEnvironmentUtil : NSObject
22 |
23 | /// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator,
24 | /// development environment or sideloaded.
25 | + (BOOL)isFromAppStore;
26 |
27 | /// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt.
28 | /// Returns NO otherwise.
29 | + (BOOL)isAppStoreReceiptSandbox;
30 |
31 | /// Indicates whether the app is on simulator or not at runtime depending on the device
32 | /// architecture.
33 | + (BOOL)isSimulator;
34 |
35 | /// The current device model. Returns an empty string if device model cannot be retrieved.
36 | + (nullable NSString *)deviceModel;
37 |
38 | /// The current device model, with simulator-specific values. Returns an empty string if device
39 | /// model cannot be retrieved.
40 | + (nullable NSString *)deviceSimulatorModel;
41 |
42 | /// The current operating system version. Returns an empty string if the system version cannot be
43 | /// retrieved.
44 | + (NSString *)systemVersion;
45 |
46 | /// Indicates whether it is running inside an extension or an app.
47 | + (BOOL)isAppExtension;
48 |
49 | /// Indicates whether it is running inside an app clip or a full app.
50 | + (BOOL)isAppClip;
51 |
52 | /// Indicates whether the current target supports background URL session uploads.
53 | /// App extensions and app clips do not support background URL sessions.
54 | + (BOOL)supportsBackgroundURLSessionUploads;
55 |
56 | /// @return An Apple platform. Possible values "ios", "tvos", "macos", "watchos", "maccatalyst", and
57 | /// "visionos".
58 | + (NSString *)applePlatform;
59 |
60 | /// @return An Apple Device platform. Same possible values as `applePlatform`, with the addition of
61 | /// "ipados".
62 | + (NSString *)appleDevicePlatform;
63 |
64 | /// @return The way the library was added to the app, e.g. "swiftpm", "cocoapods", etc.
65 | + (NSString *)deploymentType;
66 |
67 | @end
68 |
69 | NS_ASSUME_NONNULL_END
70 |
--------------------------------------------------------------------------------
/GoogleUtilities/Environment/Public/GoogleUtilities/GULKeychainStorage.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | /// The class provides a convenient, multiplatform abstraction of the Keychain.
22 | ///
23 | /// When using this API on macOS, the corresponding target must be signed with a provisioning
24 | /// profile that has the Keychain Sharing capability enabled.
25 | @interface GULKeychainStorage : NSObject
26 |
27 | - (instancetype)init NS_UNAVAILABLE;
28 |
29 | /** Initializes the keychain storage with Keychain Service name.
30 | * @param service A Keychain Service name that will be used to store and retrieve objects. See also
31 | * `kSecAttrService`.
32 | */
33 | - (instancetype)initWithService:(NSString *)service;
34 |
35 | /// Get an object by key.
36 | /// @param key The key.
37 | /// @param objectClass The expected object class required by `NSSecureCoding`.
38 | /// @param accessGroup The Keychain Access Group.
39 | /// @param completionHandler The completion handler to call when the
40 | /// synchronized keychain read is complete. An error is passed to the
41 | /// completion handler if the keychain read fails. Else, the object stored in
42 | /// the keychain, or `nil` if it does not exist, is passed to the completion
43 | /// handler.
44 | - (void)getObjectForKey:(NSString *)key
45 | objectClass:(Class)objectClass
46 | accessGroup:(nullable NSString *)accessGroup
47 | completionHandler:
48 | (void (^)(id _Nullable obj, NSError *_Nullable error))completionHandler;
49 |
50 | /// Saves the given object by the given key.
51 | /// @param object The object to store.
52 | /// @param key The key to store the object. If there is an existing object by the key, it will be
53 | /// overridden.
54 | /// @param accessGroup The Keychain Access Group.
55 | /// @param completionHandler The completion handler to call when the
56 | /// synchronized keychain write is complete. An error is passed to the
57 | /// completion handler if the keychain read fails. Else, the object written to
58 | /// the keychain is passed to the completion handler.
59 | - (void)setObject:(id)object
60 | forKey:(NSString *)key
61 | accessGroup:(nullable NSString *)accessGroup
62 | completionHandler:
63 | (void (^)(id _Nullable obj, NSError *_Nullable error))completionHandler;
64 |
65 | /// Removes the object by the given key.
66 | /// @param key The key to store the object. If there is an existing object by
67 | /// the key, it will be overridden.
68 | /// @param accessGroup The Keychain Access Group.
69 | /// @param completionHandler The completion handler to call when the
70 | /// synchronized keychain removal is complete. An error is passed to the
71 | /// completion handler if the keychain removal fails.
72 | - (void)removeObjectForKey:(NSString *)key
73 | accessGroup:(nullable NSString *)accessGroup
74 | completionHandler:(void (^)(NSError *_Nullable error))completionHandler;
75 |
76 | #if TARGET_OS_OSX
77 | /// If not `nil`, then only this keychain will be used to save and read data (see
78 | /// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests.
79 | @property(nonatomic, nullable) SecKeychainRef keychainRef;
80 | #endif // TARGET_OS_OSX
81 |
82 | @end
83 |
84 | NS_ASSUME_NONNULL_END
85 |
--------------------------------------------------------------------------------
/GoogleUtilities/Environment/Public/GoogleUtilities/GULKeychainUtils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | FOUNDATION_EXPORT NSString *const kGULKeychainUtilsErrorDomain;
22 |
23 | /// A collection of helper functions that abstract away common Keychain operations.
24 | ///
25 | /// When using this API on macOS, the corresponding target must be signed with a provisioning
26 | /// profile that has the Keychain Sharing capability enabled.
27 | @interface GULKeychainUtils : NSObject
28 |
29 | /** Fetches a keychain item data matching to the provided query.
30 | * @param query A dictionary with Keychain query parameters. See docs for `SecItemCopyMatching` for
31 | * details.
32 | * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be
33 | * assigned with an error if there is.
34 | * @returns Data for the first Keychain Item matching the provided query or `nil` if there is not
35 | * such an item (`outError` will be `nil` in this case) or an error occurred.
36 | */
37 | + (nullable NSData *)getItemWithQuery:(NSDictionary *)query
38 | error:(NSError *_Nullable *_Nullable)outError;
39 |
40 | /** Stores data to a Keychain Item matching to the provided query. An existing Keychain Item
41 | * matching the query parameters will be updated or a new will be created.
42 | * @param item A Keychain Item data to store.
43 | * @param query A dictionary with Keychain query parameters. See docs for `SecItemAdd` and
44 | * `SecItemUpdate` for details.
45 | * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be
46 | * assigned with an error if there is.
47 | * @returns `YES` when data was successfully stored, `NO` otherwise.
48 | */
49 | + (BOOL)setItem:(NSData *)item
50 | withQuery:(NSDictionary *)query
51 | error:(NSError *_Nullable *_Nullable)outError;
52 |
53 | /** Removes a Keychain Item matching to the provided query.
54 | * @param query A dictionary with Keychain query parameters. See docs for `SecItemDelete` for
55 | * details.
56 | * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be
57 | * assigned with an error if there is.
58 | * @returns `YES` if the item was removed successfully or doesn't exist, `NO` otherwise.
59 | */
60 | + (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError;
61 |
62 | @end
63 |
64 | NS_ASSUME_NONNULL_END
65 |
--------------------------------------------------------------------------------
/GoogleUtilities/Environment/Public/GoogleUtilities/GULNetworkInfo.h:
--------------------------------------------------------------------------------
1 | // Copyright 2022 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 | #import
16 |
17 | NS_ASSUME_NONNULL_BEGIN
18 |
19 | /// The type of network that the device is running with. Values should correspond to the NetworkType
20 | /// values in android/play/playlog/proto/clientanalytics.proto
21 | typedef NS_ENUM(NSInteger, GULNetworkType) {
22 | GULNetworkTypeNone = -1,
23 | GULNetworkTypeMobile = 0,
24 | GULNetworkTypeWIFI = 1,
25 | };
26 |
27 | /// Collection of utilities to read network status information
28 | @interface GULNetworkInfo : NSObject
29 |
30 | /// Returns an enum indicating the network type. The enum values should be easily transferrable to
31 | /// the NetworkType value in android/play/playlog/proto/clientanalytics.proto. Right now this always
32 | /// returns None on platforms other than iOS. This should be updated in the future to return Wi-Fi
33 | /// values for the other platforms when applicable.
34 | + (GULNetworkType)getNetworkType;
35 |
36 | /// Returns a string indicating the radio access technology used by the app. The return value will
37 | /// be one of CTRadioAccess constants defined in
38 | /// https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo/radio_access_technology_constants
39 | + (NSString *)getNetworkRadioType;
40 |
41 | @end
42 |
43 | NS_ASSUME_NONNULL_END
44 |
--------------------------------------------------------------------------------
/GoogleUtilities/Environment/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 | NSPrivacyAccessedAPIType
17 | NSPrivacyAccessedAPICategoryUserDefaults
18 | NSPrivacyAccessedAPITypeReasons
19 |
20 | C56D.1
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google
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 | #import "GoogleUtilities/Environment/Public/GoogleUtilities/GULKeychainUtils.h"
18 |
19 | NSString *const kGULKeychainUtilsErrorDomain = @"com.gul.keychain.ErrorDomain";
20 |
21 | @implementation GULKeychainUtils
22 |
23 | + (nullable NSData *)getItemWithQuery:(NSDictionary *)query
24 | error:(NSError *_Nullable *_Nullable)outError {
25 | NSMutableDictionary *mutableGetItemQuery =
26 | [[[self class] multiplatformQueryWithQuery:query] mutableCopy];
27 |
28 | mutableGetItemQuery[(__bridge id)kSecReturnData] = @YES;
29 | mutableGetItemQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
30 |
31 | CFDataRef result = NULL;
32 | OSStatus status =
33 | SecItemCopyMatching((__bridge CFDictionaryRef)mutableGetItemQuery, (CFTypeRef *)&result);
34 |
35 | if (status == errSecSuccess && result != NULL) {
36 | if (outError) {
37 | *outError = nil;
38 | }
39 |
40 | return (__bridge_transfer NSData *)result;
41 | }
42 |
43 | if (status == errSecItemNotFound) {
44 | if (outError) {
45 | *outError = nil;
46 | }
47 | } else {
48 | if (outError) {
49 | *outError = [self keychainErrorWithFunction:@"SecItemCopyMatching" status:status];
50 | }
51 | }
52 | return nil;
53 | }
54 |
55 | + (BOOL)setItem:(NSData *)item
56 | withQuery:(NSDictionary *)query
57 | error:(NSError *_Nullable *_Nullable)outError {
58 | NSDictionary *multiplatformQuery = [[self class] multiplatformQueryWithQuery:query];
59 |
60 | NSData *existingItem = [self getItemWithQuery:multiplatformQuery error:outError];
61 | if (outError && *outError) {
62 | return NO;
63 | }
64 |
65 | OSStatus status;
66 | if (!existingItem) {
67 | NSMutableDictionary *mutableAddItemQuery = [multiplatformQuery mutableCopy];
68 | mutableAddItemQuery[(__bridge id)kSecAttrAccessible] =
69 | (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
70 | mutableAddItemQuery[(__bridge id)kSecValueData] = item;
71 |
72 | status = SecItemAdd((__bridge CFDictionaryRef)mutableAddItemQuery, NULL);
73 | } else {
74 | NSDictionary *attributes = @{(__bridge id)kSecValueData : item};
75 | status = SecItemUpdate((__bridge CFDictionaryRef)multiplatformQuery,
76 | (__bridge CFDictionaryRef)attributes);
77 | }
78 |
79 | if (status == noErr) {
80 | if (outError) {
81 | *outError = nil;
82 | }
83 | return YES;
84 | }
85 |
86 | NSString *function = existingItem ? @"SecItemUpdate" : @"SecItemAdd";
87 | if (outError) {
88 | *outError = [self keychainErrorWithFunction:function status:status];
89 | }
90 | return NO;
91 | }
92 |
93 | + (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError {
94 | NSDictionary *deleteItemQuery = [[self class] multiplatformQueryWithQuery:query];
95 |
96 | OSStatus status = SecItemDelete((__bridge CFDictionaryRef)deleteItemQuery);
97 |
98 | if (status == noErr || status == errSecItemNotFound) {
99 | if (outError) {
100 | *outError = nil;
101 | }
102 | return YES;
103 | }
104 |
105 | if (outError) {
106 | *outError = [self keychainErrorWithFunction:@"SecItemDelete" status:status];
107 | }
108 | return NO;
109 | }
110 |
111 | #pragma mark - Private
112 |
113 | /// Returns a `NSDictionary` query that behaves the same across all platforms.
114 | /// - Note: In practice, this API only makes a difference to keychain queries on macOS.
115 | /// See go/firebase-macos-keychain-popups for details.
116 | /// - Parameter query: A query to create the protected keychain query with.
117 | + (NSDictionary *)multiplatformQueryWithQuery:(NSDictionary *)query {
118 | NSMutableDictionary *multiplatformQuery = [query mutableCopy];
119 | if (@available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *)) {
120 | multiplatformQuery[(__bridge id)kSecUseDataProtectionKeychain] = (__bridge id)kCFBooleanTrue;
121 | }
122 | return [multiplatformQuery copy];
123 | }
124 |
125 | #pragma mark - Errors
126 |
127 | + (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status {
128 | NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status];
129 | NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey : failureReason};
130 | return [NSError errorWithDomain:kGULKeychainUtilsErrorDomain code:0 userInfo:userInfo];
131 | }
132 |
133 | @end
134 |
--------------------------------------------------------------------------------
/GoogleUtilities/Logger/Public/GoogleUtilities/GULLoggerLevel.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | /// The log levels used by internal logging.
22 | typedef NS_ENUM(NSInteger, GULLoggerLevel) {
23 | /// Error level, corresponding to `OS_LOG_TYPE_ERROR`.
24 | GULLoggerLevelError = 3, // For backwards compatibility, the enum value matches `ASL_LEVEL_ERR`.
25 |
26 | /// Warning level, corresponding to `OS_LOG_TYPE_DEFAULT`.
27 | ///
28 | /// > Note: Since OSLog doesn't have a WARNING type, this is equivalent to `GULLoggerLevelNotice`.
29 | GULLoggerLevelWarning = 4, // For backwards compatibility, the value matches `ASL_LEVEL_WARNING`.
30 |
31 | /// Notice level, corresponding to `OS_LOG_TYPE_DEFAULT`.
32 | GULLoggerLevelNotice = 5, // For backwards compatibility, the value matches `ASL_LEVEL_NOTICE`.
33 |
34 | /// Info level, corresponding to `OS_LOG_TYPE_INFO`.
35 | GULLoggerLevelInfo = 6, // For backwards compatibility, the enum value matches `ASL_LEVEL_INFO`.
36 |
37 | /// Debug level, corresponding to `OS_LOG_TYPE_DEBUG`.
38 | GULLoggerLevelDebug = 7, // For backwards compatibility, the value matches `ASL_LEVEL_DEBUG`.
39 |
40 | /// The minimum (most severe) supported logging level.
41 | GULLoggerLevelMin = GULLoggerLevelError,
42 |
43 | /// The maximum (least severe) supported logging level.
44 | GULLoggerLevelMax = GULLoggerLevelDebug
45 | } NS_SWIFT_NAME(GoogleLoggerLevel);
46 |
47 | NS_ASSUME_NONNULL_END
48 |
--------------------------------------------------------------------------------
/GoogleUtilities/Logger/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/GoogleUtilities/MethodSwizzler/GULSwizzler.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import "GoogleUtilities/MethodSwizzler/Public/GoogleUtilities/GULSwizzler.h"
16 |
17 | #import
18 |
19 | #ifdef DEBUG
20 | #import "GoogleUtilities/Common/GULLoggerCodes.h"
21 | #import "GoogleUtilities/Logger/Public/GoogleUtilities/GULLogger.h"
22 |
23 | static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/MethodSwizzler]";
24 | #endif
25 |
26 | dispatch_queue_t GetGULSwizzlingQueue(void) {
27 | static dispatch_queue_t queue;
28 | static dispatch_once_t onceToken;
29 | dispatch_once(&onceToken, ^{
30 | queue = dispatch_queue_create("com.google.GULSwizzler", DISPATCH_QUEUE_SERIAL);
31 | });
32 | return queue;
33 | }
34 |
35 | @implementation GULSwizzler
36 |
37 | + (void)swizzleClass:(Class)aClass
38 | selector:(SEL)selector
39 | isClassSelector:(BOOL)isClassSelector
40 | withBlock:(nullable id)block {
41 | dispatch_sync(GetGULSwizzlingQueue(), ^{
42 | NSAssert(selector, @"The selector cannot be NULL");
43 | NSAssert(aClass, @"The class cannot be Nil");
44 | Class resolvedClass = aClass;
45 | Method method = nil;
46 | if (isClassSelector) {
47 | method = class_getClassMethod(aClass, selector);
48 | resolvedClass = object_getClass(aClass);
49 | } else {
50 | method = class_getInstanceMethod(aClass, selector);
51 | }
52 | NSAssert(method, @"You're attempting to swizzle a method that doesn't exist. (%@, %@)",
53 | NSStringFromClass(resolvedClass), NSStringFromSelector(selector));
54 | IMP newImp = imp_implementationWithBlock(block);
55 | #ifdef DEBUG
56 | IMP currentImp = class_getMethodImplementation(resolvedClass, selector);
57 | Class class = NSClassFromString(@"GULSwizzlingCache");
58 | if (class) {
59 | SEL cacheSelector = NSSelectorFromString(@"cacheCurrentIMP:forNewIMP:forClass:withSelector:");
60 | NSMethodSignature *methodSignature = [class methodSignatureForSelector:cacheSelector];
61 | if (methodSignature != nil) {
62 | NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature];
63 | [inv setSelector:cacheSelector];
64 | [inv setTarget:class];
65 | [inv setArgument:&(currentImp) atIndex:2];
66 | [inv setArgument:&(newImp) atIndex:3];
67 | [inv setArgument:&(resolvedClass) atIndex:4];
68 | [inv setArgument:(void *_Nonnull)&(selector) atIndex:5];
69 | [inv invoke];
70 | }
71 | }
72 | #endif
73 |
74 | const char *typeEncoding = method_getTypeEncoding(method);
75 | __unused IMP originalImpOfClass =
76 | class_replaceMethod(resolvedClass, selector, newImp, typeEncoding);
77 |
78 | #ifdef DEBUG
79 | // If !originalImpOfClass, then the IMP came from a superclass.
80 | if (originalImpOfClass) {
81 | SEL selector = NSSelectorFromString(@"originalIMPOfCurrentIMP:");
82 | NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector];
83 | if (methodSignature != nil) {
84 | NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature];
85 | [inv setSelector:selector];
86 | [inv setTarget:class];
87 | [inv setArgument:&(currentImp) atIndex:2];
88 | [inv invoke];
89 | IMP testOriginal;
90 | [inv getReturnValue:&testOriginal];
91 | if (originalImpOfClass != testOriginal) {
92 | GULOSLogWarning(
93 | kGULLogSubsystem, kGULLoggerSwizzler, NO,
94 | [NSString
95 | stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeMethodSwizzling000],
96 | @"Swizzling class: %@ SEL:%@ after it has been previously been swizzled.",
97 | NSStringFromClass(resolvedClass), NSStringFromSelector(selector));
98 | }
99 | }
100 | }
101 | #endif
102 | });
103 | }
104 |
105 | + (nullable IMP)currentImplementationForClass:(Class)aClass
106 | selector:(SEL)selector
107 | isClassSelector:(BOOL)isClassSelector {
108 | NSAssert(selector, @"The selector cannot be NULL");
109 | NSAssert(aClass, @"The class cannot be Nil");
110 | if (selector == NULL || aClass == nil) {
111 | return nil;
112 | }
113 | __block IMP currentIMP = nil;
114 | dispatch_sync(GetGULSwizzlingQueue(), ^{
115 | Method method = nil;
116 | if (isClassSelector) {
117 | method = class_getClassMethod(aClass, selector);
118 | } else {
119 | method = class_getInstanceMethod(aClass, selector);
120 | }
121 | NSAssert(method, @"The Method for this class/selector combo doesn't exist (%@, %@).",
122 | NSStringFromClass(aClass), NSStringFromSelector(selector));
123 | if (method == nil) {
124 | return;
125 | }
126 | currentIMP = method_getImplementation(method);
127 | NSAssert(currentIMP, @"The IMP for this class/selector combo doesn't exist (%@, %@).",
128 | NSStringFromClass(aClass), NSStringFromSelector(selector));
129 | });
130 | return currentIMP;
131 | }
132 |
133 | + (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector {
134 | Method method = isClassSelector ? class_getClassMethod(aClass, selector)
135 | : class_getInstanceMethod(aClass, selector);
136 | return method != nil;
137 | }
138 |
139 | + (NSArray *)ivarObjectsForObject:(id)object {
140 | NSMutableArray *array = [NSMutableArray array];
141 | unsigned int count;
142 | Ivar *vars = class_copyIvarList([object class], &count);
143 | for (NSUInteger i = 0; i < count; i++) {
144 | const char *typeEncoding = ivar_getTypeEncoding(vars[i]);
145 | // Check to see if the ivar is an object.
146 | if (strncmp(typeEncoding, "@", 1) == 0) {
147 | id ivarObject = object_getIvar(object, vars[i]);
148 | [array addObject:ivarObject];
149 | }
150 | }
151 | free(vars);
152 | return array;
153 | }
154 | @end
155 |
--------------------------------------------------------------------------------
/GoogleUtilities/MethodSwizzler/Public/GoogleUtilities/GULSwizzler.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | /** This class handles the runtime manipulation necessary to instrument selectors. It stores the
22 | * classes and selectors that have been swizzled, and runs all operations on its own queue.
23 | */
24 | @interface GULSwizzler : NSObject
25 |
26 | /** Manipulates the Objective-C runtime to replace the original IMP with the supplied block.
27 | *
28 | * @param aClass The class to swizzle.
29 | * @param selector The selector of the class to swizzle.
30 | * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector.
31 | * @param block The block that replaces the original IMP.
32 | */
33 | + (void)swizzleClass:(Class)aClass
34 | selector:(SEL)selector
35 | isClassSelector:(BOOL)isClassSelector
36 | withBlock:(nullable id)block;
37 |
38 | /** Returns the current IMP for the given class and selector.
39 | *
40 | * @param aClass The class to use.
41 | * @param selector The selector to find the implementation of.
42 | * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector.
43 | * @return The implementation of the selector in the runtime.
44 | */
45 | + (nullable IMP)currentImplementationForClass:(Class)aClass
46 | selector:(SEL)selector
47 | isClassSelector:(BOOL)isClassSelector;
48 |
49 | /** Checks the runtime to see if a selector exists on a class. If a property is declared as
50 | * @dynamic, we have a reverse swizzling situation, where the implementation of a method exists
51 | * only in concrete subclasses, and NOT in the superclass. We can detect that situation using
52 | * this helper method. Similarly, we can detect situations where a class doesn't implement a
53 | * protocol method.
54 | *
55 | * @param selector The selector to check for.
56 | * @param aClass The class to check.
57 | * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector.
58 | * @return YES if the method was found in this selector/class combination, NO otherwise.
59 | */
60 | + (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector;
61 |
62 | /** Returns a list of all Objective-C (and not primitive) ivars contained by the given object.
63 | *
64 | * @param object The object whose ivars will be iterated.
65 | * @return The list of ivar objects.
66 | */
67 | + (NSArray *)ivarObjectsForObject:(id)object;
68 |
69 | @end
70 |
71 | NS_ASSUME_NONNULL_END
72 |
--------------------------------------------------------------------------------
/GoogleUtilities/MethodSwizzler/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/GoogleUtilities/NSData+zlib/Public/GoogleUtilities/GULNSData+zlib.h:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Google
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 | #import
16 |
17 | NS_ASSUME_NONNULL_BEGIN
18 |
19 | /// This is a copy of Google Toolbox for Mac library to avoid creating an extra framework.
20 |
21 | // NOTE: For 64bit, none of these apis handle input sizes >32bits, they will return nil when given
22 | // such data. To handle data of that size you really should be streaming it rather then doing it all
23 | // in memory.
24 |
25 | @interface NSData (GULGzip)
26 |
27 | /// Returns an data as the result of decompressing the payload of |data|.The data to decompress must
28 | /// be a gzipped payloads.
29 | + (nullable NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error;
30 |
31 | /// Returns an compressed data with the result of gzipping the payload of |data|. Uses the default
32 | /// compression level.
33 | + (nullable NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error;
34 |
35 | FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorDomain;
36 | FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorKey; // NSNumber
37 | FOUNDATION_EXPORT NSString *const GULNSDataZlibRemainingBytesKey; // NSNumber
38 |
39 | typedef NS_ENUM(NSInteger, GULNSDataZlibError) {
40 | GULNSDataZlibErrorGreaterThan32BitsToCompress = 1024,
41 | // An internal zlib error.
42 | // GULNSDataZlibErrorKey will contain the error value.
43 | // NSLocalizedDescriptionKey may contain an error string from zlib.
44 | // Look in zlib.h for list of errors.
45 | GULNSDataZlibErrorInternal,
46 | // There was left over data in the buffer that was not used.
47 | // GULNSDataZlibRemainingBytesKey will contain number of remaining bytes.
48 | GULNSDataZlibErrorDataRemaining
49 | };
50 |
51 | @end
52 |
53 | NS_ASSUME_NONNULL_END
54 |
--------------------------------------------------------------------------------
/GoogleUtilities/NSData+zlib/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/GULMutableDictionary.m:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google
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 | #import "GoogleUtilities/Network/Public/GoogleUtilities/GULMutableDictionary.h"
16 |
17 | @implementation GULMutableDictionary {
18 | /// The mutable dictionary.
19 | NSMutableDictionary *_objects;
20 |
21 | /// Serial synchronization queue. All reads should use dispatch_sync, while writes use
22 | /// dispatch_async.
23 | dispatch_queue_t _queue;
24 | }
25 |
26 | - (instancetype)init {
27 | self = [super init];
28 |
29 | if (self) {
30 | _objects = [[NSMutableDictionary alloc] init];
31 | _queue = dispatch_queue_create("GULMutableDictionary", DISPATCH_QUEUE_SERIAL);
32 | }
33 |
34 | return self;
35 | }
36 |
37 | - (NSString *)description {
38 | __block NSString *description;
39 | dispatch_sync(_queue, ^{
40 | description = self->_objects.description;
41 | });
42 | return description;
43 | }
44 |
45 | - (id)objectForKey:(id)key {
46 | __block id object;
47 | dispatch_sync(_queue, ^{
48 | object = [self->_objects objectForKey:key];
49 | });
50 | return object;
51 | }
52 |
53 | - (void)setObject:(id)object forKey:(id)key {
54 | dispatch_async(_queue, ^{
55 | [self->_objects setObject:object forKey:key];
56 | });
57 | }
58 |
59 | - (void)removeObjectForKey:(id)key {
60 | dispatch_async(_queue, ^{
61 | [self->_objects removeObjectForKey:key];
62 | });
63 | }
64 |
65 | - (void)removeAllObjects {
66 | dispatch_async(_queue, ^{
67 | [self->_objects removeAllObjects];
68 | });
69 | }
70 |
71 | - (NSUInteger)count {
72 | __block NSUInteger count;
73 | dispatch_sync(_queue, ^{
74 | count = self->_objects.count;
75 | });
76 | return count;
77 | }
78 |
79 | - (id)objectForKeyedSubscript:(id)key {
80 | __block id object;
81 | dispatch_sync(_queue, ^{
82 | object = self->_objects[key];
83 | });
84 | return object;
85 | }
86 |
87 | - (void)setObject:(id)obj forKeyedSubscript:(id)key {
88 | dispatch_async(_queue, ^{
89 | self->_objects[key] = obj;
90 | });
91 | }
92 |
93 | - (NSDictionary *)dictionary {
94 | __block NSDictionary *dictionary;
95 | dispatch_sync(_queue, ^{
96 | dictionary = [self->_objects copy];
97 | });
98 | return dictionary;
99 | }
100 |
101 | @end
102 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/GULNetworkConstants.m:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google
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 | #import "GoogleUtilities/Network/Public/GoogleUtilities/GULNetworkConstants.h"
16 | #import "GoogleUtilities/Logger/Public/GoogleUtilities/GULLogger.h"
17 |
18 | #import
19 |
20 | NSString *const kGULNetworkBackgroundSessionConfigIDPrefix = @"com.gul.network.background-upload";
21 | NSString *const kGULNetworkApplicationSupportSubdirectory = @"GUL/Network";
22 | NSString *const kGULNetworkTempDirectoryName = @"GULNetworkTemporaryDirectory";
23 | const NSTimeInterval kGULNetworkTempFolderExpireTime = 60 * 60; // 1 hour
24 | const NSTimeInterval kGULNetworkTimeOutInterval = 60; // 1 minute.
25 | NSString *const kGULNetworkReachabilityHost = @"app-measurement.com";
26 | NSString *const kGULNetworkErrorContext = @"Context";
27 |
28 | const int kGULNetworkHTTPStatusOK = 200;
29 | const int kGULNetworkHTTPStatusNoContent = 204;
30 | const int kGULNetworkHTTPStatusCodeMultipleChoices = 300;
31 | const int kGULNetworkHTTPStatusCodeMovedPermanently = 301;
32 | const int kGULNetworkHTTPStatusCodeFound = 302;
33 | const int kGULNetworkHTTPStatusCodeNotModified = 304;
34 | const int kGULNetworkHTTPStatusCodeMovedTemporarily = 307;
35 | const int kGULNetworkHTTPStatusCodeNotFound = 404;
36 | const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic = 429;
37 | const int kGULNetworkHTTPStatusCodeUnavailable = 503;
38 |
39 | NSString *const kGULNetworkErrorDomain = @"com.gul.network.ErrorDomain";
40 |
41 | GULLoggerService kGULLoggerNetwork = @"[GULNetwork]";
42 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/GULNetworkInternal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | #import "GoogleUtilities/Logger/Public/GoogleUtilities/GULLogger.h"
20 |
21 | extern NSString *const kGULNetworkErrorDomain;
22 |
23 | /// The logger service for GULNetwork.
24 | extern GULLoggerService kGULLoggerNetwork;
25 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/Public/GoogleUtilities/GULMutableDictionary.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | /// A mutable dictionary that provides atomic accessor and mutators.
22 | @interface GULMutableDictionary : NSObject
23 |
24 | /// Returns an object given a key in the dictionary or nil if not found.
25 | - (id)objectForKey:(id)key;
26 |
27 | /// Updates the object given its key or adds it to the dictionary if it is not in the dictionary.
28 | - (void)setObject:(id)object forKey:(id)key;
29 |
30 | /// Removes the object given its session ID from the dictionary.
31 | - (void)removeObjectForKey:(id)key;
32 |
33 | /// Removes all objects.
34 | - (void)removeAllObjects;
35 |
36 | /// Returns the number of current objects in the dictionary.
37 | - (NSUInteger)count;
38 |
39 | /// Returns an object given a key in the dictionary or nil if not found.
40 | - (id)objectForKeyedSubscript:(id)key;
41 |
42 | /// Updates the object given its key or adds it to the dictionary if it is not in the dictionary.
43 | - (void)setObject:(id)obj forKeyedSubscript:(id)key;
44 |
45 | /// Returns the immutable dictionary.
46 | - (NSDictionary *)dictionary;
47 |
48 | @end
49 |
50 | NS_ASSUME_NONNULL_END
51 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/Public/GoogleUtilities/GULNetwork.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | #import "GULNetworkConstants.h"
20 | #import "GULNetworkLoggerProtocol.h"
21 | #import "GULNetworkURLSession.h"
22 |
23 | NS_ASSUME_NONNULL_BEGIN
24 |
25 | /// Delegate protocol for GULNetwork events.
26 | @protocol GULNetworkReachabilityDelegate
27 |
28 | /// Tells the delegate to handle events when the network reachability changes to connected or not
29 | /// connected.
30 | - (void)reachabilityDidChange;
31 |
32 | @end
33 |
34 | /// The Network component that provides network status and handles network requests and responses.
35 | /// This is not thread safe.
36 | ///
37 | /// NOTE:
38 | /// User must add FIRAnalytics handleEventsForBackgroundURLSessionID:completionHandler to the
39 | /// AppDelegate application:handleEventsForBackgroundURLSession:completionHandler:
40 | @interface GULNetwork : NSObject
41 |
42 | /// Indicates if network connectivity is available.
43 | @property(nonatomic, readonly, getter=isNetworkConnected) BOOL networkConnected;
44 |
45 | /// Indicates if there are any uploads in progress.
46 | @property(nonatomic, readonly, getter=hasUploadInProgress) BOOL uploadInProgress;
47 |
48 | /// An optional delegate that can be used in the event when network reachability changes.
49 | @property(nonatomic, weak) id reachabilityDelegate;
50 |
51 | /// An optional delegate that can be used to log messages, warnings or errors that occur in the
52 | /// network operations.
53 | @property(nonatomic, weak) id loggerDelegate;
54 |
55 | /// Indicates whether the logger should display debug messages.
56 | @property(nonatomic, assign) BOOL isDebugModeEnabled;
57 |
58 | /// The time interval in seconds for the network request to timeout.
59 | @property(nonatomic, assign) NSTimeInterval timeoutInterval;
60 |
61 | /// Initializes with the default reachability host.
62 | - (instancetype)init;
63 |
64 | /// Initializes with a custom reachability host.
65 | - (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost;
66 |
67 | /// Handles events when background session with the given ID has finished.
68 | + (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID
69 | completionHandler:(GULNetworkSystemCompletionHandler)completionHandler;
70 |
71 | /// Compresses and sends a POST request with the provided data to the URL. The session will be
72 | /// background session if usingBackgroundSession is YES. Otherwise, the POST session is default
73 | /// session. Returns a session ID or nil if an error occurs.
74 | - (nullable NSString *)postURL:(NSURL *)url
75 | payload:(NSData *)payload
76 | queue:(nullable dispatch_queue_t)queue
77 | usingBackgroundSession:(BOOL)usingBackgroundSession
78 | completionHandler:(GULNetworkCompletionHandler)handler;
79 |
80 | /// Compresses and sends a POST request with the provided headers and data to the URL. The session
81 | /// will be background session if usingBackgroundSession is YES. Otherwise, the POST session is
82 | /// default session. Returns a session ID or nil if an error occurs.
83 | - (nullable NSString *)postURL:(NSURL *)url
84 | headers:(nullable NSDictionary *)headers
85 | payload:(NSData *)payload
86 | queue:(nullable dispatch_queue_t)queue
87 | usingBackgroundSession:(BOOL)usingBackgroundSession
88 | completionHandler:(GULNetworkCompletionHandler)handler;
89 |
90 | /// Sends a GET request with the provided data to the URL. The session will be background session
91 | /// if usingBackgroundSession is YES. Otherwise, the GET session is default session. Returns a
92 | /// session ID or nil if an error occurs.
93 | - (nullable NSString *)getURL:(NSURL *)url
94 | headers:(nullable NSDictionary *)headers
95 | queue:(nullable dispatch_queue_t)queue
96 | usingBackgroundSession:(BOOL)usingBackgroundSession
97 | completionHandler:(GULNetworkCompletionHandler)handler;
98 |
99 | @end
100 |
101 | NS_ASSUME_NONNULL_END
102 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/Public/GoogleUtilities/GULNetworkConstants.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | /// Error codes in Firebase Network error domain.
22 | /// Note: these error codes should never change. It would make it harder to decode the errors if
23 | /// we inadvertently altered any of these codes in a future SDK version.
24 | typedef NS_ENUM(NSInteger, GULNetworkErrorCode) {
25 | /// Unknown error.
26 | GULNetworkErrorCodeUnknown = 0,
27 | /// Error occurs when the request URL is invalid.
28 | GULErrorCodeNetworkInvalidURL = 1,
29 | /// Error occurs when request cannot be constructed.
30 | GULErrorCodeNetworkRequestCreation = 2,
31 | /// Error occurs when payload cannot be compressed.
32 | GULErrorCodeNetworkPayloadCompression = 3,
33 | /// Error occurs when session task cannot be created.
34 | GULErrorCodeNetworkSessionTaskCreation = 4,
35 | /// Error occurs when there is no response.
36 | GULErrorCodeNetworkInvalidResponse = 5
37 | };
38 |
39 | #pragma mark - Network constants
40 |
41 | /// The prefix of the ID of the background session.
42 | extern NSString *const kGULNetworkBackgroundSessionConfigIDPrefix;
43 |
44 | /// The sub directory to store the files of data that is being uploaded in the background.
45 | extern NSString *const kGULNetworkApplicationSupportSubdirectory;
46 |
47 | /// Name of the temporary directory that stores files for background uploading.
48 | extern NSString *const kGULNetworkTempDirectoryName;
49 |
50 | /// The period when the temporary uploading file can stay.
51 | extern const NSTimeInterval kGULNetworkTempFolderExpireTime;
52 |
53 | /// The default network request timeout interval.
54 | extern const NSTimeInterval kGULNetworkTimeOutInterval;
55 |
56 | /// The host to check the reachability of the network.
57 | extern NSString *const kGULNetworkReachabilityHost;
58 |
59 | /// The key to get the error context of the UserInfo.
60 | extern NSString *const kGULNetworkErrorContext;
61 |
62 | #pragma mark - Network Status Code
63 |
64 | extern const int kGULNetworkHTTPStatusOK;
65 | extern const int kGULNetworkHTTPStatusNoContent;
66 | extern const int kGULNetworkHTTPStatusCodeMultipleChoices;
67 | extern const int kGULNetworkHTTPStatusCodeMovedPermanently;
68 | extern const int kGULNetworkHTTPStatusCodeFound;
69 | extern const int kGULNetworkHTTPStatusCodeNotModified;
70 | extern const int kGULNetworkHTTPStatusCodeMovedTemporarily;
71 | extern const int kGULNetworkHTTPStatusCodeNotFound;
72 | extern const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic;
73 | extern const int kGULNetworkHTTPStatusCodeUnavailable;
74 |
75 | NS_ASSUME_NONNULL_END
76 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/Public/GoogleUtilities/GULNetworkLoggerProtocol.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | #import "GULNetworkMessageCode.h"
20 |
21 | NS_ASSUME_NONNULL_BEGIN
22 |
23 | /// The log levels used by GULNetworkLogger.
24 | typedef NS_ENUM(NSInteger, GULNetworkLogLevel) {
25 | kGULNetworkLogLevelError = 3,
26 | kGULNetworkLogLevelWarning = 4,
27 | kGULNetworkLogLevelInfo = 6,
28 | kGULNetworkLogLevelDebug = 7,
29 | };
30 |
31 | @protocol GULNetworkLoggerDelegate
32 |
33 | @required
34 | /// Tells the delegate to log a message with an array of contexts and the log level.
35 | - (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel
36 | messageCode:(GULNetworkMessageCode)messageCode
37 | message:(NSString *)message
38 | contexts:(NSArray *)contexts;
39 |
40 | /// Tells the delegate to log a message with a context and the log level.
41 | - (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel
42 | messageCode:(GULNetworkMessageCode)messageCode
43 | message:(NSString *)message
44 | context:(id)context;
45 |
46 | /// Tells the delegate to log a message with the log level.
47 | - (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel
48 | messageCode:(GULNetworkMessageCode)messageCode
49 | message:(NSString *)message;
50 |
51 | @end
52 |
53 | NS_ASSUME_NONNULL_END
54 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/Public/GoogleUtilities/GULNetworkMessageCode.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | // Make sure these codes do not overlap with any contained in the FIRAMessageCode enum.
22 | typedef NS_ENUM(NSInteger, GULNetworkMessageCode) {
23 | // GULNetwork.m
24 | kGULNetworkMessageCodeNetwork000 = 900000, // I-NET900000
25 | kGULNetworkMessageCodeNetwork001 = 900001, // I-NET900001
26 | kGULNetworkMessageCodeNetwork002 = 900002, // I-NET900002
27 | kGULNetworkMessageCodeNetwork003 = 900003, // I-NET900003
28 | // GULNetworkURLSession.m
29 | kGULNetworkMessageCodeURLSession000 = 901000, // I-NET901000
30 | kGULNetworkMessageCodeURLSession001 = 901001, // I-NET901001
31 | kGULNetworkMessageCodeURLSession002 = 901002, // I-NET901002
32 | kGULNetworkMessageCodeURLSession003 = 901003, // I-NET901003
33 | kGULNetworkMessageCodeURLSession004 = 901004, // I-NET901004
34 | kGULNetworkMessageCodeURLSession005 = 901005, // I-NET901005
35 | kGULNetworkMessageCodeURLSession006 = 901006, // I-NET901006
36 | kGULNetworkMessageCodeURLSession007 = 901007, // I-NET901007
37 | kGULNetworkMessageCodeURLSession008 = 901008, // I-NET901008
38 | kGULNetworkMessageCodeURLSession009 = 901009, // I-NET901009
39 | kGULNetworkMessageCodeURLSession010 = 901010, // I-NET901010
40 | kGULNetworkMessageCodeURLSession011 = 901011, // I-NET901011
41 | kGULNetworkMessageCodeURLSession012 = 901012, // I-NET901012
42 | kGULNetworkMessageCodeURLSession013 = 901013, // I-NET901013
43 | kGULNetworkMessageCodeURLSession014 = 901014, // I-NET901014
44 | kGULNetworkMessageCodeURLSession015 = 901015, // I-NET901015
45 | kGULNetworkMessageCodeURLSession016 = 901016, // I-NET901016
46 | kGULNetworkMessageCodeURLSession017 = 901017, // I-NET901017
47 | kGULNetworkMessageCodeURLSession018 = 901018, // I-NET901018
48 | kGULNetworkMessageCodeURLSession019 = 901019, // I-NET901019
49 | };
50 |
51 | NS_ASSUME_NONNULL_END
52 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/Public/GoogleUtilities/GULNetworkURLSession.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | #import "GULNetworkLoggerProtocol.h"
20 |
21 | NS_ASSUME_NONNULL_BEGIN
22 |
23 | typedef void (^GULNetworkCompletionHandler)(NSHTTPURLResponse *_Nullable response,
24 | NSData *_Nullable data,
25 | NSError *_Nullable error);
26 | typedef void (^GULNetworkURLSessionCompletionHandler)(NSHTTPURLResponse *_Nullable response,
27 | NSData *_Nullable data,
28 | NSString *sessionID,
29 | NSError *_Nullable error);
30 | typedef void (^GULNetworkSystemCompletionHandler)(void);
31 |
32 | /// The protocol that uses NSURLSession for iOS >= 7.0 to handle requests and responses.
33 | @interface GULNetworkURLSession : NSObject
34 |
35 | /// Indicates whether the background network is enabled. Default value is NO.
36 | @property(nonatomic, getter=isBackgroundNetworkEnabled) BOOL backgroundNetworkEnabled;
37 |
38 | /// The logger delegate to log message, errors or warnings that occur during the network operations.
39 | @property(nonatomic, weak, nullable) id loggerDelegate;
40 |
41 | /// Calls the system provided completion handler after the background session is finished.
42 | + (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID
43 | completionHandler:(GULNetworkSystemCompletionHandler)completionHandler;
44 |
45 | /// Initializes with logger delegate.
46 | - (instancetype)initWithNetworkLoggerDelegate:
47 | (nullable id)networkLoggerDelegate NS_DESIGNATED_INITIALIZER;
48 |
49 | - (instancetype)init NS_UNAVAILABLE;
50 |
51 | /// Sends an asynchronous POST request and calls the provided completion handler when the request
52 | /// completes or when errors occur, and returns an ID of the session/connection.
53 | - (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request
54 | completionHandler:(GULNetworkURLSessionCompletionHandler)handler;
55 |
56 | /// Sends an asynchronous GET request and calls the provided completion handler when the request
57 | /// completes or when errors occur, and returns an ID of the session.
58 | - (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request
59 | completionHandler:(GULNetworkURLSessionCompletionHandler)handler;
60 |
61 | NS_ASSUME_NONNULL_END
62 | @end
63 |
--------------------------------------------------------------------------------
/GoogleUtilities/Network/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 | NSPrivacyAccessedAPIType
17 | NSPrivacyAccessedAPICategoryFileTimestamp
18 | NSPrivacyAccessedAPITypeReasons
19 |
20 | C617.1
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/GoogleUtilities/Privacy/Empty.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2024 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 | // This file is intentionally empty and satisfies SwiftPM's requirement that a
16 | // target contain sources.
17 |
--------------------------------------------------------------------------------
/GoogleUtilities/Privacy/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 | NSPrivacyAccessedAPIType
17 | NSPrivacyAccessedAPICategoryFileTimestamp
18 | NSPrivacyAccessedAPITypeReasons
19 |
20 | C617.1
21 |
22 |
23 |
24 | NSPrivacyAccessedAPIType
25 | NSPrivacyAccessedAPICategoryUserDefaults
26 | NSPrivacyAccessedAPITypeReasons
27 |
28 | C56D.1
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import "GoogleUtilities/Reachability/Public/GoogleUtilities/GULReachabilityChecker.h"
18 |
19 | #if !TARGET_OS_WATCH
20 | typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator,
21 | const char *host);
22 |
23 | typedef Boolean (*GULReachabilitySetCallbackFn)(SCNetworkReachabilityRef target,
24 | SCNetworkReachabilityCallBack callback,
25 | SCNetworkReachabilityContext *context);
26 | typedef Boolean (*GULReachabilityScheduleWithRunLoopFn)(SCNetworkReachabilityRef target,
27 | CFRunLoopRef runLoop,
28 | CFStringRef runLoopMode);
29 | typedef Boolean (*GULReachabilityUnscheduleFromRunLoopFn)(SCNetworkReachabilityRef target,
30 | CFRunLoopRef runLoop,
31 | CFStringRef runLoopMode);
32 |
33 | typedef void (*GULReachabilityReleaseFn)(CFTypeRef cf);
34 |
35 | struct GULReachabilityApi {
36 | GULReachabilityCreateWithNameFn createWithNameFn;
37 | GULReachabilitySetCallbackFn setCallbackFn;
38 | GULReachabilityScheduleWithRunLoopFn scheduleWithRunLoopFn;
39 | GULReachabilityUnscheduleFromRunLoopFn unscheduleFromRunLoopFn;
40 | GULReachabilityReleaseFn releaseFn;
41 | };
42 | #endif
43 | @interface GULReachabilityChecker (Internal)
44 |
45 | - (const struct GULReachabilityApi *)reachabilityApi;
46 | - (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi;
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/GoogleUtilities/Reachability/GULReachabilityMessageCode.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 |
19 | // Make sure these codes do not overlap with any contained in the FIRAMessageCode enum.
20 | typedef NS_ENUM(NSInteger, GULReachabilityMessageCode) {
21 | // GULReachabilityChecker.m
22 | kGULReachabilityMessageCode000 = 902000, // I-NET902000
23 | kGULReachabilityMessageCode001 = 902001, // I-NET902001
24 | kGULReachabilityMessageCode002 = 902002, // I-NET902002
25 | kGULReachabilityMessageCode003 = 902003, // I-NET902003
26 | kGULReachabilityMessageCode004 = 902004, // I-NET902004
27 | kGULReachabilityMessageCode005 = 902005, // I-NET902005
28 | kGULReachabilityMessageCode006 = 902006, // I-NET902006
29 | };
30 |
--------------------------------------------------------------------------------
/GoogleUtilities/Reachability/Public/GoogleUtilities/GULReachabilityChecker.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google
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 | #import
18 | #if !TARGET_OS_WATCH
19 | #import
20 | #endif
21 |
22 | NS_ASSUME_NONNULL_BEGIN
23 |
24 | /// Reachability Status
25 | typedef enum {
26 | kGULReachabilityUnknown, ///< Have not yet checked or been notified whether host is reachable.
27 | kGULReachabilityNotReachable, ///< Host is not reachable.
28 | kGULReachabilityViaWifi, ///< Host is reachable via Wifi.
29 | kGULReachabilityViaCellular, ///< Host is reachable via cellular.
30 | } GULReachabilityStatus;
31 |
32 | const NSString *GULReachabilityStatusString(GULReachabilityStatus status);
33 |
34 | @class GULReachabilityChecker;
35 |
36 | /// Google Analytics iOS Reachability Checker.
37 | @protocol GULReachabilityDelegate
38 | @required
39 | /// Called when network status has changed.
40 | - (void)reachability:(GULReachabilityChecker *)reachability
41 | statusChanged:(GULReachabilityStatus)status;
42 | @end
43 |
44 | /// Google Analytics iOS Network Status Checker.
45 | @interface GULReachabilityChecker : NSObject
46 |
47 | /// The last known reachability status, or GULReachabilityStatusUnknown if the
48 | /// checker is not active.
49 | @property(nonatomic, readonly) GULReachabilityStatus reachabilityStatus;
50 | /// The host to which reachability status is to be checked.
51 | @property(nonatomic, copy, readonly) NSString *host;
52 | /// The delegate to be notified of reachability status changes.
53 | @property(nonatomic, weak) id reachabilityDelegate;
54 | /// `YES` if the reachability checker is active, `NO` otherwise.
55 | @property(nonatomic, readonly) BOOL isActive;
56 |
57 | /// Initialize the reachability checker. Note that you must call start to begin checking for and
58 | /// receiving notifications about network status changes.
59 | ///
60 | /// @param reachabilityDelegate The delegate to be notified when reachability status to host
61 | /// changes.
62 | ///
63 | /// @param host The name of the host.
64 | ///
65 | - (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate
66 | withHost:(NSString *)host;
67 |
68 | - (instancetype)init NS_UNAVAILABLE;
69 |
70 | /// Start checking for reachability to the specified host. This has no effect if the status
71 | /// checker is already checking for connectivity.
72 | ///
73 | /// @return `YES` if initiating status checking was successful or the status checking has already
74 | /// been initiated, `NO` otherwise.
75 | - (BOOL)start;
76 |
77 | /// Stop checking for reachability to the specified host. This has no effect if the status
78 | /// checker is not checking for connectivity.
79 | - (void)stop;
80 |
81 | @end
82 |
83 | NS_ASSUME_NONNULL_END
84 |
--------------------------------------------------------------------------------
/GoogleUtilities/Reachability/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | /** A simple container class for representing the diff of a class. */
22 | @interface GULRuntimeClassDiff : NSObject
23 |
24 | /** The class this diff is with respect to. */
25 | @property(nonatomic, nullable, weak) Class aClass;
26 |
27 | /** The added class properties (as opposed to instance properties). */
28 | @property(nonatomic) NSSet *addedClassProperties;
29 |
30 | /** The added instance properties. */
31 | @property(nonatomic) NSSet *addedInstanceProperties;
32 |
33 | /** The added class selectors. */
34 | @property(nonatomic) NSSet *addedClassSelectors;
35 |
36 | /** The added instance selectors. */
37 | @property(nonatomic) NSSet *addedInstanceSelectors;
38 |
39 | /** The modified imps. */
40 | @property(nonatomic) NSSet *modifiedImps;
41 |
42 | @end
43 |
44 | NS_ASSUME_NONNULL_END
45 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.h"
16 |
17 | /** Computes the equality of possibly nil or empty NSSets.
18 | *
19 | * @param firstSet The first set of strings.
20 | * @param secondSet The second set of strings.
21 | * @return YES if both sets are zero length or nil, or the result of `isEqualToSet:`.
22 | */
23 | FOUNDATION_STATIC_INLINE
24 | BOOL IsEqual(NSSet *firstSet, NSSet *secondSet) {
25 | return ((!firstSet || firstSet.count == 0) && (!secondSet || secondSet.count == 0)) ||
26 | [firstSet isEqualToSet:secondSet];
27 | }
28 |
29 | @implementation GULRuntimeClassDiff
30 |
31 | - (NSUInteger)hash {
32 | return [_aClass hash] ^ [_addedClassProperties hash] ^ [_addedInstanceProperties hash] ^
33 | [_addedClassSelectors hash] ^ [_addedInstanceSelectors hash] ^ [_modifiedImps hash];
34 | }
35 |
36 | - (BOOL)isEqual:(id)object {
37 | GULRuntimeClassDiff *otherObject = (GULRuntimeClassDiff *)object;
38 | return _aClass == otherObject->_aClass &&
39 | IsEqual(_addedClassProperties, otherObject->_addedClassProperties) &&
40 | IsEqual(_addedInstanceProperties, otherObject->_addedInstanceProperties) &&
41 | IsEqual(_addedClassSelectors, otherObject->_addedClassSelectors) &&
42 | IsEqual(_addedInstanceSelectors, otherObject->_addedInstanceSelectors) &&
43 | IsEqual(_modifiedImps, otherObject->_modifiedImps);
44 | }
45 |
46 | - (NSString *)description {
47 | NSMutableString *description = [[NSMutableString alloc] init];
48 | [description appendFormat:@"%@:\n", NSStringFromClass(self.aClass)];
49 | if (_addedClassProperties.count) {
50 | [description appendString:@"\tAdded class properties:\n"];
51 | for (NSString *addedClassProperty in _addedClassProperties) {
52 | [description appendFormat:@"\t\t%@\n", addedClassProperty];
53 | }
54 | }
55 | if (_addedInstanceProperties.count) {
56 | [description appendString:@"\tAdded instance properties:\n"];
57 | for (NSString *addedInstanceProperty in _addedInstanceProperties) {
58 | [description appendFormat:@"\t\t%@\n", addedInstanceProperty];
59 | }
60 | }
61 | if (_addedClassSelectors.count) {
62 | [description appendString:@"\tAdded class selectors:\n"];
63 | for (NSString *addedClassSelector in _addedClassSelectors) {
64 | [description appendFormat:@"\t\t%@\n", addedClassSelector];
65 | }
66 | }
67 | if (_addedInstanceSelectors.count) {
68 | [description appendString:@"\tAdded instance selectors:\n"];
69 | for (NSString *addedInstanceSelector in _addedInstanceSelectors) {
70 | [description appendFormat:@"\t\t%@\n", addedInstanceSelector];
71 | }
72 | }
73 | if (_modifiedImps.count) {
74 | [description appendString:@"\tModified IMPs:\n"];
75 | for (NSString *modifiedImp in _modifiedImps) {
76 | [description appendFormat:@"\t\t%@\n", modifiedImp];
77 | }
78 | }
79 | return description;
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassSnapshot.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | @class GULRuntimeClassDiff;
20 |
21 | NS_ASSUME_NONNULL_BEGIN
22 |
23 | /** This class is able to capture the runtime state of a given class. */
24 | @interface GULRuntimeClassSnapshot : NSObject
25 |
26 | - (instancetype)init NS_UNAVAILABLE;
27 |
28 | /** Instantiates an instance of this class with the given class.
29 | *
30 | * @param aClass The class that will be snapshot.
31 | * @return An instance of this class.
32 | */
33 | - (instancetype)initWithClass:(Class)aClass NS_DESIGNATED_INITIALIZER;
34 |
35 | /** Captures the runtime state of this class. */
36 | - (void)capture;
37 |
38 | /** Calculates the diff between snapshots and returns a diff object populated with information.
39 | *
40 | * @param otherClassSnapshot The other snapshot to compare it to. It's assumed that the
41 | * otherClassSnapshot was created after the caller.
42 | * @return A diff object representing the diff between the two snapshots.
43 | */
44 | - (GULRuntimeClassDiff *)diff:(GULRuntimeClassSnapshot *)otherClassSnapshot;
45 |
46 | @end
47 |
48 | NS_ASSUME_NONNULL_END
49 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeDiff.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | @class GULRuntimeClassDiff;
20 |
21 | NS_ASSUME_NONNULL_BEGIN
22 |
23 | /** A simple container class for storing the diff of some runtime state. */
24 | @interface GULRuntimeDiff : NSObject
25 |
26 | /** The added classes. */
27 | @property(nonatomic) NSSet *addedClasses;
28 |
29 | /** The removed classes. */
30 | @property(nonatomic) NSSet *removedClasses;
31 |
32 | /** The diff objects for modified classes. */
33 | @property(nonatomic) NSSet *classDiffs;
34 |
35 | @end
36 |
37 | NS_ASSUME_NONNULL_END
38 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeDiff.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeDiff.h"
16 |
17 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.h"
18 |
19 | /** Computes the equality of possibly nil or empty NSSets.
20 | *
21 | * @param firstSet The first set of strings.
22 | * @param secondSet The second set of strings.
23 | * @return YES if both sets are zero length or nil, or the result of `isEqualToSet:`.
24 | */
25 | FOUNDATION_STATIC_INLINE
26 | BOOL IsEqual(NSSet *firstSet, NSSet *secondSet) {
27 | return ((!firstSet || firstSet.count == 0) && (!secondSet || secondSet.count == 0)) ||
28 | [firstSet isEqualToSet:secondSet];
29 | }
30 |
31 | @implementation GULRuntimeDiff
32 |
33 | - (NSUInteger)hash {
34 | return [_addedClasses hash] ^ [_removedClasses hash] ^ [_classDiffs hash];
35 | }
36 |
37 | - (BOOL)isEqual:(id)object {
38 | GULRuntimeDiff *otherObject = (GULRuntimeDiff *)object;
39 | return IsEqual(_addedClasses, otherObject->_addedClasses) &&
40 | IsEqual(_removedClasses, otherObject->_removedClasses) &&
41 | IsEqual(_classDiffs, otherObject->_classDiffs);
42 | }
43 |
44 | - (NSString *)description {
45 | NSMutableString *description = [[NSMutableString alloc] init];
46 | if (_addedClasses.count) {
47 | [description appendString:@"Added classes:\n"];
48 | for (NSString *classString in _addedClasses) {
49 | [description appendFormat:@"\t%@\n", classString];
50 | }
51 | }
52 | if (_removedClasses.count) {
53 | [description appendString:@"\nRemoved classes:\n"];
54 | for (NSString *classString in _removedClasses) {
55 | [description appendFormat:@"\t%@\n", classString];
56 | }
57 | }
58 | if (_classDiffs.count) {
59 | [description appendString:@"\nClass diffs:\n"];
60 | for (GULRuntimeClassDiff *classDiff in _classDiffs) {
61 | NSString *classDiffDescription =
62 | [[classDiff description] stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"];
63 | [description appendFormat:@"\t%@\n", classDiffDescription];
64 | }
65 | }
66 | return description;
67 | }
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeSnapshot.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | @class GULRuntimeClassSnapshot;
20 | @class GULRuntimeDiff;
21 |
22 | NS_ASSUME_NONNULL_BEGIN
23 |
24 | /** This class captures various aspects the current state of the Objective-C runtime. */
25 | @interface GULRuntimeSnapshot : NSObject
26 |
27 | /** Initializes an instance of this class. The designated initializer.
28 | *
29 | * @param classes The set of classes to track. If nil or empty, all ObjC classes are tracked.
30 | * @return An instance of this class.
31 | */
32 | - (instancetype)initWithClasses:(nullable NSSet *)classes NS_DESIGNATED_INITIALIZER;
33 |
34 | /** Captures the state of the class set. */
35 | - (void)capture;
36 |
37 | /** Computes the diff between this snapshot and another snapshot.
38 | *
39 | * @param otherSnapshot The other snapshot, assumed to be more recent than self.
40 | * @return A diff object populated with the diff.
41 | */
42 | - (GULRuntimeDiff *)diff:(GULRuntimeSnapshot *)otherSnapshot;
43 |
44 | @end
45 |
46 | NS_ASSUME_NONNULL_END
47 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeSnapshot.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeSnapshot.h"
16 |
17 | #import
18 |
19 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.h"
20 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassSnapshot.h"
21 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeDiff.h"
22 |
23 | @implementation GULRuntimeSnapshot {
24 | /** The set of tracked classes. */
25 | NSSet *__nullable _classes;
26 |
27 | /** The class snapshots for each tracked class. */
28 | NSMutableDictionary *_classSnapshots;
29 |
30 | /** The hash value of this object. */
31 | NSUInteger _runningHash;
32 | }
33 |
34 | - (instancetype)init {
35 | return [self initWithClasses:nil];
36 | }
37 |
38 | - (instancetype)initWithClasses:(nullable NSSet *)classes {
39 | self = [super init];
40 | if (self) {
41 | _classSnapshots = [[NSMutableDictionary alloc] init];
42 | _classes = classes;
43 | _runningHash = [_classes hash] ^ [_classSnapshots hash];
44 | }
45 | return self;
46 | }
47 |
48 | - (NSUInteger)hash {
49 | return _runningHash;
50 | }
51 |
52 | - (BOOL)isEqual:(id)object {
53 | return [self hash] == [object hash];
54 | }
55 |
56 | - (NSString *)description {
57 | return [[super description] stringByAppendingFormat:@" Hash: 0x%lX", (unsigned long)[self hash]];
58 | }
59 |
60 | - (void)capture {
61 | int numberOfClasses = objc_getClassList(NULL, 0);
62 | Class *classList = (Class *)malloc(numberOfClasses * sizeof(Class));
63 | numberOfClasses = objc_getClassList(classList, numberOfClasses);
64 |
65 | // If we should track specific classes, then there's no need to figure out all ObjC classes.
66 | if (_classes) {
67 | for (Class aClass in _classes) {
68 | NSString *classString = NSStringFromClass(aClass);
69 | GULRuntimeClassSnapshot *classSnapshot =
70 | [[GULRuntimeClassSnapshot alloc] initWithClass:aClass];
71 | _classSnapshots[classString] = classSnapshot;
72 | [classSnapshot capture];
73 | _runningHash ^= [classSnapshot hash];
74 | }
75 | } else {
76 | for (int i = 0; i < numberOfClasses; i++) {
77 | Class aClass = classList[i];
78 | NSString *classString = NSStringFromClass(aClass);
79 | GULRuntimeClassSnapshot *classSnapshot =
80 | [[GULRuntimeClassSnapshot alloc] initWithClass:aClass];
81 | _classSnapshots[classString] = classSnapshot;
82 | [classSnapshot capture];
83 | _runningHash ^= [classSnapshot hash];
84 | }
85 | }
86 | free(classList);
87 | }
88 |
89 | - (GULRuntimeDiff *)diff:(GULRuntimeSnapshot *)otherSnapshot {
90 | GULRuntimeDiff *runtimeDiff = [[GULRuntimeDiff alloc] init];
91 | NSSet *setOne = [NSSet setWithArray:[_classSnapshots allKeys]];
92 | NSSet *setTwo = [NSSet setWithArray:[otherSnapshot->_classSnapshots allKeys]];
93 |
94 | // All items contained within setOne, but not in setTwo.
95 | NSSet *removedClasses = [setOne
96 | filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(
97 | id _Nullable evaluatedObject,
98 | NSDictionary *_Nullable bindings) {
99 | return ![setTwo containsObject:evaluatedObject];
100 | }]];
101 |
102 | // All items contained within setTwo, but not in setOne.
103 | NSSet *addedClasses = [setTwo
104 | filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(
105 | id _Nullable evaluatedObject,
106 | NSDictionary *_Nullable bindings) {
107 | return ![setOne containsObject:evaluatedObject];
108 | }]];
109 | runtimeDiff.removedClasses = removedClasses;
110 | runtimeDiff.addedClasses = addedClasses;
111 |
112 | NSMutableSet *classDiffs = [[NSMutableSet alloc] init];
113 | [_classSnapshots
114 | enumerateKeysAndObjectsUsingBlock:^(
115 | NSString *_Nonnull key, GULRuntimeClassSnapshot *_Nonnull obj, BOOL *_Nonnull stop) {
116 | GULRuntimeClassSnapshot *classSnapshot = self->_classSnapshots[key];
117 | GULRuntimeClassSnapshot *otherClassSnapshot = otherSnapshot->_classSnapshots[key];
118 | GULRuntimeClassDiff *classDiff = [classSnapshot diff:otherClassSnapshot];
119 | if ([classDiff hash]) {
120 | NSAssert(![classDiffs containsObject:classDiff],
121 | @"An equivalent class diff has already been stored.");
122 | [classDiffs addObject:classDiff];
123 | }
124 | }];
125 | runtimeDiff.classDiffs = classDiffs;
126 | return runtimeDiff;
127 | }
128 |
129 | @end
130 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeStateHelper.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.h"
20 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeDiff.h"
21 |
22 | NS_ASSUME_NONNULL_BEGIN
23 |
24 | /** A helper class that enables the snapshotting and diffing of ObjC runtime state. */
25 | @interface GULRuntimeStateHelper : NSObject
26 |
27 | /** Captures the current state of the entire runtime and returns the snapshot number.
28 | *
29 | * @return The snapshot number corresponding to this capture.
30 | */
31 | + (NSUInteger)captureRuntimeState;
32 |
33 | /** Captures the current state of the runtime for the provided classes.
34 | *
35 | * @param classes The classes whose state should be snapshotted.
36 | * @return The snapshot number corresponding to this capture.
37 | */
38 | + (NSUInteger)captureRuntimeStateOfClasses:(NSSet *)classes;
39 |
40 | /** Prints the diff between two snapshot numbers.
41 | *
42 | * @param firstSnapshot The first runtime snapshot, as provided by captureRuntimeState.
43 | * @param secondSnapshot The runtime snapshot sometime after firstSnapshot.
44 | * @return An instance of GULRuntimeDiff that contains the diff information.
45 | */
46 | + (GULRuntimeDiff *)diffBetween:(NSUInteger)firstSnapshot secondSnapshot:(NSUInteger)secondSnapshot;
47 |
48 | @end
49 |
50 | NS_ASSUME_NONNULL_END
51 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULRuntimeStateHelper.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeStateHelper.h"
16 |
17 | #import
18 |
19 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeSnapshot.h"
20 |
21 | @implementation GULRuntimeStateHelper
22 |
23 | /** Initializes and returns the snapshot cache.
24 | *
25 | * @return A singleton snapshot cache.
26 | */
27 | + (NSMutableArray *)snapshotCache {
28 | static NSMutableArray *snapshots;
29 | static dispatch_once_t onceToken;
30 | dispatch_once(&onceToken, ^{
31 | snapshots = [[NSMutableArray alloc] init];
32 | });
33 | return snapshots;
34 | }
35 |
36 | + (NSUInteger)captureRuntimeState {
37 | GULRuntimeSnapshot *snapshot = [[GULRuntimeSnapshot alloc] init];
38 | [snapshot capture];
39 | [[self snapshotCache] addObject:snapshot];
40 | return [self snapshotCache].count - 1;
41 | }
42 |
43 | + (NSUInteger)captureRuntimeStateOfClasses:(NSSet *)classes {
44 | GULRuntimeSnapshot *snapshot = [[GULRuntimeSnapshot alloc] initWithClasses:classes];
45 | [snapshot capture];
46 | [[self snapshotCache] addObject:snapshot];
47 | return [self snapshotCache].count - 1;
48 | }
49 |
50 | + (GULRuntimeDiff *)diffBetween:(NSUInteger)firstSnapshot
51 | secondSnapshot:(NSUInteger)secondSnapshot {
52 | NSArray *snapshotCache = [self snapshotCache];
53 | return [snapshotCache[firstSnapshot] diff:snapshotCache[secondSnapshot]];
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULSwizzler+Unswizzle.m:
--------------------------------------------------------------------------------
1 | // Copyright 2019 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 | #import "GoogleUtilities/MethodSwizzler/Public/GoogleUtilities/GULSwizzler.h"
16 |
17 | #import
18 |
19 | #import "GoogleUtilities/SwizzlerTestHelpers/GULSwizzlingCache.h"
20 |
21 | extern dispatch_queue_t GetGULSwizzlingQueue(void);
22 |
23 | @implementation GULSwizzler (Unswizzle)
24 |
25 | + (void)unswizzleClass:(Class)aClass selector:(SEL)selector isClassSelector:(BOOL)isClassSelector {
26 | dispatch_sync(GetGULSwizzlingQueue(), ^{
27 | NSAssert(aClass != nil && selector != nil, @"You cannot unswizzle a nil class or selector.");
28 | Method method = nil;
29 | Class resolvedClass = aClass;
30 | if (isClassSelector) {
31 | resolvedClass = object_getClass(aClass);
32 | method = class_getClassMethod(aClass, selector);
33 | } else {
34 | method = class_getInstanceMethod(aClass, selector);
35 | }
36 | NSAssert(method, @"Couldn't find the method you're unswizzling in the runtime.");
37 | IMP originalImp = [[GULSwizzlingCache sharedInstance] cachedIMPForClass:resolvedClass
38 | withSelector:selector];
39 | NSAssert(originalImp, @"This class/selector combination hasn't been swizzled");
40 | IMP currentImp = method_setImplementation(method, originalImp);
41 | __unused BOOL didRemoveBlock = imp_removeBlock(currentImp);
42 | NSAssert(didRemoveBlock, @"Wasn't able to remove the block of a swizzled IMP.");
43 | [[GULSwizzlingCache sharedInstance] clearCacheForSwizzledIMP:currentImp
44 | selector:selector
45 | aClass:resolvedClass];
46 | });
47 | }
48 |
49 | + (nullable IMP)originalImplementationForClass:(Class)aClass
50 | selector:(SEL)selector
51 | isClassSelector:(BOOL)isClassSelector {
52 | __block IMP originalImp = nil;
53 | dispatch_sync(GetGULSwizzlingQueue(), ^{
54 | Class resolvedClass = isClassSelector ? object_getClass(aClass) : aClass;
55 | originalImp = [[GULSwizzlingCache sharedInstance] cachedIMPForClass:resolvedClass
56 | withSelector:selector];
57 | NSAssert(originalImp, @"The IMP for this class/selector combo doesn't exist (%@, %@).",
58 | NSStringFromClass(resolvedClass), NSStringFromSelector(selector));
59 | });
60 | return originalImp;
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULSwizzlingCache.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | #import
18 |
19 | /** This class handles the caching and retrieval of IMPs as we swizzle and unswizzle them. It uses
20 | * two C++ STL unordered_maps as the underlying data store. This class is NOT thread safe.
21 | */
22 | @interface GULSwizzlingCache : NSObject
23 |
24 | /** Singleton initializer.
25 | *
26 | * @return a singleton GULSwizzlingCache.
27 | */
28 | + (instancetype)sharedInstance;
29 |
30 | /** Save the existing IMP that exists before we install the new IMP for a class, selector combo.
31 | * If the currentIMP is something that we put there, it will ignore it and instead point newIMP
32 | * to what existed before we swizzled.
33 | *
34 | * @param currentIMP The IMP returned by class_getMethodImplementation.
35 | * @param newIMP new The IMP that is going to replace the current IMP.
36 | * @param aClass The class that we're swizzling.
37 | * @param selector The selector we're swizzling.
38 | */
39 | - (void)cacheCurrentIMP:(IMP)currentIMP
40 | forNewIMP:(IMP)newIMP
41 | forClass:(Class)aClass
42 | withSelector:(SEL)selector;
43 |
44 | /** Save the existing IMP that exists before we install the new IMP for a class, selector combo.
45 | * If the currentIMP is something that we put there, it will ignore it and instead point newIMP
46 | * to what existed before we swizzled.
47 | *
48 | * @param currentIMP The IMP returned by class_getMethodImplementation.
49 | * @param newIMP new The IMP that is going to replace the current IMP.
50 | * @param aClass The class that we're swizzling.
51 | * @param selector The selector we're swizzling.
52 | */
53 | + (void)cacheCurrentIMP:(IMP)currentIMP
54 | forNewIMP:(IMP)newIMP
55 | forClass:(Class)aClass
56 | withSelector:(SEL)selector;
57 |
58 | /** Returns the cached IMP that would be invoked with the class and selector combo had we
59 | * never swizzled.
60 | *
61 | * @param aClass The class the selector would be invoked on.
62 | * @param selector The selector
63 | * @return The original IMP i.e. the one that existed right before GULSwizzler swizzled either
64 | * this or a superclass.
65 | */
66 | - (IMP)cachedIMPForClass:(Class)aClass withSelector:(SEL)selector;
67 |
68 | /** Clears the cache of values we no longer need because we've unswizzled the relevant method.
69 | *
70 | * @param swizzledIMP The IMP we replaced the existing IMP with.
71 | * @param selector The selector which that we swizzled for.
72 | * @param aClass The class that we're swizzling.
73 | */
74 | - (void)clearCacheForSwizzledIMP:(IMP)swizzledIMP selector:(SEL)selector aClass:(Class)aClass;
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULSwizzlingCache.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import "GoogleUtilities/SwizzlerTestHelpers/GULSwizzlingCache.h"
16 |
17 | #import
18 |
19 | @interface GULSwizzlingCache ()
20 | - (IMP)originalIMPOfCurrentIMP:(IMP)currentIMP;
21 | @end
22 |
23 | @implementation GULSwizzlingCache {
24 | /** A mapping from the new IMP to the original IMP. */
25 | CFMutableDictionaryRef _newToOriginalImps;
26 |
27 | /** A mapping from a Class and SEL (stored in a CFArray) to the original IMP that existed for it.
28 | */
29 | CFMutableDictionaryRef _originalImps;
30 | }
31 |
32 | + (instancetype)sharedInstance {
33 | static GULSwizzlingCache *sharedInstance;
34 | static dispatch_once_t token;
35 | dispatch_once(&token, ^{
36 | sharedInstance = [[GULSwizzlingCache alloc] init];
37 | });
38 | return sharedInstance;
39 | }
40 |
41 | - (instancetype)init {
42 | self = [super init];
43 | if (self) {
44 | _newToOriginalImps = CFDictionaryCreateMutable(kCFAllocatorDefault,
45 | 0, // Size.
46 | NULL, // Keys are pointers, so this is NULL.
47 | NULL); // Values are pointers so this is NULL.
48 | _originalImps = CFDictionaryCreateMutable(kCFAllocatorDefault,
49 | 0, // Size.
50 | &kCFTypeDictionaryKeyCallBacks, // Keys are CFArrays.
51 | NULL); // Values are pointers so this is NULL.
52 | }
53 | return self;
54 | }
55 |
56 | - (void)dealloc {
57 | CFRelease(_newToOriginalImps);
58 | CFRelease(_originalImps);
59 | }
60 |
61 | - (void)cacheCurrentIMP:(IMP)currentIMP
62 | forNewIMP:(IMP)newIMP
63 | forClass:(Class)aClass
64 | withSelector:(SEL)selector {
65 | IMP originalIMP = [self originalIMPOfCurrentIMP:currentIMP];
66 | CFDictionaryAddValue(_newToOriginalImps, newIMP, originalIMP);
67 |
68 | const void *classSELCArray[2] = {(__bridge void *)(aClass), selector};
69 | CFArrayRef classSELPair = CFArrayCreate(kCFAllocatorDefault, classSELCArray,
70 | 2, // Size.
71 | NULL); // Elements are pointers so this is NULL.
72 | CFDictionaryAddValue(_originalImps, classSELPair, originalIMP);
73 | CFRelease(classSELPair);
74 | }
75 |
76 | + (void)cacheCurrentIMP:(IMP)currentIMP
77 | forNewIMP:(IMP)newIMP
78 | forClass:(Class)aClass
79 | withSelector:(SEL)selector {
80 | [[GULSwizzlingCache sharedInstance] cacheCurrentIMP:currentIMP
81 | forNewIMP:newIMP
82 | forClass:aClass
83 | withSelector:selector];
84 | }
85 |
86 | - (IMP)cachedIMPForClass:(Class)aClass withSelector:(SEL)selector {
87 | const void *classSELCArray[2] = {(__bridge void *)(aClass), selector};
88 | CFArrayRef classSELPair = CFArrayCreate(kCFAllocatorDefault, classSELCArray,
89 | 2, // Size.
90 | NULL); // Elements are pointers so this is NULL.
91 | const void *returnedIMP = CFDictionaryGetValue(_originalImps, classSELPair);
92 | CFRelease(classSELPair);
93 | return (IMP)returnedIMP;
94 | }
95 |
96 | - (void)clearCacheForSwizzledIMP:(IMP)swizzledIMP selector:(SEL)selector aClass:(Class)aClass {
97 | CFDictionaryRemoveValue(_newToOriginalImps, swizzledIMP);
98 | const void *classSELCArray[2] = {(__bridge void *)(aClass), selector};
99 | CFArrayRef classSELPair = CFArrayCreate(kCFAllocatorDefault, classSELCArray,
100 | 2, // Size.
101 | NULL); // Elements are pointers so this is NULL.
102 | CFDictionaryRemoveValue(_originalImps, classSELPair);
103 | CFRelease(classSELPair);
104 | }
105 |
106 | - (IMP)originalIMPOfCurrentIMP:(IMP)currentIMP {
107 | const void *returnedIMP = CFDictionaryGetValue(_newToOriginalImps, currentIMP);
108 | if (returnedIMP != NULL) {
109 | return (IMP)returnedIMP;
110 | } else {
111 | return currentIMP;
112 | }
113 | }
114 |
115 | + (IMP)originalIMPOfCurrentIMP:(IMP)currentIMP {
116 | return [[GULSwizzlingCache sharedInstance] originalIMPOfCurrentIMP:currentIMP];
117 | }
118 |
119 | #pragma mark - Helper methods for testing
120 |
121 | - (void)clearCache {
122 | CFDictionaryRemoveAllValues(_originalImps);
123 | CFDictionaryRemoveAllValues(_newToOriginalImps);
124 | }
125 |
126 | - (CFMutableDictionaryRef)originalImps {
127 | return _originalImps;
128 | }
129 |
130 | - (CFMutableDictionaryRef)newToOriginalImps {
131 | return _newToOriginalImps;
132 | }
133 |
134 | @end
135 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/GULSwizzlingCache_Private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Google LLC
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 | @interface GULSwizzlingCache ()
18 |
19 | /** Checks if we've swizzled the currentIMP and returns the original IMP that would be invoked if
20 | * we hadn't swizzled it in the first place. This method is private because consumers don't need it
21 | * to cache or retrieve any IMPs. It is used internally and for certain asserts in GULSwizzler.
22 | *
23 | * @param currentIMP The IMP returned by class_getMethodImplementation.
24 | * @return The original IMP that would be invoked if we hadn't swizzled at all, and in cases where
25 | * currentIMP is not something that we put there, just returns currentIMP.
26 | */
27 | + (IMP)originalIMPOfCurrentIMP:(IMP)currentIMP;
28 |
29 | #pragma mark - Helper methods for testing
30 |
31 | /** Clears all the cache data structures. */
32 | - (void)clearCache;
33 |
34 | /** Allows tests access to the originalImps CFMutableDictionaryRef.
35 | *
36 | * @returns the originalImps CFMutableDictionaryRef.
37 | */
38 | - (CFMutableDictionaryRef)originalImps;
39 |
40 | /** Allows tests access to the newToOriginalImps CFMutableDictionaryRef.
41 | *
42 | * @returns the newToOriginalImps CFMutableDictionaryRef.
43 | */
44 | - (CFMutableDictionaryRef)newToOriginalImps;
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/GoogleUtilities/SwizzlerTestHelpers/Public/GoogleUtilities/GULSwizzler+Unswizzle.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google LLC
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 | #import
18 | #import
19 |
20 | NS_ASSUME_NONNULL_BEGIN
21 |
22 | /** This category adds methods for unswizzling that are only used for testing.
23 | */
24 | @interface GULSwizzler (Unswizzle)
25 |
26 | /** Restores the original implementation.
27 | *
28 | * @param aClass The class to unswizzle.
29 | * @param selector The selector to restore the original implementation of.
30 | * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector.
31 | */
32 | + (void)unswizzleClass:(Class)aClass selector:(SEL)selector isClassSelector:(BOOL)isClassSelector;
33 |
34 | /** Returns the original IMP for the given class and selector.
35 | *
36 | * @param aClass The class to use.
37 | * @param selector The selector to find the implementation of.
38 | * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector.
39 | * @return The implementation of the selector in the runtime before any consumer or GULSwizzler
40 | * swizzled.
41 | */
42 | + (nullable IMP)originalImplementationForClass:(Class)aClass
43 | selector:(SEL)selector
44 | isClassSelector:(BOOL)isClassSelector;
45 |
46 | @end
47 |
48 | NS_ASSUME_NONNULL_END
49 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/SwiftUnit/GULAppEnvironmentUtilTest.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
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 | @testable import GoogleUtilities
18 | import XCTest
19 |
20 | class GULAppEnvironmentUtilTest: XCTestCase {
21 | func testIsAppExtension() throws {
22 | XCTAssertFalse(GULAppEnvironmentUtil.isAppExtension())
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Environment/GULAppEnvironmentUtilTest.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Google
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 | #import
16 | #import
17 | #import
18 |
19 | #if __has_include()
20 | #import
21 | #endif
22 |
23 | #import "GoogleUtilities/Environment/Public/GoogleUtilities/GULAppEnvironmentUtil.h"
24 |
25 | @interface GULAppEnvironmentUtilTest : XCTestCase
26 |
27 | @property(nonatomic) id processInfoMock;
28 |
29 | @end
30 |
31 | @implementation GULAppEnvironmentUtilTest
32 |
33 | - (void)setUp {
34 | [super setUp];
35 |
36 | _processInfoMock = OCMPartialMock([NSProcessInfo processInfo]);
37 | }
38 |
39 | - (void)tearDown {
40 | [super tearDown];
41 |
42 | [_processInfoMock stopMocking];
43 | }
44 |
45 | - (void)testSystemVersionInfoMajorOnly {
46 | #if TARGET_OS_IOS
47 | XCTAssertEqualObjects([GULAppEnvironmentUtil systemVersion],
48 | [UIDevice currentDevice].systemVersion);
49 | #else
50 | NSOperatingSystemVersion osTen = {.majorVersion = 10, .minorVersion = 0, .patchVersion = 0};
51 | OCMStub([self.processInfoMock operatingSystemVersion]).andReturn(osTen);
52 | XCTAssertEqualObjects([GULAppEnvironmentUtil systemVersion], @"10.0");
53 | #endif
54 | }
55 |
56 | - (void)testSystemVersionInfoMajorMinor {
57 | #if TARGET_OS_IOS
58 | XCTAssertEqualObjects([GULAppEnvironmentUtil systemVersion],
59 | [UIDevice currentDevice].systemVersion);
60 | #else
61 | NSOperatingSystemVersion osTenTwo = {.majorVersion = 10, .minorVersion = 2, .patchVersion = 0};
62 | OCMStub([self.processInfoMock operatingSystemVersion]).andReturn(osTenTwo);
63 | XCTAssertEqualObjects([GULAppEnvironmentUtil systemVersion], @"10.2");
64 | #endif
65 | }
66 |
67 | - (void)testSystemVersionInfoMajorMinorPatch {
68 | #if TARGET_OS_IOS
69 | XCTAssertEqualObjects([GULAppEnvironmentUtil systemVersion],
70 | [UIDevice currentDevice].systemVersion);
71 | #else
72 | NSOperatingSystemVersion osTenTwoOne = {.majorVersion = 10, .minorVersion = 2, .patchVersion = 1};
73 | OCMStub([self.processInfoMock operatingSystemVersion]).andReturn(osTenTwoOne);
74 | XCTAssertEqualObjects([GULAppEnvironmentUtil systemVersion], @"10.2.1");
75 | #endif
76 | }
77 |
78 | - (void)testDeploymentType {
79 | #if SWIFT_PACKAGE
80 | NSString *deploymentType = @"swiftpm";
81 | #elif FIREBASE_BUILD_CARTHAGE
82 | NSString *deploymentType = @"carthage";
83 | #elif FIREBASE_BUILD_ZIP_FILE
84 | NSString *deploymentType = @"zip";
85 | #elif COCOAPODS
86 | NSString *deploymentType = @"cocoapods";
87 | #else
88 | NSString *deploymentType = @"unknown";
89 | #endif
90 |
91 | XCTAssertEqualObjects([GULAppEnvironmentUtil deploymentType], deploymentType);
92 | }
93 |
94 | - (void)testApplePlatform {
95 | // The below ordering is important. For example, both `TARGET_OS_MACCATALYST`
96 | // and `TARGET_OS_IOS` are `true` when building a macCatalyst app.
97 | #if TARGET_OS_MACCATALYST
98 | NSString *expectedPlatform = @"maccatalyst";
99 | #elif TARGET_OS_IOS
100 | NSString *expectedPlatform = @"ios";
101 | #elif TARGET_OS_TV
102 | NSString *expectedPlatform = @"tvos";
103 | #elif TARGET_OS_OSX
104 | NSString *expectedPlatform = @"macos";
105 | #elif TARGET_OS_WATCH
106 | NSString *expectedPlatform = @"watchos";
107 | #endif // TARGET_OS_MACCATALYST
108 |
109 | #if TARGET_OS_VISION
110 | NSString *expectedPlatform = @"visionos";
111 | #endif // TARGET_OS_VISION
112 |
113 | XCTAssertEqualObjects([GULAppEnvironmentUtil applePlatform], expectedPlatform);
114 | }
115 |
116 | - (void)testAppleDevicePlatform {
117 | // When a Catalyst app is run on macOS then both `TARGET_OS_MACCATALYST` and `TARGET_OS_IOS` are
118 | // `true`.
119 | #if TARGET_OS_MACCATALYST
120 | NSString *expectedPlatform = @"maccatalyst";
121 | #elif TARGET_OS_IOS
122 | NSString *expectedPlatform = @"ios";
123 |
124 | if ([[UIDevice currentDevice].model.lowercaseString containsString:@"ipad"] ||
125 | [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
126 | expectedPlatform = @"ipados";
127 | }
128 | #endif // TARGET_OS_MACCATALYST
129 |
130 | #if TARGET_OS_TV
131 | NSString *expectedPlatform = @"tvos";
132 | #endif // TARGET_OS_TV
133 |
134 | #if TARGET_OS_OSX
135 | NSString *expectedPlatform = @"macos";
136 | #endif // TARGET_OS_OSX
137 |
138 | #if TARGET_OS_WATCH
139 | NSString *expectedPlatform = @"watchos";
140 | #endif // TARGET_OS_WATCH
141 |
142 | #if TARGET_OS_VISION
143 | NSString *expectedPlatform = @"visionos";
144 | #endif // TARGET_OS_VISION
145 |
146 | XCTAssertEqualObjects([GULAppEnvironmentUtil appleDevicePlatform], expectedPlatform);
147 | }
148 |
149 | @end
150 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Logger/GULLoggerTest.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Google
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 | #ifdef DEBUG
16 | // The tests depend upon library methods only built with #ifdef DEBUG
17 |
18 | #import
19 | #import
20 |
21 | #import "GoogleUtilities/Logger/Public/GoogleUtilities/GULLogger.h"
22 |
23 | #import
24 | #import
25 |
26 | extern void GULResetLogger(void);
27 |
28 | extern dispatch_queue_t getGULClientQueue(void);
29 |
30 | extern BOOL getGULLoggerDebugMode(void);
31 |
32 | extern os_log_type_t GULLoggerLevelToOSLogType(GULLoggerLevel level);
33 |
34 | static NSString *const kMessageCode = @"I-COR000001";
35 |
36 | @interface GULLoggerTest : XCTestCase
37 |
38 | @property(nonatomic) NSString *randomLogString;
39 |
40 | @property(nonatomic, strong) NSUserDefaults *defaults;
41 |
42 | @end
43 |
44 | @implementation GULLoggerTest
45 |
46 | + (void)setUp {
47 | GULLoggerInitialize();
48 | }
49 |
50 | - (void)setUp {
51 | [super setUp];
52 | GULResetLogger();
53 |
54 | // Stub NSUserDefaults for cleaner testing.
55 | _defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.google.logger_test"];
56 | }
57 |
58 | - (void)tearDown {
59 | [super tearDown];
60 |
61 | _defaults = nil;
62 | }
63 |
64 | - (void)testMessageCodeFormat {
65 | // Valid case.
66 | XCTAssertNoThrow(
67 | GULOSLogError(@"com.my.service", @"My/Category", NO, @"I-APP000001", @"Message."));
68 |
69 | // An extra dash or missing dash should fail.
70 | XCTAssertThrows(
71 | GULOSLogError(@"com.my.service", @"My/Category", NO, @"I-APP-000001", @"Message."));
72 | XCTAssertThrows(GULOSLogError(@"com.my.service", @"My/Category", NO, @"IAPP000001", @"Message."));
73 |
74 | // Wrong number of digits should fail.
75 | XCTAssertThrows(GULOSLogError(@"com.my.service", @"My/Category", NO, @"I-APP00001", @"Message."));
76 | XCTAssertThrows(
77 | GULOSLogError(@"com.my.service", @"My/Category", NO, @"I-APP0000001", @"Message."));
78 |
79 | // Lowercase should fail.
80 | XCTAssertThrows(
81 | GULOSLogError(@"com.my.service", @"My/Category", NO, @"I-app000001", @"Message."));
82 |
83 | // nil or empty message code should fail.
84 | #pragma clang diagnostic push
85 | #pragma clang diagnostic ignored "-Wnonnull"
86 | XCTAssertThrows(GULOSLogError(@"com.my.service", @"My/Category", NO, nil, @"Message."));
87 | #pragma clang diagnostic pop
88 |
89 | XCTAssertThrows(GULOSLogError(@"com.my.service", @"My/Category", NO, @"", @"Message."));
90 |
91 | // Android message code should fail.
92 | XCTAssertThrows(
93 | GULOSLogError(@"com.my.service", @"My/Category", NO, @"A-APP000001", @"Message."));
94 | }
95 |
96 | // The GULLoggerLevel enum must match the ASL_LEVEL_* constants, but we manually redefine
97 | // them in GULLoggerLevel.h since we cannot include (see b/34976089 for more details).
98 | // This test ensures the constants match.
99 | - (void)testGULLoggerLevelValues {
100 | XCTAssertEqual(GULLoggerLevelError, ASL_LEVEL_ERR);
101 | XCTAssertEqual(GULLoggerLevelWarning, ASL_LEVEL_WARNING);
102 | XCTAssertEqual(GULLoggerLevelNotice, ASL_LEVEL_NOTICE);
103 | XCTAssertEqual(GULLoggerLevelInfo, ASL_LEVEL_INFO);
104 | XCTAssertEqual(GULLoggerLevelDebug, ASL_LEVEL_DEBUG);
105 | }
106 |
107 | - (void)testGULLoggerLevelToOSLogType {
108 | XCTAssertEqual(GULLoggerLevelToOSLogType(GULLoggerLevelError), OS_LOG_TYPE_ERROR);
109 | // OSLog doesn't have a WARNING level so it is remapped to DEFAULT (Notice).
110 | XCTAssertEqual(GULLoggerLevelToOSLogType(GULLoggerLevelWarning),
111 | GULLoggerLevelToOSLogType(GULLoggerLevelNotice));
112 | XCTAssertEqual(GULLoggerLevelToOSLogType(GULLoggerLevelNotice), OS_LOG_TYPE_DEFAULT);
113 | XCTAssertEqual(GULLoggerLevelToOSLogType(GULLoggerLevelInfo), OS_LOG_TYPE_INFO);
114 | XCTAssertEqual(GULLoggerLevelToOSLogType(GULLoggerLevelDebug), OS_LOG_TYPE_DEBUG);
115 | }
116 |
117 | - (void)testGULGetLoggerLevel {
118 | GULLoggerLevel loggerLevel = GULGetLoggerLevel();
119 |
120 | // The default logger level is GULLoggerLevelNotice.
121 | XCTAssertEqual(loggerLevel, GULLoggerLevelNotice);
122 | }
123 |
124 | - (void)testGULSetLoggerLevel {
125 | GULSetLoggerLevel(GULLoggerLevelDebug);
126 |
127 | GULLoggerLevel loggerLevel = GULGetLoggerLevel();
128 |
129 | // The default logger level is GULLoggerLevelNotice.
130 | XCTAssertEqual(loggerLevel, GULLoggerLevelDebug);
131 | }
132 |
133 | - (void)testGULResetLogger_ResetsLoggerLevel {
134 | GULSetLoggerLevel(GULLoggerLevelDebug);
135 |
136 | GULResetLogger();
137 | GULLoggerLevel loggerLevel = GULGetLoggerLevel();
138 |
139 | // The default logger level is GULLoggerLevelNotice.
140 | XCTAssertEqual(loggerLevel, GULLoggerLevelNotice);
141 | }
142 |
143 | @end
144 | #endif
145 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Network/GULMutableDictionaryTest.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Google
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 | #import
16 |
17 | #import "GoogleUtilities/Network/Public/GoogleUtilities/GULMutableDictionary.h"
18 |
19 | const static NSString *const kKey = @"testKey1";
20 | const static NSString *const kValue = @"testValue1";
21 | const static NSString *const kKey2 = @"testKey2";
22 | const static NSString *const kValue2 = @"testValue2";
23 |
24 | @interface GULMutableDictionaryTest : XCTestCase
25 | @property(nonatomic) GULMutableDictionary *dictionary;
26 | @end
27 |
28 | @implementation GULMutableDictionaryTest
29 |
30 | - (void)setUp {
31 | [super setUp];
32 | self.dictionary = [[GULMutableDictionary alloc] init];
33 | }
34 |
35 | - (void)tearDown {
36 | self.dictionary = nil;
37 | [super tearDown];
38 | }
39 |
40 | - (void)testSetGetAndRemove {
41 | XCTAssertNil([self.dictionary objectForKey:kKey]);
42 | [self.dictionary setObject:kValue forKey:kKey];
43 | XCTAssertEqual(kValue, [self.dictionary objectForKey:kKey]);
44 | [self.dictionary removeObjectForKey:kKey];
45 | XCTAssertNil([self.dictionary objectForKey:kKey]);
46 | }
47 |
48 | - (void)testSetGetAndRemoveKeyed {
49 | XCTAssertNil(self.dictionary[kKey]);
50 | self.dictionary[kKey] = kValue;
51 | XCTAssertEqual(kValue, self.dictionary[kKey]);
52 | [self.dictionary removeObjectForKey:kKey];
53 | XCTAssertNil(self.dictionary[kKey]);
54 | }
55 |
56 | - (void)testRemoveAll {
57 | XCTAssertNil(self.dictionary[kKey]);
58 | XCTAssertNil(self.dictionary[kKey2]);
59 | self.dictionary[kKey] = kValue;
60 | self.dictionary[kKey2] = kValue2;
61 | [self.dictionary removeAllObjects];
62 | XCTAssertNil(self.dictionary[kKey]);
63 | XCTAssertNil(self.dictionary[kKey2]);
64 | }
65 |
66 | - (void)testCount {
67 | XCTAssertEqual([self.dictionary count], 0);
68 | self.dictionary[kKey] = kValue;
69 | XCTAssertEqual([self.dictionary count], 1);
70 | self.dictionary[kKey2] = kValue2;
71 | XCTAssertEqual([self.dictionary count], 2);
72 | [self.dictionary removeAllObjects];
73 | XCTAssertEqual([self.dictionary count], 0);
74 | }
75 |
76 | - (void)testUnderlyingDictionary {
77 | XCTAssertEqual([self.dictionary count], 0);
78 | self.dictionary[kKey] = kValue;
79 | self.dictionary[kKey2] = kValue2;
80 |
81 | NSDictionary *dict = self.dictionary.dictionary;
82 | XCTAssertEqual([dict count], 2);
83 | XCTAssertEqual(dict[kKey], kValue);
84 | XCTAssertEqual(dict[kKey2], kValue2);
85 | }
86 |
87 | @end
88 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Network/third_party/GTMHTTPServer.h:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 Google Inc.
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 |
16 | //
17 | // GTMHTTPServer.h
18 | //
19 | // This is a *very* *simple* webserver that can be built into something, it is
20 | // not meant to stand up a site, it sends all requests to its delegate for
21 | // processing on the main thread. It does not support pipelining, etc. It's
22 | // great for places where you need a simple webserver to unittest some code
23 | // that hits a server.
24 | //
25 | // NOTE: there are several TODOs left in here as markers for things that could
26 | // be done if one wanted to add more to this class.
27 | //
28 | // Based a little on HTTPServer, part of the CocoaHTTPServer sample code found at
29 | // https://opensource.apple.com/source/HTTPServer/HTTPServer-11/CocoaHTTPServer/
30 | // License for the CocoaHTTPServer sample code:
31 | //
32 | // Software License Agreement (BSD License)
33 | //
34 | // Copyright (c) 2011, Deusty, LLC
35 | // All rights reserved.
36 | //
37 | // Redistribution and use of this software in source and binary forms,
38 | // with or without modification, are permitted provided that the following conditions are met:
39 | //
40 | // * Redistributions of source code must retain the above
41 | // copyright notice, this list of conditions and the
42 | // following disclaimer.
43 | //
44 | // * Neither the name of Deusty nor the names of its
45 | // contributors may be used to endorse or promote products
46 | // derived from this software without specific prior
47 | // written permission of Deusty, LLC.
48 | //
49 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
50 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
51 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
52 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
54 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
56 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 | // POSSIBILITY OF SUCH DAMAGE.
58 |
59 | #import
60 |
61 | #if GTM_IPHONE_SDK
62 | #import
63 | #endif // GTM_IPHONE_SDK
64 |
65 | // Global constants needed for errors from start
66 |
67 | #undef _EXTERN
68 | #undef _INITIALIZE_AS
69 | #ifdef GTMHTTPSERVER_DEFINE_GLOBALS
70 | #define _EXTERN
71 | #define _INITIALIZE_AS(x) = x
72 | #else
73 | #define _EXTERN extern
74 | #define _INITIALIZE_AS(x)
75 | #endif
76 |
77 | _EXTERN NSString *const kGTMHTTPServerErrorDomain
78 | _INITIALIZE_AS(@"com.google.mactoolbox.HTTPServerDomain");
79 | enum {
80 | kGTMHTTPServerSocketCreateFailedError = -100,
81 | kGTMHTTPServerBindFailedError = -101,
82 | kGTMHTTPServerListenFailedError = -102,
83 | kGTMHTTPServerHandleCreateFailedError = -103,
84 | };
85 |
86 | @class GTMHTTPRequestMessage, GTMHTTPResponseMessage;
87 |
88 | // ----------------------------------------------------------------------------
89 |
90 | // See comment at top of file for the intended use of this class.
91 | @interface GTMHTTPServer : NSObject {
92 | @private
93 | id delegate_; // WEAK
94 | uint16_t port_;
95 | BOOL reusePort_;
96 | BOOL localhostOnly_;
97 | NSFileHandle *listenHandle_;
98 | NSMutableArray *connections_;
99 | }
100 |
101 | // The delegate must support the httpServer:handleRequest: method in
102 | // NSObject(GTMHTTPServerDelegateMethods) below.
103 | - (id)initWithDelegate:(id)delegate;
104 |
105 | - (id)delegate;
106 |
107 | // Passing port zero will let one get assigned.
108 | - (uint16_t)port;
109 | - (void)setPort:(uint16_t)port;
110 |
111 | // Controls listening socket behavior: SO_REUSEADDR vs SO_REUSEPORT.
112 | // The default is NO (SO_REUSEADDR)
113 | - (BOOL)reusePort;
114 | - (void)setReusePort:(BOOL)reusePort;
115 |
116 | // Receive connections on the localHost loopback address only or on all
117 | // interfaces for this machine. The default is to only listen on localhost.
118 | - (BOOL)localhostOnly;
119 | - (void)setLocalhostOnly:(BOOL)yesno;
120 |
121 | // Start/Stop the web server. If there is an error starting up the server, |NO|
122 | // is returned, and the specific startup failure can be returned in |error| (see
123 | // above for the error domain and error codes). If the server is started, |YES|
124 | // is returned and the server's delegate is called for any requests that come
125 | // in.
126 | - (BOOL)start:(NSError **)error;
127 | - (void)stop;
128 |
129 | // returns the number of requests currently active in the server (i.e.-being
130 | // read in, sent replies).
131 | - (NSUInteger)activeRequestCount;
132 |
133 | @end
134 |
135 | @interface NSObject (GTMHTTPServerDelegateMethods)
136 | - (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server
137 | handleRequest:(GTMHTTPRequestMessage *)request;
138 | @end
139 |
140 | // ----------------------------------------------------------------------------
141 |
142 | // Encapsulates an http request, one of these is sent to the server's delegate
143 | // for each request.
144 | @interface GTMHTTPRequestMessage : NSObject {
145 | @private
146 | CFHTTPMessageRef message_;
147 | }
148 | - (NSString *)version;
149 | - (NSURL *)URL;
150 | - (NSString *)method;
151 | - (NSData *)body;
152 | - (NSDictionary *)allHeaderFieldValues;
153 | @end
154 |
155 | // ----------------------------------------------------------------------------
156 |
157 | // Encapsulates an http response, the server's delegate should return one for
158 | // each request received.
159 | @interface GTMHTTPResponseMessage : NSObject {
160 | @private
161 | CFHTTPMessageRef message_;
162 | }
163 | + (instancetype)responseWithString:(NSString *)plainText;
164 | + (instancetype)responseWithHTMLString:(NSString *)htmlString;
165 | + (instancetype)responseWithBody:(NSData *)body
166 | contentType:(NSString *)contentType
167 | statusCode:(int)statusCode;
168 | + (instancetype)emptyResponseWithCode:(int)statusCode;
169 | // TODO: class method for redirections?
170 | // TODO: add helper for expire/no-cache
171 | - (void)setValue:(NSString *)value forHeaderField:(NSString *)headerField;
172 | - (void)setHeaderValuesFromDictionary:(NSDictionary *)dict;
173 | @end
174 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Network/third_party/LICENSE:
--------------------------------------------------------------------------------
1 | Based a little on HTTPServer, part of the CocoaHTTPServer sample code found at
2 | https://opensource.apple.com/source/HTTPServer/HTTPServer-11/CocoaHTTPServer/
3 | License for the CocoaHTTPServer sample code:
4 |
5 | Software License Agreement (BSD License)
6 |
7 | Copyright (c) 2011, Deusty, LLC
8 | All rights reserved.
9 |
10 | Redistribution and use of this software in source and binary forms,
11 | with or without modification, are permitted provided that the following conditions are met:
12 |
13 | * Redistributions of source code must retain the above
14 | copyright notice, this list of conditions and the
15 | following disclaimer.
16 |
17 | * Neither the name of Deusty nor the names of its
18 | contributors may be used to endorse or promote products
19 | derived from this software without specific prior
20 | written permission of Deusty, LLC.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Shared/URLSession/FIRURLSessionOCMockStub.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
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 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | typedef BOOL (^FIRRequestValidationBlock)(NSURLRequest *request);
22 |
23 | @interface FIRURLSessionOCMockStub : NSObject
24 |
25 | + (id)stubURLSessionDataTaskWithResponse:(nullable NSHTTPURLResponse *)response
26 | body:(nullable NSData *)body
27 | error:(nullable NSError *)error
28 | URLSessionMock:(id)URLSessionMock
29 | requestValidationBlock:(nullable FIRRequestValidationBlock)requestValidationBlock;
30 |
31 | + (NSHTTPURLResponse *)HTTPResponseWithCode:(NSInteger)statusCode;
32 |
33 | @end
34 |
35 | NS_ASSUME_NONNULL_END
36 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Shared/URLSession/FIRURLSessionOCMockStub.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
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 | #import "GoogleUtilities/Tests/Unit/Shared/URLSession/FIRURLSessionOCMockStub.h"
18 |
19 | #import
20 |
21 | @implementation FIRURLSessionOCMockStub
22 |
23 | + (id)stubURLSessionDataTaskWithResponse:(NSHTTPURLResponse *)response
24 | body:(NSData *)body
25 | error:(NSError *)error
26 | URLSessionMock:(id)URLSessionMock
27 | requestValidationBlock:(FIRRequestValidationBlock)requestValidationBlock {
28 | id mockDataTask = OCMStrictClassMock([NSURLSessionDataTask class]);
29 |
30 | // Validate request content.
31 | FIRRequestValidationBlock nonOptionalRequestValidationBlock =
32 | requestValidationBlock ?: ^BOOL(id request) {
33 | return YES;
34 | };
35 |
36 | id URLRequestValidationArg = [OCMArg checkWithBlock:nonOptionalRequestValidationBlock];
37 |
38 | // Save task completion to be called on the `[NSURLSessionDataTask resume]`
39 | __block void (^taskCompletion)(NSData *, NSURLResponse *, NSError *);
40 | id completionArg = [OCMArg checkWithBlock:^BOOL(id obj) {
41 | taskCompletion = obj;
42 | return YES;
43 | }];
44 |
45 | // Expect `dataTaskWithRequest` to be called.
46 | OCMExpect([URLSessionMock dataTaskWithRequest:URLRequestValidationArg
47 | completionHandler:completionArg])
48 | .andReturn(mockDataTask);
49 |
50 | // Expect the task to be resumed and call the task completion.
51 | OCMExpect([(NSURLSessionDataTask *)mockDataTask resume]).andDo(^(NSInvocation *invocation) {
52 | taskCompletion(body, response, error);
53 | });
54 |
55 | return mockDataTask;
56 | }
57 |
58 | + (NSHTTPURLResponse *)HTTPResponseWithCode:(NSInteger)statusCode {
59 | return [[NSHTTPURLResponse alloc] initWithURL:[NSURL URLWithString:@"http://localhost"]
60 | statusCode:statusCode
61 | HTTPVersion:@"HTTP/1.1"
62 | headerFields:nil];
63 | }
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Swizzler/GULRuntimeClassDiffTests.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import
16 |
17 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.h"
18 |
19 | @interface GULRuntimeClassDiffTests : XCTestCase
20 |
21 | @end
22 |
23 | @implementation GULRuntimeClassDiffTests
24 |
25 | /** Tests various different permutations of diff hashes and equality. */
26 | - (void)testHashAndEquality {
27 | GULRuntimeClassDiff *classDiff1 = [[GULRuntimeClassDiff alloc] init];
28 | classDiff1.aClass = [self class];
29 | GULRuntimeClassDiff *classDiff2 = [[GULRuntimeClassDiff alloc] init];
30 | classDiff2.aClass = [NSObject class];
31 | XCTAssertNotEqual([classDiff1 hash], [classDiff2 hash]);
32 | XCTAssertNotEqualObjects(classDiff1, classDiff2);
33 |
34 | classDiff2.aClass = [self class];
35 | XCTAssertEqual([classDiff1 hash], [classDiff2 hash]);
36 | XCTAssertEqualObjects(classDiff1, classDiff2);
37 |
38 | classDiff1.addedClassSelectors = [[NSSet alloc] initWithObjects:@"selector", nil];
39 | XCTAssertNotEqual([classDiff1 hash], [classDiff2 hash]);
40 | XCTAssertNotEqualObjects(classDiff1, classDiff2);
41 |
42 | classDiff2.addedClassSelectors = [[NSSet alloc] initWithObjects:@"selector", nil];
43 | XCTAssertEqual([classDiff1 hash], [classDiff2 hash]);
44 | XCTAssertEqualObjects(classDiff1, classDiff2);
45 |
46 | classDiff1.modifiedImps = [[NSSet alloc] initWithObjects:@"someImp", nil];
47 | XCTAssertNotEqual([classDiff1 hash], [classDiff2 hash]);
48 | XCTAssertNotEqualObjects(classDiff1, classDiff2);
49 |
50 | classDiff2.modifiedImps = [[NSSet alloc] initWithObjects:@"someImp", nil];
51 | XCTAssertEqual([classDiff1 hash], [classDiff2 hash]);
52 | XCTAssertEqualObjects(classDiff1, classDiff2);
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Swizzler/GULRuntimeDiffTests.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import
16 |
17 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeClassDiff.h"
18 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeDiff.h"
19 |
20 | @interface GULRuntimeDiffTests : XCTestCase
21 |
22 | @end
23 |
24 | @implementation GULRuntimeDiffTests
25 |
26 | /** Tests various different permutations of diff hashes and equality. */
27 | - (void)testHashAndEquality {
28 | GULRuntimeDiff *runtimeDiff1 = [[GULRuntimeDiff alloc] init];
29 | GULRuntimeDiff *runtimeDiff2 = [[GULRuntimeDiff alloc] init];
30 | XCTAssertEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
31 | XCTAssertEqualObjects(runtimeDiff1, runtimeDiff2);
32 |
33 | runtimeDiff1.addedClasses = [[NSSet alloc] initWithObjects:@"FakeClass", nil];
34 | XCTAssertNotEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
35 | XCTAssertNotEqualObjects(runtimeDiff1, runtimeDiff2);
36 |
37 | runtimeDiff2.addedClasses = [[NSSet alloc] initWithObjects:@"FakeClass", nil];
38 | XCTAssertEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
39 | XCTAssertEqualObjects(runtimeDiff1, runtimeDiff2);
40 |
41 | runtimeDiff1.removedClasses = [[NSSet alloc] initWithObjects:@"FakeClass", nil];
42 | XCTAssertNotEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
43 | XCTAssertNotEqualObjects(runtimeDiff1, runtimeDiff2);
44 |
45 | runtimeDiff2.removedClasses = [[NSSet alloc] initWithObjects:@"FakeClass", nil];
46 | XCTAssertEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
47 | XCTAssertEqualObjects(runtimeDiff1, runtimeDiff2);
48 |
49 | runtimeDiff2.classDiffs = [[NSSet alloc] init];
50 | XCTAssertEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
51 | XCTAssertEqualObjects(runtimeDiff1, runtimeDiff2);
52 |
53 | runtimeDiff1.classDiffs = [[NSSet alloc] init];
54 | XCTAssertEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
55 | XCTAssertEqualObjects(runtimeDiff1, runtimeDiff2);
56 |
57 | GULRuntimeClassDiff *classDiff1 = [[GULRuntimeClassDiff alloc] init];
58 | classDiff1.aClass = [self class];
59 | classDiff1.addedClassSelectors = [[NSSet alloc] initWithObjects:@"selector", nil];
60 |
61 | GULRuntimeClassDiff *classDiff2 = [[GULRuntimeClassDiff alloc] init];
62 | classDiff2.aClass = [self class];
63 | classDiff2.addedClassSelectors = [[NSSet alloc] initWithObjects:@"selector2", nil];
64 |
65 | runtimeDiff1.classDiffs = [runtimeDiff1.classDiffs setByAddingObject:classDiff1];
66 | XCTAssertNotEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
67 | XCTAssertNotEqualObjects(runtimeDiff1, runtimeDiff2);
68 |
69 | runtimeDiff2.classDiffs = [runtimeDiff2.classDiffs setByAddingObject:classDiff1];
70 | XCTAssertEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
71 | XCTAssertEqualObjects(runtimeDiff1, runtimeDiff2);
72 |
73 | runtimeDiff1.classDiffs = [runtimeDiff1.classDiffs setByAddingObject:classDiff2];
74 | XCTAssertNotEqual([runtimeDiff1 hash], [runtimeDiff2 hash]);
75 | XCTAssertNotEqualObjects(runtimeDiff1, runtimeDiff2);
76 | }
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Swizzler/GULRuntimeSnapshotTests.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import
16 | #import
17 |
18 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeDiff.h"
19 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeSnapshot.h"
20 |
21 | @interface GULRuntimeSnapshotTestsTestClass : NSObject
22 |
23 | @end
24 |
25 | @implementation GULRuntimeSnapshotTestsTestClass
26 |
27 | - (NSString *)description {
28 | return [super description];
29 | }
30 |
31 | @end
32 |
33 | @interface GULRuntimeSnapshotTests : XCTestCase
34 |
35 | @end
36 |
37 | @implementation GULRuntimeSnapshotTests
38 |
39 | /** Tests default init. */
40 | - (void)testInitDoesntThrow {
41 | XCTAssertNoThrow([[GULRuntimeSnapshot alloc] init]);
42 | }
43 |
44 | /** Tests the designated initializer. */
45 | - (void)testDesignatedInitializer {
46 | XCTAssertNoThrow([[GULRuntimeSnapshot alloc] initWithClasses:nil]);
47 | NSSet *classes = [NSSet setWithObjects:[NSString class], [NSObject class], [self class], nil];
48 | XCTAssertNoThrow([[GULRuntimeSnapshot alloc] initWithClasses:classes]);
49 | }
50 |
51 | /** Tests equality of snapshots. */
52 | - (void)testEquality {
53 | GULRuntimeSnapshot *snapshot1 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
54 | GULRuntimeSnapshot *snapshot2 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
55 | XCTAssertEqualObjects(snapshot1, snapshot2);
56 | snapshot1 = nil;
57 | snapshot2 = nil;
58 |
59 | NSSet *classSet = [NSSet setWithObject:[GULRuntimeSnapshotTestsTestClass class]];
60 | snapshot1 = [[GULRuntimeSnapshot alloc] initWithClasses:classSet];
61 | snapshot2 = [[GULRuntimeSnapshot alloc] initWithClasses:classSet];
62 | XCTAssertEqualObjects(snapshot1, snapshot2);
63 |
64 | [snapshot1 capture];
65 | [snapshot2 capture];
66 | XCTAssertEqualObjects(snapshot1, snapshot2);
67 |
68 | SEL selector = @selector(description);
69 | Method description = class_getInstanceMethod([GULRuntimeSnapshotTestsTestClass class], selector);
70 | IMP newDescriptionIMP = imp_implementationWithBlock(^(id _self) {
71 | return @"swizzled description";
72 | });
73 | IMP originalDescriptionIMP = method_getImplementation(description);
74 | IMP probableOriginalDescriptionIMP = method_setImplementation(description, newDescriptionIMP);
75 | XCTAssertEqual(probableOriginalDescriptionIMP, originalDescriptionIMP);
76 |
77 | [snapshot1 capture];
78 | [snapshot2 capture];
79 | XCTAssertEqualObjects(snapshot1, snapshot2);
80 |
81 | method_setImplementation(description, originalDescriptionIMP);
82 |
83 | [snapshot2 capture];
84 | XCTAssertNotEqualObjects(snapshot2, snapshot1);
85 | [snapshot1 capture];
86 | XCTAssertEqualObjects(snapshot1, snapshot2);
87 | }
88 |
89 | /** Tests capturing snapshots doesn't throw. */
90 | - (void)testCapture {
91 | GULRuntimeSnapshot *snapshot1 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
92 | XCTAssertNoThrow([snapshot1 capture]);
93 |
94 | GULRuntimeSnapshot *snapshot2 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
95 | XCTAssertNoThrow([snapshot2 capture]);
96 | }
97 |
98 | /** Tests detecting a new class works. */
99 | - (void)testNewClassDetected {
100 | GULRuntimeSnapshot *snapshot1 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
101 | [snapshot1 capture];
102 |
103 | Class newClass = objc_allocateClassPair([NSObject class], "GULNewClass", 0);
104 | objc_registerClassPair(newClass);
105 |
106 | GULRuntimeSnapshot *snapshot2 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
107 | [snapshot2 capture];
108 |
109 | GULRuntimeDiff *diff = [snapshot1 diff:snapshot2];
110 | XCTAssertGreaterThan(diff.addedClasses.count, 0);
111 | BOOL found = NO;
112 | for (NSString *class in diff.addedClasses) {
113 | if ([class isEqualToString:@"GULNewClass"]) {
114 | found = YES;
115 | break;
116 | }
117 | }
118 | XCTAssertTrue(found);
119 | }
120 |
121 | /** Tests detecting a class deletion works. */
122 | - (void)testClassRemovedDetected {
123 | Class newClass = objc_allocateClassPair([NSObject class], "GULNewClass2", 0);
124 | objc_registerClassPair(newClass);
125 |
126 | GULRuntimeSnapshot *snapshot1 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
127 | [snapshot1 capture];
128 |
129 | objc_disposeClassPair(NSClassFromString(@"GULNewClass2"));
130 |
131 | GULRuntimeSnapshot *snapshot2 = [[GULRuntimeSnapshot alloc] initWithClasses:nil];
132 | [snapshot2 capture];
133 |
134 | GULRuntimeDiff *diff = [snapshot1 diff:snapshot2];
135 | XCTAssertGreaterThan(diff.removedClasses.count, 0);
136 | BOOL found = NO;
137 | for (NSString *class in diff.removedClasses) {
138 | if ([class isEqualToString:@"GULNewClass2"]) {
139 | found = YES;
140 | break;
141 | }
142 | }
143 | XCTAssertTrue(found);
144 | }
145 |
146 | @end
147 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Swizzler/GULRuntimeStateHelperTests.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 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 | #import
16 | #import
17 |
18 | #import "GoogleUtilities/SwizzlerTestHelpers/GULRuntimeStateHelper.h"
19 |
20 | @interface GULRuntimeStateHelperTestHelperClass : NSObject
21 |
22 | @end
23 |
24 | @implementation GULRuntimeStateHelperTestHelperClass
25 |
26 | @end
27 |
28 | @interface GULRuntimeStateHelperTests : XCTestCase
29 |
30 | @end
31 |
32 | @implementation GULRuntimeStateHelperTests
33 |
34 | - (void)testCaptureRuntimeState {
35 | NSUInteger snapshot1 = 0;
36 | XCTAssertNoThrow(snapshot1 = [GULRuntimeStateHelper captureRuntimeState]);
37 | }
38 |
39 | - (void)testDiffBetweenFirstSnapshotSecondSnapshot {
40 | NSUInteger snapshot1 = [GULRuntimeStateHelper captureRuntimeState];
41 |
42 | NSString *newClassName = [NSStringFromClass([self class]) stringByAppendingString:@"_gen"];
43 | Class newSubclass = objc_allocateClassPair([self class], [newClassName UTF8String], 0);
44 | objc_registerClassPair(newSubclass);
45 |
46 | Method dummyMethod = class_getInstanceMethod([self class], @selector(dummyMethod));
47 | IMP originalIMP = method_getImplementation(dummyMethod);
48 | NSString *originalIMPString = [NSString stringWithFormat:@"%p", originalIMP];
49 | IMP newIMP = imp_implementationWithBlock((NSString *)^(id _self) {
50 | return @"Goodbye!";
51 | });
52 | method_setImplementation(dummyMethod, newIMP);
53 |
54 | NSUInteger snapshot2 = [GULRuntimeStateHelper captureRuntimeState];
55 | GULRuntimeDiff *diff = [GULRuntimeStateHelper diffBetween:snapshot1 secondSnapshot:snapshot2];
56 |
57 | BOOL found = NO;
58 | for (NSString *class in diff.addedClasses) {
59 | if ([class isEqualToString:newClassName]) {
60 | found = YES;
61 | break;
62 | }
63 | }
64 | XCTAssertTrue(found, @"The generated class above should be found in the list of added classes");
65 |
66 | found = NO;
67 | for (GULRuntimeClassDiff *classDiff in diff.classDiffs) {
68 | for (NSString *modifiedIMP in classDiff.modifiedImps) {
69 | if ([modifiedIMP containsString:originalIMPString]) {
70 | found = YES;
71 | break;
72 | }
73 | }
74 | }
75 | XCTAssertTrue(found, @"One of the classdiffs should contain the address of the original IMP of "
76 | "the method that was modified above");
77 | }
78 |
79 | #pragma mark - Helper methods
80 |
81 | /** Exists to just be swizzled, to test detection capability.
82 | *
83 | * @return The string "Hello!".
84 | */
85 | - (NSString *)dummyMethod {
86 | return @"Hello!";
87 | }
88 |
89 | @end
90 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Utils/GULTestKeychain.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google
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 | #import
17 | #import
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | #if TARGET_OS_OSX
22 |
23 | @interface GULTestKeychain : NSObject
24 |
25 | - (nullable instancetype)init;
26 |
27 | @property(nonatomic, readonly, nullable) SecKeychainRef testKeychainRef;
28 |
29 | @end
30 |
31 | #endif // TARGET_OS_OSX
32 |
33 | NS_ASSUME_NONNULL_END
34 |
--------------------------------------------------------------------------------
/GoogleUtilities/Tests/Unit/Utils/GULTestKeychain.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Google
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 | #import
18 | #if TARGET_OS_OSX
19 |
20 | #import "GoogleUtilities/Tests/Unit/Utils/GULTestKeychain.h"
21 |
22 | #import
23 |
24 | @implementation GULTestKeychain
25 |
26 | - (nullable instancetype)init {
27 | self = [super init];
28 | if (self) {
29 | SecKeychainRef privateKeychain;
30 | NSString *keychainPath =
31 | [NSTemporaryDirectory() stringByAppendingPathComponent:@"GULTestKeychain"];
32 | if ([[NSFileManager defaultManager] fileExistsAtPath:keychainPath]) {
33 | NSError *error;
34 | if (![[NSFileManager defaultManager] removeItemAtPath:keychainPath error:&error]) {
35 | NSLog(@"Failed to delete existing test keychain: %@", error);
36 | return nil;
37 | }
38 | }
39 | #pragma clang diagnostic push
40 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
41 | OSStatus result = SecKeychainCreate([keychainPath cStringUsingEncoding:NSUTF8StringEncoding], 0,
42 | "1", false, nil, &privateKeychain);
43 | #pragma clang diagnostic pop
44 | if (result != errSecSuccess) {
45 | NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:result userInfo:nil];
46 | NSLog(@"SecKeychainCreate error: %@", error);
47 | return nil;
48 | }
49 | _testKeychainRef = privateKeychain;
50 | }
51 | return self;
52 | }
53 |
54 | - (void)dealloc {
55 | if (self.testKeychainRef) {
56 | #pragma clang diagnostic push
57 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
58 | OSStatus result = SecKeychainDelete(self.testKeychainRef);
59 | #pragma clang diagnostic pop
60 | if (result != errSecSuccess) {
61 | NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:result userInfo:nil];
62 | NSLog(@"SecKeychainCreate error: %@", error);
63 | }
64 |
65 | CFRelease(self.testKeychainRef);
66 | }
67 | }
68 |
69 | @end
70 |
71 | #endif // TARGET_OS_OSX
72 |
--------------------------------------------------------------------------------
/GoogleUtilities/UserDefaults/GULUserDefaults.m:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Google
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 | #import "GoogleUtilities/UserDefaults/Public/GoogleUtilities/GULUserDefaults.h"
16 |
17 | #import "GoogleUtilities/Logger/Public/GoogleUtilities/GULLogger.h"
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | static NSString *const kGULLogFormat = @"I-GUL%06ld";
22 |
23 | static GULLoggerService kGULLogUserDefaultsService = @"[GoogleUtilities/UserDefaults]";
24 |
25 | typedef NS_ENUM(NSInteger, GULUDMessageCode) {
26 | GULUDMessageCodeInvalidKeyGet = 1,
27 | GULUDMessageCodeInvalidKeySet = 2,
28 | GULUDMessageCodeInvalidObjectSet = 3,
29 | GULUDMessageCodeSynchronizeFailed = 4,
30 | };
31 |
32 | @interface GULUserDefaults ()
33 |
34 | @property(nonatomic, readonly) NSUserDefaults *userDefaults;
35 |
36 | @end
37 |
38 | @implementation GULUserDefaults
39 |
40 | + (GULUserDefaults *)standardUserDefaults {
41 | static GULUserDefaults *standardUserDefaults;
42 | static dispatch_once_t onceToken;
43 | dispatch_once(&onceToken, ^{
44 | standardUserDefaults = [[GULUserDefaults alloc] init];
45 | });
46 | return standardUserDefaults;
47 | }
48 |
49 | - (instancetype)init {
50 | return [self initWithSuiteName:nil];
51 | }
52 |
53 | - (instancetype)initWithSuiteName:(nullable NSString *)suiteName {
54 | self = [super init];
55 |
56 | NSString *name = [suiteName copy];
57 |
58 | if (self) {
59 | _userDefaults = name.length ? [[NSUserDefaults alloc] initWithSuiteName:name]
60 | : [NSUserDefaults standardUserDefaults];
61 | }
62 |
63 | return self;
64 | }
65 |
66 | - (nullable id)objectForKey:(NSString *)defaultName {
67 | NSString *key = [defaultName copy];
68 | if (![key isKindOfClass:[NSString class]] || !key.length) {
69 | GULOSLogWarning(kGULLogSubsystem, @"", NO,
70 | [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeyGet],
71 | @"Cannot get object for invalid user default key.");
72 | return nil;
73 | }
74 |
75 | return [self.userDefaults objectForKey:key];
76 | }
77 |
78 | - (void)setObject:(nullable id)value forKey:(NSString *)defaultName {
79 | NSString *key = [defaultName copy];
80 | if (![key isKindOfClass:[NSString class]] || !key.length) {
81 | GULOSLogWarning(kGULLogSubsystem, kGULLogUserDefaultsService, NO,
82 | [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeySet],
83 | @"Cannot set object for invalid user default key.");
84 | return;
85 | }
86 | if (!value) {
87 | [self.userDefaults removeObjectForKey:key];
88 | return;
89 | }
90 | BOOL isAcceptableValue =
91 | [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]] ||
92 | [value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]] ||
93 | [value isKindOfClass:[NSDate class]] || [value isKindOfClass:[NSData class]];
94 | if (!isAcceptableValue) {
95 | GULOSLogWarning(
96 | kGULLogSubsystem, kGULLogUserDefaultsService, NO,
97 | [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidObjectSet],
98 | @"Cannot set invalid object to user defaults. Must be a string, number, array, "
99 | @"dictionary, date, or data. Value: %@",
100 | value);
101 | return;
102 | }
103 |
104 | [self.userDefaults setObject:value forKey:key];
105 | }
106 |
107 | - (void)removeObjectForKey:(NSString *)key {
108 | [self setObject:nil forKey:key];
109 | }
110 |
111 | #pragma mark - Getters
112 |
113 | - (NSInteger)integerForKey:(NSString *)defaultName {
114 | NSNumber *object = [self objectForKey:defaultName];
115 | return object.integerValue;
116 | }
117 |
118 | - (float)floatForKey:(NSString *)defaultName {
119 | NSNumber *object = [self objectForKey:defaultName];
120 | return object.floatValue;
121 | }
122 |
123 | - (double)doubleForKey:(NSString *)defaultName {
124 | NSNumber *object = [self objectForKey:defaultName];
125 | return object.doubleValue;
126 | }
127 |
128 | - (BOOL)boolForKey:(NSString *)defaultName {
129 | NSNumber *object = [self objectForKey:defaultName];
130 | return object.boolValue;
131 | }
132 |
133 | - (nullable NSString *)stringForKey:(NSString *)defaultName {
134 | return [self objectForKey:defaultName];
135 | }
136 |
137 | - (nullable NSArray *)arrayForKey:(NSString *)defaultName {
138 | return [self objectForKey:defaultName];
139 | }
140 |
141 | - (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName {
142 | return [self objectForKey:defaultName];
143 | }
144 |
145 | #pragma mark - Setters
146 |
147 | - (void)setInteger:(NSInteger)integer forKey:(NSString *)defaultName {
148 | [self setObject:@(integer) forKey:defaultName];
149 | }
150 |
151 | - (void)setFloat:(float)value forKey:(NSString *)defaultName {
152 | [self setObject:@(value) forKey:defaultName];
153 | }
154 |
155 | - (void)setDouble:(double)doubleNumber forKey:(NSString *)defaultName {
156 | [self setObject:@(doubleNumber) forKey:defaultName];
157 | }
158 |
159 | - (void)setBool:(BOOL)boolValue forKey:(NSString *)defaultName {
160 | [self setObject:@(boolValue) forKey:defaultName];
161 | }
162 |
163 | @end
164 |
165 | NS_ASSUME_NONNULL_END
166 |
--------------------------------------------------------------------------------
/GoogleUtilities/UserDefaults/Public/GoogleUtilities/GULUserDefaults.h:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Google
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 | #import
16 |
17 | NS_ASSUME_NONNULL_BEGIN
18 |
19 | /// A thread-safe user defaults that uses C functions from CFPreferences.h instead of
20 | /// `NSUserDefaults`. This is to avoid sending an `NSNotification` when it's changed from a
21 | /// background thread to avoid crashing. // TODO: Insert radar number here.
22 | @interface GULUserDefaults : NSObject
23 |
24 | /// A shared user defaults similar to +[NSUserDefaults standardUserDefaults] and accesses the same
25 | /// data of the standardUserDefaults.
26 | + (GULUserDefaults *)standardUserDefaults;
27 |
28 | /// Initializes preferences with a suite name that is the same with the NSUserDefaults' suite name.
29 | /// Both of CFPreferences and NSUserDefaults share the same plist file so their data will exactly
30 | /// the same.
31 | ///
32 | /// @param suiteName The name of the suite of the user defaults.
33 | - (instancetype)initWithSuiteName:(nullable NSString *)suiteName;
34 |
35 | #pragma mark - Getters
36 |
37 | /// Searches the receiver's search list for a default with the key 'defaultName' and return it. If
38 | /// another process has changed defaults in the search list, NSUserDefaults will automatically
39 | /// update to the latest values. If the key in question has been marked as ubiquitous via a Defaults
40 | /// Configuration File, the latest value may not be immediately available, and the registered value
41 | /// will be returned instead.
42 | - (nullable id)objectForKey:(NSString *)defaultName;
43 |
44 | /// Equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray.
45 | - (nullable NSArray *)arrayForKey:(NSString *)defaultName;
46 |
47 | /// Equivalent to -objectForKey:, except that it will return nil if the value
48 | /// is not an NSDictionary.
49 | - (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName;
50 |
51 | /// Equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString
52 | /// representation. If a non-string non-number value is found, nil will be returned.
53 | - (nullable NSString *)stringForKey:(NSString *)defaultName;
54 |
55 | /// Equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the
56 | /// value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString,
57 | /// it will be converted to NSInteger if possible. If the value is a boolean, it will be converted
58 | /// to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0
59 | /// will be returned.
60 | - (NSInteger)integerForKey:(NSString *)defaultName;
61 |
62 | /// Similar to -integerForKey:, except that it returns a float, and boolean values will not be
63 | /// converted.
64 | - (float)floatForKey:(NSString *)defaultName;
65 |
66 | /// Similar to -integerForKey:, except that it returns a double, and boolean values will not be
67 | /// converted.
68 | - (double)doubleForKey:(NSString *)defaultName;
69 |
70 | /// Equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value
71 | /// is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an
72 | /// NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string
73 | /// will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned.
74 | - (BOOL)boolForKey:(NSString *)defaultName;
75 |
76 | #pragma mark - Setters
77 |
78 | /// Immediately stores a value (or removes the value if `nil` is passed as the value) for the
79 | /// provided key in the search list entry for the receiver's suite name in the current user and any
80 | /// host, then asynchronously stores the value persistently, where it is made available to other
81 | /// processes.
82 | - (void)setObject:(nullable id)value forKey:(NSString *)defaultName;
83 |
84 | /// Equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber.
85 | - (void)setFloat:(float)value forKey:(NSString *)defaultName;
86 |
87 | /// Equivalent to -setObject:forKey: except that the value is converted from a double to an
88 | /// NSNumber.
89 | - (void)setDouble:(double)value forKey:(NSString *)defaultName;
90 |
91 | /// Equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an
92 | /// NSNumber.
93 | - (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName;
94 |
95 | /// Equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber.
96 | - (void)setBool:(BOOL)value forKey:(NSString *)defaultName;
97 |
98 | #pragma mark - Removing Defaults
99 |
100 | /// Equivalent to -[... setObject:nil forKey:defaultName]
101 | - (void)removeObjectForKey:(NSString *)defaultName;
102 |
103 | @end
104 |
105 | NS_ASSUME_NONNULL_END
106 |
--------------------------------------------------------------------------------
/GoogleUtilities/UserDefaults/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyTrackingDomains
8 |
9 |
10 | NSPrivacyCollectedDataTypes
11 |
12 |
13 | NSPrivacyAccessedAPITypes
14 |
15 |
16 | NSPrivacyAccessedAPIType
17 | NSPrivacyAccessedAPICategoryUserDefaults
18 | NSPrivacyAccessedAPITypeReasons
19 |
20 | 1C8F.1
21 | C56D.1
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Mintfile:
--------------------------------------------------------------------------------
1 | nicklockwood/SwiftFormat@0.49.2
2 |
--------------------------------------------------------------------------------
/SwiftPMTests/objc-import-test/objc-header.m:
--------------------------------------------------------------------------------
1 | // Copyright 2021 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 | #import "GoogleUtilities/GULApplication.h"
16 | #import "GoogleUtilities/GULKeychainStorage.h"
17 | #import "GoogleUtilities/GULLogger.h"
18 | #import "GoogleUtilities/GULNSData+zlib.h"
19 | #import "GoogleUtilities/GULNetwork.h"
20 | #import "GoogleUtilities/GULReachabilityChecker.h"
21 | #import "GoogleUtilities/GULSwizzler.h"
22 | #import "GoogleUtilities/GULUserDefaults.h"
23 |
24 | #import
25 | #import
26 | #import
27 | #import
28 | #import
29 | #import
30 | #import
31 | #import
32 |
--------------------------------------------------------------------------------
/SwiftPMTests/objc-import-test/objc-module.m:
--------------------------------------------------------------------------------
1 | // Copyright 2021 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 | @import GoogleUtilities_AppDelegateSwizzler;
16 | @import GoogleUtilities_Environment;
17 | @import GoogleUtilities_Logger;
18 | @import GoogleUtilities_MethodSwizzler;
19 | @import GoogleUtilities_Network;
20 | @import GoogleUtilities_NSData;
21 | @import GoogleUtilities_Reachability;
22 | @import GoogleUtilities_UserDefaults;
23 |
--------------------------------------------------------------------------------
/SwiftPMTests/swift-test/main.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2021 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 | import Foundation
16 | import GoogleUtilities_AppDelegateSwizzler
17 | import GoogleUtilities_Environment
18 | import GoogleUtilities_Logger
19 | import GoogleUtilities_MethodSwizzler
20 | import GoogleUtilities_Network
21 | import GoogleUtilities_NSData
22 | import GoogleUtilities_Reachability
23 | import GoogleUtilities_UserDefaults
24 |
25 | import XCTest
26 |
27 | class importTest: XCTestCase {
28 | func testImports() throws {
29 | XCTAssertFalse(GULAppEnvironmentUtil.isAppStoreReceiptSandbox())
30 | XCTAssertFalse(GULAppEnvironmentUtil.isFromAppStore())
31 | #if targetEnvironment(simulator)
32 | XCTAssertTrue(GULAppEnvironmentUtil.isSimulator())
33 | #else
34 | XCTAssertFalse(GULAppEnvironmentUtil.isSimulator())
35 | #endif
36 | XCTAssertFalse(GULAppEnvironmentUtil.isAppExtension())
37 |
38 | #if os(macOS) || targetEnvironment(macCatalyst)
39 | // Device model should now return the appropriate hardware model on macOS.
40 | XCTAssertNotEqual(GULAppEnvironmentUtil.deviceModel(), "x86_64")
41 | #else
42 | // Device model should show up as x86_64 for iOS, tvOS, and watchOS
43 | // simulators.
44 | let device = GULAppEnvironmentUtil.deviceModel()
45 | XCTAssertTrue(device == "x86_64" || device == "arm64")
46 | #endif
47 |
48 | print("System version? Answer: \(GULAppEnvironmentUtil.systemVersion())")
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/setup-scripts.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2021 Google LLC
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 | # http://www.apache.org/licenses/LICENSE-2.0
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | git clone \
15 | --depth 1 \
16 | --no-checkout \
17 | https://github.com/firebase/firebase-ios-sdk.git \
18 | ;
19 | cd firebase-ios-sdk
20 | git checkout main -- scripts
21 | cd ..
22 | ln -s firebase-ios-sdk/scripts scripts
23 |
--------------------------------------------------------------------------------
/third_party/IsAppEncrypted/IsAppEncrypted.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Landon J. Fuller
2 | // All rights reserved.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to
6 | // deal in the Software without restriction, including without limitation the
7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | // sell copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | // IN THE SOFTWARE.
21 | //
22 | // Comment from
23 | // iPhone Dev
24 | // Wiki Crack Prevention:
25 | // App Store binaries are signed by both their developer and Apple. This
26 | // encrypts the binary so that decryption keys are needed in order to make the
27 | // binary readable. When iOS executes the binary, the decryption keys are used
28 | // to decrypt the binary into a readable state where it is then loaded into
29 | // memory and executed. iOS can tell the encryption status of a binary via the
30 | // cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If
31 | // cryptid is a non-zero value then the binary is encrypted.
32 | //
33 | // 'Cracking' works by letting the kernel decrypt the binary then siphoning the
34 | // decrypted data into a new binary file, resigning, and repackaging. This will
35 | // only work on jailbroken devices as codesignature validation has been
36 | // removed. Resigning takes place because while the codesignature doesn't have
37 | // to be valid thanks to the jailbreak, it does have to be in place unless you
38 | // have AppSync or similar to disable codesignature checks.
39 | //
40 | // More information at
41 | // Landon Fuller's blog
42 |
43 | #import "third_party/IsAppEncrypted/Public/IsAppEncrypted.h"
44 |
45 | #import
46 | #import
47 |
48 | /// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from
49 | /// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just
50 | /// provide the definitions here.
51 | #if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO)
52 | #define LC_ENCRYPTION_INFO 0x21
53 | struct encryption_info_command {
54 | uint32_t cmd;
55 | uint32_t cmdsize;
56 | uint32_t cryptoff;
57 | uint32_t cryptsize;
58 | uint32_t cryptid;
59 | };
60 | #endif
61 |
62 | BOOL IsAppEncrypted(void) {
63 | const struct mach_header *executableHeader = NULL;
64 | for (uint32_t i = 0; i < _dyld_image_count(); i++) {
65 | const struct mach_header *header = _dyld_get_image_header(i);
66 | if (header && header->filetype == MH_EXECUTE) {
67 | executableHeader = header;
68 | break;
69 | }
70 | }
71 |
72 | if (!executableHeader) {
73 | return NO;
74 | }
75 |
76 | BOOL is64bit = (executableHeader->magic == MH_MAGIC_64);
77 | uintptr_t cursor = (uintptr_t)executableHeader +
78 | (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
79 | const struct segment_command *segmentCommand = NULL;
80 | uint32_t i = 0;
81 |
82 | while (i++ < executableHeader->ncmds) {
83 | segmentCommand = (struct segment_command *)cursor;
84 |
85 | if (!segmentCommand) {
86 | continue;
87 | }
88 |
89 | if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) ||
90 | (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) {
91 | if (is64bit) {
92 | struct encryption_info_command_64 *cryptCmd =
93 | (struct encryption_info_command_64 *)segmentCommand;
94 | return cryptCmd && cryptCmd->cryptid != 0;
95 | } else {
96 | struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand;
97 | return cryptCmd && cryptCmd->cryptid != 0;
98 | }
99 | }
100 | cursor += segmentCommand->cmdsize;
101 | }
102 |
103 | return NO;
104 | }
105 |
--------------------------------------------------------------------------------
/third_party/IsAppEncrypted/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Landon J. Fuller
2 | All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | and associated documentation files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
8 | Software is furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or
11 | substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/third_party/IsAppEncrypted/Public/IsAppEncrypted.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Landon J. Fuller
2 | // All rights reserved.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to
6 | // deal in the Software without restriction, including without limitation the
7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | // sell copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | // IN THE SOFTWARE.
21 |
22 | #import
23 |
24 | BOOL IsAppEncrypted(void);
25 |
--------------------------------------------------------------------------------