{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/firefox-ios/pulls/comments/75332059","id":75332059,"diff_hunk":"@@ -0,0 +1,125 @@\n+/* This Source Code Form is subject to the terms of the Mozilla Public\n+ * License, v. 2.0. If a copy of the MPL was not distributed with this\n+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n+\n+import Foundation\n+import Deferred\n+import Shared\n+\n+private let log = Logger.syncLogger\n+\n+// The current version of the device registration, we use this to re-register\n+// devices after we update what we send on device registration.\n+private let DeviceRegistrationVersion = 1\n+\n+public enum FxADeviceRegistrationResult {\n+    case RegisteredOrUpdated\n+    case AlreadyRegistered\n+}\n+\n+public class FxADeviceRegistrator {\n+    public enum DeviceRegistratorError: MaybeErrorType {\n+        case DeviceRegistrationFailed\n+\n+        public var description: String {\n+            switch self {\n+            case DeviceRegistrationFailed: return \"Device registration failed.\"\n+            }\n+        }\n+    }\n+\n+    public static func registerOrUpdateDevice(account: FirefoxAccount, state: MarriedState) -> Deferred<Maybe<FxADeviceRegistrationResult>> {\n+        if let _ = account.fxaDeviceId where account.deviceRegistrationVersion == DeviceRegistrationVersion {\n+            return Deferred(value: Maybe(success: FxADeviceRegistrationResult.AlreadyRegistered))\n+        }\n+\n+        let client = FxAClient10(endpoint: account.configuration.authEndpointURL)\n+        let sessionToken = state.sessionToken\n+        let name = DeviceInfo.defaultClientName()\n+        let device: FxADevice\n+        if let deviceId = account.fxaDeviceId {\n+            device = FxADevice.forUpdate(name, id: deviceId)\n+        } else {\n+            device = FxADevice.forRegister(name, type: \"mobile\")\n+        }\n+\n+        return client.registerOrUpdateDevice(sessionToken, device: device).bind { result in\n+            let deferred = Deferred<Maybe<FxADeviceRegistrationResult>>()\n+\n+            if let device = result.successValue,\n+                let deviceId = device.id {\n+                account.fxaDeviceId = deviceId\n+                account.deviceRegistrationVersion = DeviceRegistrationVersion\n+                deferred.fill(Maybe(success: FxADeviceRegistrationResult.RegisteredOrUpdated))\n+                return deferred\n+            }\n+\n+            let error = result.failureValue as? FxAClientError\n+            switch (error) {\n+            case let .Remote(remoteError)?:\n+                switch (remoteError.code) {\n+                case FxAccountRemoteError.DEVICE_SESSION_CONFLICT:\n+                    recoverFromDeviceSessionConflict(account, client: client, deferred: deferred, sessionToken: sessionToken)\n+                case FxAccountRemoteError.UNKNOWN_DEVICE:\n+                    // TODO: Shouldn't this also clear registration version? Android doesn't.\n+                    handleUnknownDevice(account)\n+                case FxAccountRemoteError.INVALID_AUTHENTICATION_TOKEN:\n+                    logErrorAndResetDeviceRegistrationVersion(account, description: String(remoteError))\n+                    handleTokenError(account, client: client)\n+                default:\n+                    logErrorAndResetDeviceRegistrationVersion(account, description: String(remoteError))\n+                }\n+            case let .Local(localError)?:\n+                self.logErrorAndResetDeviceRegistrationVersion(account, description: localError.description)\n+            default:\n+                // This shouldn't happen.\n+                self.logErrorAndResetDeviceRegistrationVersion(account, description: \"invalid error type\")\n+                assertionFailure()\n+            }\n+\n+            deferred.fillIfUnfilled(Maybe(failure: DeviceRegistratorError.DeviceRegistrationFailed))\n+\n+            return deferred\n+        }\n+    }\n+\n+    private static func handleUnknownDevice(account: FirefoxAccount) {\n+        log.info(\"unknown device id, clearing the cached device id\")\n+        account.fxaDeviceId = nil\n+    }\n+\n+    private static func recoverFromDeviceSessionConflict(account: FirefoxAccount, client: FxAClient10, deferred: Deferred<Maybe<FxADeviceRegistrationResult>>, sessionToken: NSData) {\n+        log.warning(\"device session conflict, attempting to ascertain the correct device id\")\n+        client.devices(sessionToken).upon { response in\n+            if let success = response.successValue,\n+                let currentDevice = success.devices.find({ $0.isCurrentDevice }) {\n+                account.fxaDeviceId = currentDevice.id\n+                deferred.fill(Maybe(success: FxADeviceRegistrationResult.RegisteredOrUpdated))\n+            } else {\n+                self.logErrorAndResetDeviceRegistrationVersion(account, description: \"conflict recovery failed: \\(response.failureValue?.description ?? \"\")\")\n+                deferred.fill(Maybe(failure: DeviceRegistratorError.DeviceRegistrationFailed))\n+            }\n+        }\n+    }\n+\n+    private static func handleTokenError(account: FirefoxAccount, client: FxAClient10) {","path":"Account/FxADeviceRegistrator.swift","position":105,"original_position":105,"commit_id":"deaad80c635893c9195f2fe70920efc1490c8e60","original_commit_id":"deaad80c635893c9195f2fe70920efc1490c8e60","user":{"login":"sleroux","id":434322,"avatar_url":"https://avatars.githubusercontent.com/u/434322?v=3","gravatar_id":"","url":"https://api.github.com/users/sleroux","html_url":"https://github.com/sleroux","followers_url":"https://api.github.com/users/sleroux/followers","following_url":"https://api.github.com/users/sleroux/following{/other_user}","gists_url":"https://api.github.com/users/sleroux/gists{/gist_id}","starred_url":"https://api.github.com/users/sleroux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sleroux/subscriptions","organizations_url":"https://api.github.com/users/sleroux/orgs","repos_url":"https://api.github.com/users/sleroux/repos","events_url":"https://api.github.com/users/sleroux/events{/privacy}","received_events_url":"https://api.github.com/users/sleroux/received_events","type":"User","site_admin":false},"body":"Same comment as above re: async-ness","created_at":"2016-08-18T15:36:21Z","updated_at":"2016-08-18T15:36:21Z","html_url":"https://github.com/mozilla/firefox-ios/pull/2056#discussion_r75332059","pull_request_url":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056","_links":{"self":{"href":"https://api.github.com/repos/mozilla/firefox-ios/pulls/comments/75332059"},"html":{"href":"https://github.com/mozilla/firefox-ios/pull/2056#discussion_r75332059"},"pull_request":{"href":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056","id":81737464,"html_url":"https://github.com/mozilla/firefox-ios/pull/2056","diff_url":"https://github.com/mozilla/firefox-ios/pull/2056.diff","patch_url":"https://github.com/mozilla/firefox-ios/pull/2056.patch","issue_url":"https://api.github.com/repos/mozilla/firefox-ios/issues/2056","number":2056,"state":"open","locked":false,"title":"Bug 1250783 - FxA device registration","user":{"login":"thebnich","id":1093266,"avatar_url":"https://avatars.githubusercontent.com/u/1093266?v=3","gravatar_id":"","url":"https://api.github.com/users/thebnich","html_url":"https://github.com/thebnich","followers_url":"https://api.github.com/users/thebnich/followers","following_url":"https://api.github.com/users/thebnich/following{/other_user}","gists_url":"https://api.github.com/users/thebnich/gists{/gist_id}","starred_url":"https://api.github.com/users/thebnich/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thebnich/subscriptions","organizations_url":"https://api.github.com/users/thebnich/orgs","repos_url":"https://api.github.com/users/thebnich/repos","events_url":"https://api.github.com/users/thebnich/events{/privacy}","received_events_url":"https://api.github.com/users/thebnich/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-08-17T23:59:37Z","updated_at":"2016-08-18T15:36:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056/commits","review_comments_url":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056/comments","review_comment_url":"https://api.github.com/repos/mozilla/firefox-ios/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/firefox-ios/issues/2056/comments","statuses_url":"https://api.github.com/repos/mozilla/firefox-ios/statuses/deaad80c635893c9195f2fe70920efc1490c8e60","head":{"label":"mozilla:pr/2025","ref":"pr/2025","sha":"deaad80c635893c9195f2fe70920efc1490c8e60","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":26133979,"name":"firefox-ios","full_name":"mozilla/firefox-ios","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/firefox-ios","description":"Firefox for iOS","fork":false,"url":"https://api.github.com/repos/mozilla/firefox-ios","forks_url":"https://api.github.com/repos/mozilla/firefox-ios/forks","keys_url":"https://api.github.com/repos/mozilla/firefox-ios/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/firefox-ios/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/firefox-ios/teams","hooks_url":"https://api.github.com/repos/mozilla/firefox-ios/hooks","issue_events_url":"https://api.github.com/repos/mozilla/firefox-ios/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/firefox-ios/events","assignees_url":"https://api.github.com/repos/mozilla/firefox-ios/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/firefox-ios/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/firefox-ios/tags","blobs_url":"https://api.github.com/repos/mozilla/firefox-ios/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/firefox-ios/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/firefox-ios/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/firefox-ios/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/firefox-ios/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/firefox-ios/languages","stargazers_url":"https://api.github.com/repos/mozilla/firefox-ios/stargazers","contributors_url":"https://api.github.com/repos/mozilla/firefox-ios/contributors","subscribers_url":"https://api.github.com/repos/mozilla/firefox-ios/subscribers","subscription_url":"https://api.github.com/repos/mozilla/firefox-ios/subscription","commits_url":"https://api.github.com/repos/mozilla/firefox-ios/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/firefox-ios/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/firefox-ios/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/firefox-ios/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/firefox-ios/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/firefox-ios/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/firefox-ios/merges","archive_url":"https://api.github.com/repos/mozilla/firefox-ios/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/firefox-ios/downloads","issues_url":"https://api.github.com/repos/mozilla/firefox-ios/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/firefox-ios/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/firefox-ios/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/firefox-ios/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/firefox-ios/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/firefox-ios/releases{/id}","deployments_url":"https://api.github.com/repos/mozilla/firefox-ios/deployments","created_at":"2014-11-03T19:07:02Z","updated_at":"2016-08-18T14:52:12Z","pushed_at":"2016-08-18T06:37:17Z","git_url":"git://github.com/mozilla/firefox-ios.git","ssh_url":"git@github.com:mozilla/firefox-ios.git","clone_url":"https://github.com/mozilla/firefox-ios.git","svn_url":"https://github.com/mozilla/firefox-ios","homepage":"","size":282791,"stargazers_count":5925,"watchers_count":5925,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1192,"mirror_url":null,"open_issues_count":50,"forks":1192,"open_issues":50,"watchers":5925,"default_branch":"master"}},"base":{"label":"mozilla:master","ref":"master","sha":"7e95b152aa21e60da4357133eec22cdb5c1dc1ba","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":26133979,"name":"firefox-ios","full_name":"mozilla/firefox-ios","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/firefox-ios","description":"Firefox for iOS","fork":false,"url":"https://api.github.com/repos/mozilla/firefox-ios","forks_url":"https://api.github.com/repos/mozilla/firefox-ios/forks","keys_url":"https://api.github.com/repos/mozilla/firefox-ios/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/firefox-ios/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/firefox-ios/teams","hooks_url":"https://api.github.com/repos/mozilla/firefox-ios/hooks","issue_events_url":"https://api.github.com/repos/mozilla/firefox-ios/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/firefox-ios/events","assignees_url":"https://api.github.com/repos/mozilla/firefox-ios/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/firefox-ios/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/firefox-ios/tags","blobs_url":"https://api.github.com/repos/mozilla/firefox-ios/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/firefox-ios/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/firefox-ios/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/firefox-ios/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/firefox-ios/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/firefox-ios/languages","stargazers_url":"https://api.github.com/repos/mozilla/firefox-ios/stargazers","contributors_url":"https://api.github.com/repos/mozilla/firefox-ios/contributors","subscribers_url":"https://api.github.com/repos/mozilla/firefox-ios/subscribers","subscription_url":"https://api.github.com/repos/mozilla/firefox-ios/subscription","commits_url":"https://api.github.com/repos/mozilla/firefox-ios/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/firefox-ios/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/firefox-ios/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/firefox-ios/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/firefox-ios/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/firefox-ios/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/firefox-ios/merges","archive_url":"https://api.github.com/repos/mozilla/firefox-ios/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/firefox-ios/downloads","issues_url":"https://api.github.com/repos/mozilla/firefox-ios/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/firefox-ios/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/firefox-ios/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/firefox-ios/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/firefox-ios/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/firefox-ios/releases{/id}","deployments_url":"https://api.github.com/repos/mozilla/firefox-ios/deployments","created_at":"2014-11-03T19:07:02Z","updated_at":"2016-08-18T14:52:12Z","pushed_at":"2016-08-18T06:37:17Z","git_url":"git://github.com/mozilla/firefox-ios.git","ssh_url":"git@github.com:mozilla/firefox-ios.git","clone_url":"https://github.com/mozilla/firefox-ios.git","svn_url":"https://github.com/mozilla/firefox-ios","homepage":"","size":282791,"stargazers_count":5925,"watchers_count":5925,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1192,"mirror_url":null,"open_issues_count":50,"forks":1192,"open_issues":50,"watchers":5925,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056"},"html":{"href":"https://github.com/mozilla/firefox-ios/pull/2056"},"issue":{"href":"https://api.github.com/repos/mozilla/firefox-ios/issues/2056"},"comments":{"href":"https://api.github.com/repos/mozilla/firefox-ios/issues/2056/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/firefox-ios/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/firefox-ios/pulls/2056/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/firefox-ios/statuses/deaad80c635893c9195f2fe70920efc1490c8e60"}}}}
{"actor":{"display_login":"sleroux"}}