Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug1104123 hook up the share to extension to the client provider #28

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
D34F86DB1A1AC35B00331EC4 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34F86DA1A1AC35B00331EC4 /* LoginView.swift */; };
D34F86E71A1AC7DD00331EC4 /* PasswordTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34F86E61A1AC7DD00331EC4 /* PasswordTextField.swift */; };
D34F86E91A1ACD1200331EC4 /* ImageTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34F86E81A1ACD1200331EC4 /* ImageTextField.swift */; };
E418D0D91A251B3200CAE47A /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34DC84D1A16C40C00D49B7B /* Account.swift */; };
E418D0DA1A251B3200CAE47A /* AccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34DC84E1A16C40C00D49B7B /* AccountManager.swift */; };
E418D0DB1A251B3200CAE47A /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34DC84F1A16C40C00D49B7B /* Bookmarks.swift */; };
E418D0DC1A251B3200CAE47A /* Clients.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42CCDE21A23A6F900B794D3 /* Clients.swift */; };
E418D0DD1A251B3200CAE47A /* Cursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34DC8501A16C40C00D49B7B /* Cursor.swift */; };
E418D0DE1A251B3200CAE47A /* Favicons.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34DC8511A16C40C00D49B7B /* Favicons.swift */; };
E418D0DF1A251B3200CAE47A /* RestAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34DC8521A16C40C00D49B7B /* RestAPI.swift */; };
E418D0E01A25634D00CAE47A /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F84B22301A0913F200AAB793 /* Alamofire.framework */; };
E41A7D431A1BDFD800245963 /* FiraSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E41A7D421A1BDFD800245963 /* FiraSans-Regular.ttf */; };
E41A7D441A1BDFD800245963 /* FiraSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E41A7D421A1BDFD800245963 /* FiraSans-Regular.ttf */; };
E41A7D481A1BE00100245963 /* FiraMono-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E41A7D471A1BE00100245963 /* FiraMono-Medium.ttf */; };
Expand Down Expand Up @@ -312,6 +320,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E418D0E01A25634D00CAE47A /* Alamofire.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -964,9 +973,16 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E418D0DA1A251B3200CAE47A /* AccountManager.swift in Sources */,
E418D0DC1A251B3200CAE47A /* Clients.swift in Sources */,
E42CCE031A24C4E300B794D3 /* ExtensionUtils.swift in Sources */,
E418D0D91A251B3200CAE47A /* Account.swift in Sources */,
E418D0DE1A251B3200CAE47A /* Favicons.swift in Sources */,
F8708D321A0970B70051AB07 /* ShareViewController.swift in Sources */,
E418D0DF1A251B3200CAE47A /* RestAPI.swift in Sources */,
E418D0DD1A251B3200CAE47A /* Cursor.swift in Sources */,
E41A7D4B1A1BE04500245963 /* InitialViewController.swift in Sources */,
E418D0DB1A251B3200CAE47A /* Bookmarks.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
10 changes: 5 additions & 5 deletions Extensions/SendTo/ActionViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,20 +150,20 @@ class ActionViewController: UINavigationController, ClientPickerViewControllerDe
})
}

func cancel() {
func finish() {
self.extensionContext!.completeRequestReturningItems(nil, completionHandler: nil)
}

func clientPickerViewController(clientPickerViewController: ClientPickerViewController, didPickClients clients: [Client]) {
Clients.sendItem(self.sharedItem!, toClients: clients)
cancel()
account?.clients.sendItem(self.sharedItem!, toClients: clients)
finish()
}

func clientPickerViewControllerDidCancel(clientPickerViewController: ClientPickerViewController) {
cancel()
finish()
}

func loginViewControllerDidCancel(loginViewController: LoginViewController) {
cancel()
finish()
}
}
8 changes: 6 additions & 2 deletions Extensions/ShareTo/InitialViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ let LastUsedShareDestinationsKey = "LastUsedShareDestinations"
class InitialViewController: UIViewController, ShareControllerDelegate
{
var shareDialogController: ShareDialogController!
var account: Account?

override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(white: 0.75, alpha: 0.65) // TODO: Is the correct color documented somewhere?

println(self.extensionContext!.inputItems)
let accountManager = AccountManager(loginCallback: { _ in () }, logoutCallback: { _ in () })
self.account = accountManager.getAccount()
}

override func viewDidAppear(animated: Bool)
Expand Down Expand Up @@ -126,6 +128,8 @@ class InitialViewController: UIViewController, ShareControllerDelegate
}

func shareToBookmarks(item: ExtensionUtils.ShareItem) {
// TODO: Discuss how to share to bookmarks
if account != nil { // TODO: We need to properly deal with this.
account?.bookmarks.shareItem(item)
}
}
}
7 changes: 7 additions & 0 deletions Providers/Account.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ class Account {
self.credential = credential
self.logoutCallback = logoutCallback
}

func basicAuthorizationHeader() -> String {
let userPasswordString = "\(credential.user!):\(credential.password!)"
let userPasswordData = userPasswordString.dataUsingEncoding(NSUTF8StringEncoding)
let base64EncodedCredential = userPasswordData!.base64EncodedStringWithOptions(nil)
return "Basic \(base64EncodedCredential)"
}

func makeAuthRequest(request: String, success: (data: AnyObject?) -> (), error: (error: RequestError) -> ()) {
RestAPI.sendRequest(
Expand Down
38 changes: 37 additions & 1 deletion Providers/Bookmarks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,40 @@ class Bookmarks: NSObject {

return resp;
}
};

/// Send a ShareItem to this user's bookmarks
///
/// :param: item the item to be sent
///
/// Note that this code currently uses NSURLSession directly because AlamoFire
/// does not work from an Extension. (Bug 1104884)
///
/// Note that the bookmark will end up in the Unsorted Bookmarks. We have Bug
/// 1094233 open for the REST API to store the incoming item in the Mobile
/// Bookmarks instead.

func shareItem(item: ExtensionUtils.ShareItem) {
let request = NSMutableURLRequest(URL: NSURL(string: "https://moz-syncapi.sateh.com/1.0/bookmarks")!)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPMethod = "POST"

var object = NSMutableDictionary()
object["url"] = item.url
object["title"] = item.title == nil ? "" : item.title

var jsonError: NSError?
let data = NSJSONSerialization.dataWithJSONObject(object, options: nil, error: &jsonError)
if data != nil {
request.HTTPBody = data
}

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("Bookmarks/shareItem")
configuration.HTTPAdditionalHeaders = ["Authorization" : account.basicAuthorizationHeader()]
configuration.sharedContainerIdentifier = ExtensionUtils.sharedContainerIdentifier()

let session = NSURLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
let task = session.dataTaskWithRequest(request)
task.resume()
}
}
40 changes: 37 additions & 3 deletions Providers/Clients.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,43 @@ class Clients: NSObject {
return resp;
}

class func sendItem(item: ExtensionUtils.ShareItem, toClients clients: [Client]) {
for client in clients {
println("TODO Sending \(item.url) to \(client.name)")
/// Send a ShareItem to the specified clients.
///
/// :param: item the item to be sent
/// :param: clients the clients that need to display the item
///
/// The UX for the sharing dialog is incomplete. At this point sharing only
/// works with a single destination client. That is why this code makes no
/// effort to send to multiple clients. Multiple clients will also need
/// a change in the REST API, since extensions can make only one final HTTP
/// call when they finish.
///
/// Note that this code currently uses NSURLSession directly because AlamoFire
/// does not work from an Extension. (Bug 1104884)
func sendItem(item: ExtensionUtils.ShareItem, toClients clients: [Client]) {
if clients.count > 0 {
let request = NSMutableURLRequest(URL: NSURL(string: "https://moz-syncapi.sateh.com/1.0/clients/\(clients[0].id)/tab")!)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPMethod = "POST"

var object = NSMutableDictionary()
object["url"] = item.url
object["title"] = item.title == nil ? "" : item.title

var jsonError: NSError?
let data = NSJSONSerialization.dataWithJSONObject(object, options: nil, error: &jsonError)
if data != nil {
request.HTTPBody = data
}

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("Clients/sendItem")
configuration.HTTPAdditionalHeaders = ["Authorization" : account.basicAuthorizationHeader()]
configuration.sharedContainerIdentifier = ExtensionUtils.sharedContainerIdentifier()

let session = NSURLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
let task = session.dataTaskWithRequest(request)
task.resume()
}
}
}
11 changes: 11 additions & 0 deletions Utils/ExtensionUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,15 @@ struct ExtensionUtils {
}
completionHandler(nil, nil)
}

/// Return the shared identifier to be used with for example background http requests.
/// This is in ExtensionUtils because I think we can eventually do something smart here
/// to let the extension discover this value at runtime. (It is based on the app
// identifier, which will change for production and test builds)
///
/// :returns: the shared container identifier

static func sharedContainerIdentifier() -> String {
return "group.org.allizom.Client"
}
}