Skip to content

Commit

Permalink
Add FXIOS-7616 [v121] Debug utility to help identify bloat in app con…
Browse files Browse the repository at this point in the history
…tainer (#16975) (#17047)

* [7616] Add debug utility to help identify problems with excessive bloat in app container or cache storage. WIP

* [7616] Fix SwiftLint warning

* [7616] Provide nicer output for report by ordering by size

* [7616] Some general cleanup and minor refactors

* [7616] Line spacing

(cherry picked from commit 6906199)

Co-authored-by: mattreaganmozilla <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
mergify[bot] and mattreaganmozilla authored Nov 6, 2023
1 parent df2eccb commit 62d6b25
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
1DA3CE5F24EEE7C600422BB2 /* LegacyTabDataRetriever.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA3CE5E24EEE7C600422BB2 /* LegacyTabDataRetriever.swift */; };
1DA3CE6324EEE83200422BB2 /* LegacySavedTab+ConfigureExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA3CE6224EEE83200422BB2 /* LegacySavedTab+ConfigureExtension.swift */; };
1DA3CE6724EEE86C00422BB2 /* AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E65075641E37F7AB006961AC /* AppInfo.swift */; };
1DA710072AE7106B00677F6B /* AppDataUsageReportSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA710062AE7106B00677F6B /* AppDataUsageReportSetting.swift */; };
1DDAD13E24F0651C007623C8 /* TopSitesWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DDAD13C24F064F7007623C8 /* TopSitesWidget.swift */; };
1DF426CF251BDF6A0086386A /* photon-colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C49854D206173C800893DAE /* photon-colors.swift */; };
1DFE57FB27B2CB870025DE58 /* HighlightItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFE57FA27B2CB870025DE58 /* HighlightItem.swift */; };
Expand Down Expand Up @@ -2072,6 +2073,7 @@
1DA3CE5E24EEE7C600422BB2 /* LegacyTabDataRetriever.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyTabDataRetriever.swift; sourceTree = "<group>"; };
1DA3CE6224EEE83200422BB2 /* LegacySavedTab+ConfigureExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LegacySavedTab+ConfigureExtension.swift"; sourceTree = "<group>"; };
1DA64656B1F6A74800D22055 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/LoginManager.strings; sourceTree = "<group>"; };
1DA710062AE7106B00677F6B /* AppDataUsageReportSetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDataUsageReportSetting.swift; sourceTree = "<group>"; };
1DDAD13C24F064F7007623C8 /* TopSitesWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopSitesWidget.swift; sourceTree = "<group>"; };
1DE6449A95FE587845F9A459 /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/ErrorPages.strings; sourceTree = "<group>"; };
1DFE57FA27B2CB870025DE58 /* HighlightItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightItem.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -8339,6 +8341,7 @@
children = (
8CFD56872AAF057D003157A6 /* SwitchFakespotProduction.swift */,
8A3EF7FC2A2FCFAC00796E3A /* AppReviewPromptSetting.swift */,
1DA710062AE7106B00677F6B /* AppDataUsageReportSetting.swift */,
8A3EF7FE2A2FCFBB00796E3A /* ChangeToChinaSetting.swift */,
8A093D7C2A4B3E4F0099ABA5 /* DebugSettingsDelegate.swift */,
8A3EF7F12A2FCF4000796E3A /* DeleteExportedDataSetting.swift */,
Expand Down Expand Up @@ -12662,6 +12665,7 @@
8A3EF8172A2FD2B900796E3A /* AdvancedAccountSettings.swift in Sources */,
EBB89509219398E500EB91A0 /* TabContentBlocker+ContentScript.swift in Sources */,
216C133E29DCA8FF0097533B /* LegacyTabLayoutDelegate.swift in Sources */,
1DA710072AE7106B00677F6B /* AppDataUsageReportSetting.swift in Sources */,
D3BE7B461B054F8600641031 /* UITestAppDelegate.swift in Sources */,
C8DC90C72A06759E0008832B /* MarkupAttributionUtility.swift in Sources */,
23D57E6E25ED6F2700883FAD /* SearchViewController.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ class AppSettingsTableViewController: SettingsTableViewController,
ExperimentsSettings(settings: self, settingsDelegate: self),
ExportLogDataSetting(settings: self),
ExportBrowserDataSetting(settings: self),
AppDataUsageReportSetting(settings: self),
DeleteExportedDataSetting(settings: self),
ForceCrashSetting(settings: self),
ForgetSyncAuthStateDebugSetting(settings: self),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

import UIKit

class AppDataUsageReportSetting: HiddenSetting {
override var title: NSAttributedString? {
// Not localized for now.
return NSAttributedString(string: "App Data Usage Report",
attributes: [NSAttributedString.Key.foregroundColor: theme.colors.textPrimary])
}

override func onClick(_ navigationController: UINavigationController?) {
let results = generateAppDataSummary()
UIPasteboard.general.string = results

// Hidden debug utility not localized for now.
showSimpleAlert("Summary generated. Text has been copied to the clipboard.")
}

// MARK: - Internal Utilities

private func showSimpleAlert(_ message: String) {
let alert = UIAlertController(title: "App Data Usage",
message: message,
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
settings.present(alert, animated: true)
}

private func generateAppDataSummary() -> String {
var directoriesAndSizes: [String: UInt64] = [:]
var largeFileWarnings: [String: UInt64] = [:]
let fileManager = FileManager.default
let warningSize = 100 * 1024 * 1024 // (100MB) File size threshold to log for report

let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
let directories: [URL] = [cachesDirectory, documentsDirectory].compactMap({ $0 })

for baseDirectory in directories {
guard let enumerator = fileManager.enumerator(at: baseDirectory,
includingPropertiesForKeys: [URLResourceKey.fileSizeKey],
options: [],
errorHandler: nil) else { continue }
for case let fileURL as URL in enumerator {
var isDir: ObjCBool = false
let path = fileURL.path
if fileManager.fileExists(atPath: path, isDirectory: &isDir) && !isDir.boolValue {
let parentDir = fileURL.deletingLastPathComponent().path
if directoriesAndSizes[parentDir] == nil { directoriesAndSizes[parentDir] = 0 }
do {
let values = try fileURL.resourceValues(forKeys: [URLResourceKey.fileSizeKey])
let size = UInt64(values.fileSize ?? 0)

if size >= warningSize { largeFileWarnings[path] = size }

// Find any directory whose path is a valid prefix for the file path
// This allows us to tally the total sizes for parent directories
// along with nested children (if needed) at the same time.
for dir in directoriesAndSizes.keys where path.hasPrefix(dir) {
let newSize = (directoriesAndSizes[dir] ?? 0) + size
directoriesAndSizes[dir] = newSize
}
} catch {
print("Error checking file size: \(error)")
}
} else {
if directoriesAndSizes[path] == nil { directoriesAndSizes[path] = 0 }
}
}
}

let directoriesAndSizesSorted = directoriesAndSizes
.map({ return ($0, $1) })
.sorted(by: { return $0.1 > $1.1 })

var result = "FireFox Debug Utility: App Data Summary"
result += "\n======================================="
result += "\n"
for (dir, size) in directoriesAndSizesSorted {
result += "\nSize: \(size / 1024) kb \t\tDirectory: \t\(dir)"
}
result += "\n\n======================================="
result += "\nLarge files detected: \(largeFileWarnings.count)"
for (file, size) in largeFileWarnings {
result += "\nSize: \(size / 1024) kb \t\tFile: \t\(file)"
}
return result
}
}

0 comments on commit 62d6b25

Please sign in to comment.