Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Bug 1455672 - Telemetry for new share app extension (#3875)
Browse files Browse the repository at this point in the history
Stores events in the shared NSUserDefaults, and the host app adds these
to the telemetry events before this data is sent.
  • Loading branch information
garvankeeley committed May 8, 2018
1 parent 6661a8a commit dca2bf3
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 13 deletions.
5 changes: 5 additions & 0 deletions Client/Application/AppDelegate.swift
Expand Up @@ -238,6 +238,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati
}

func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if let profile = profile, let _ = profile.prefs.boolForKey(PrefsKeys.AppExtensionTelemetryOpenUrl) {
profile.prefs.removeObjectForKey(PrefsKeys.AppExtensionTelemetryOpenUrl)
UnifiedTelemetry.recordEvent(category: .appExtensionAction, method: .applicationOpenUrl, object: .url)
}

guard let routerpath = NavigationPath(url: url) else {
return false
}
Expand Down
40 changes: 28 additions & 12 deletions Client/Telemetry/UnifiedTelemetry.swift
Expand Up @@ -68,22 +68,36 @@ class UnifiedTelemetry {
return outputDict
}

Telemetry.default.beforeSerializePing(pingType: MobileEventPingBuilder.PingType) { (inputDict) -> [String: Any?] in
var outputDict = inputDict
Telemetry.default.beforeSerializePing(pingType: MobileEventPingBuilder.PingType) { (inputDict) -> [String: Any?] in
var outputDict = inputDict

var settings: [String: String?] = inputDict["settings"] as? [String: String?] ?? [:]
var settings: [String: String?] = inputDict["settings"] as? [String: String?] ?? [:]

let searchEngines = SearchEngines(prefs: profile.prefs, files: profile.files)
settings["defaultSearchEngine"] = searchEngines.defaultEngine.engineID ?? "custom"
let searchEngines = SearchEngines(prefs: profile.prefs, files: profile.files)
settings["defaultSearchEngine"] = searchEngines.defaultEngine.engineID ?? "custom"

if let windowBounds = UIApplication.shared.keyWindow?.bounds {
settings["windowWidth"] = String(describing: windowBounds.width)
settings["windowHeight"] = String(describing: windowBounds.height)
}
if let windowBounds = UIApplication.shared.keyWindow?.bounds {
settings["windowWidth"] = String(describing: windowBounds.width)
settings["windowHeight"] = String(describing: windowBounds.height)
}

outputDict["settings"] = settings

outputDict["settings"] = settings
return outputDict
}
// App Extension telemetry requires reading events stored in prefs, then clearing them from prefs.
if let extensionEvents = profile.prefs.arrayForKey(PrefsKeys.AppExtensionTelemetryEventArray) as? [[String: String]],
var pingEvents = outputDict["events"] as? [[Any?]] {
profile.prefs.removeObjectForKey(PrefsKeys.AppExtensionTelemetryEventArray)

extensionEvents.forEach { extensionEvent in
let category = UnifiedTelemetry.EventCategory.appExtensionAction.rawValue
let newEvent = TelemetryEvent(category: category, method: extensionEvent["method"] ?? "", object: extensionEvent["object"] ?? "")
pingEvents.append(newEvent.toArray())
}
outputDict["events"] = pingEvents
}

return outputDict
}

Telemetry.default.add(pingBuilderType: CorePingBuilder.self)
Telemetry.default.add(pingBuilderType: MobileEventPingBuilder.self)
Expand All @@ -99,6 +113,7 @@ class UnifiedTelemetry {
extension UnifiedTelemetry {
public enum EventCategory: String {
case action = "action"
case appExtensionAction = "app-extension-action"
}

public enum EventMethod: String {
Expand All @@ -114,6 +129,7 @@ extension UnifiedTelemetry {
case scan = "scan"
case tap = "tap"
case view = "view"
case applicationOpenUrl = "application-open-url"
}

public enum EventObject: String {
Expand Down
2 changes: 2 additions & 0 deletions Extensions/ShareTo/SendToDevice.swift
Expand Up @@ -36,6 +36,8 @@ class SendToDevice: ClientPickerViewControllerDelegate, InstructionsViewControll
profile.sendItems([item], toClients: clients).uponQueue(.main) { result in
profile.shutdown()
self.finish()

addAppExtensionTelemetryEvent(forMethod: "send-to-device")
}
}

Expand Down
18 changes: 18 additions & 0 deletions Extensions/ShareTo/ShareViewController.swift
Expand Up @@ -38,6 +38,16 @@ protocol ShareControllerDelegate: class {
func hidePopupWhenShowingAlert()
}

// Telemetry events are written to NSUserDefaults, and then the host app reads and clears this list.
func addAppExtensionTelemetryEvent(forMethod method: String) {
let profile = BrowserProfile(localName: "profile")
var events = profile.prefs.arrayForKey(PrefsKeys.AppExtensionTelemetryEventArray) ?? [[String]]()
// Currently, only URL objects are shared.
let event = ["method": method, "object": "url"]
events.append(event)
profile.prefs.setObject(events, forKey: PrefsKeys.AppExtensionTelemetryEventArray)
}

class ShareViewController: UIViewController {
private var shareItem: ShareItem?
private var viewsShownDuringDoneAnimation = [UIView]()
Expand Down Expand Up @@ -276,6 +286,8 @@ extension ShareViewController {
let profile = BrowserProfile(localName: "profile")
_ = profile.bookmarks.shareItem(shareItem).value // Blocks until database has settled
profile.shutdown()

addAppExtensionTelemetryEvent(forMethod: "bookmark-this-page")
}

finish()
Expand All @@ -289,6 +301,8 @@ extension ShareViewController {
let profile = BrowserProfile(localName: "profile")
profile.readingList.createRecordWithURL(shareItem.url, title: shareItem.title ?? "", addedBy: UIDevice.current.name)
profile.shutdown()

addAppExtensionTelemetryEvent(forMethod: "add-to-reading-list")
}

finish()
Expand All @@ -307,6 +321,10 @@ extension ShareViewController {
@objc func actionOpenInFirefoxNow(gesture: UIGestureRecognizer) {
gesture.isEnabled = false

// Telemetry is handled in the app delegate that receives this event.
let profile = BrowserProfile(localName: "profile")
profile.prefs.setBool(true, forKey: PrefsKeys.AppExtensionTelemetryOpenUrl)

func firefoxUrl(_ url: String) -> String {
let encoded = url.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.alphanumerics) ?? ""
return "firefox://open-url?url=\(encoded)"
Expand Down
4 changes: 3 additions & 1 deletion Shared/Prefs.swift
Expand Up @@ -32,7 +32,9 @@ public struct PrefsKeys {
public static let KeyCustomSyncAuth = "customSyncAuthServer"
public static let KeyCustomSyncWeb = "customSyncWebServer"
public static let UseStageServer = "useStageSyncService"


public static let AppExtensionTelemetryOpenUrl = "AppExtensionTelemetryOpenUrl"
public static let AppExtensionTelemetryEventArray = "AppExtensionTelemetryEvents"
}

public struct PrefsDefaults {
Expand Down

0 comments on commit dca2bf3

Please sign in to comment.