Merge lp:~mandel/unity-lens-music/plan-b into lp:unity-lens-music
- plan-b
- Merge into trunk
Proposed by
Manuel de la Peña
Status: | Rejected |
---|---|
Rejected by: | Alejandro J. Cura |
Proposed branch: | lp:~mandel/unity-lens-music/plan-b |
Merge into: | lp:unity-lens-music |
Diff against target: |
396 lines (+132/-66) 2 files modified
src/musicstore-scope.vala (+21/-1) src/ubuntuone-webservices.vala (+111/-65) |
To merge this branch: | bzr merge lp:~mandel/unity-lens-music/plan-b |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity Team | Pending | ||
Review via email: mp+158384@code.launchpad.net |
Commit message
Description of the change
Add code to ensure that a label is shown when u1 creds are not present.
To post a comment you must log in.
Unmerged revisions
- 133. By Manuel de la Peña
-
Check creds.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/musicstore-scope.vala' |
2 | --- src/musicstore-scope.vala 2013-02-28 09:48:46 +0000 |
3 | +++ src/musicstore-scope.vala 2013-04-11 14:16:23 +0000 |
4 | @@ -18,15 +18,19 @@ |
5 | */ |
6 | |
7 | using GLib; |
8 | +using Ubuntuone.Webservice; |
9 | |
10 | namespace Unity.MusicLens { |
11 | |
12 | public class MusicStoreScopeProxy : SimpleScope |
13 | { |
14 | + const string NO_CREDENTIALS_LABEL_TEXT = _("Before you can purchase music you need to log in to the Ubuntu One app"); |
15 | private MusicStoreCollection collection; |
16 | private Unity.Extras.PreviewPlayerController preview_player; |
17 | private Unity.MusicPreview? music_preview; |
18 | private PreferencesManager preferences = PreferencesManager.get_default (); |
19 | + private PurchaseService purchase_service; |
20 | + private bool have_credentials = false; |
21 | |
22 | public MusicStoreScopeProxy () |
23 | { |
24 | @@ -41,6 +45,7 @@ |
25 | base.initialize (); |
26 | |
27 | collection = new MusicStoreCollection (); |
28 | + purchase_service = new PurchaseService (); |
29 | |
30 | preferences.notify["remote-content-search"].connect((obj, pspec) => { scope.queue_search_changed(SearchType.DEFAULT); }); |
31 | |
32 | @@ -111,12 +116,19 @@ |
33 | } |
34 | } |
35 | |
36 | - GLib.Icon? icon = new GLib.FileIcon (File.new_for_path (Config.DATADIR + "/icons/unity-icon-theme/places/svg/service-u1.svg")); |
37 | + if (have_credentials) { |
38 | + GLib.Icon? icon = new GLib.FileIcon (File.new_for_path (Config.DATADIR + "/icons/unity-icon-theme/places/svg/service-u1.svg")); |
39 | var download_action = new Unity.PreviewAction ("download_album", _("Download"), icon); |
40 | if (album.formatted_price != null) |
41 | download_action.extra_text = album.formatted_price; |
42 | download_action.activated.connect (download_album); |
43 | music_preview.add_action (download_action); |
44 | + } else { |
45 | + var data = new HashTable<string, Variant>(str_hash, str_equal); |
46 | + data["no_credentials_label"] = NO_CREDENTIALS_LABEL_TEXT; |
47 | + InfoHint info_hint = new InfoHint.with_variant("music_preview", "", null, data); |
48 | + music_preview.add_info(info_hint); |
49 | + } |
50 | } |
51 | return music_preview; |
52 | } |
53 | @@ -142,6 +154,14 @@ |
54 | } |
55 | |
56 | try { |
57 | + yield purchase_service.fetch_credentials (); |
58 | + have_credentials = true; |
59 | + } catch (PurchaseError e) { |
60 | + // this is not a serious error, just missing credentials |
61 | + have_credentials = false; |
62 | + } |
63 | + |
64 | + try { |
65 | debug ("model has %u rows before search", search.results_model.get_n_rows ()); |
66 | yield collection.search (search, search_type, (owned) filters, max_results, cancellable); |
67 | debug ("model has %u rows after search", search.results_model.get_n_rows ()); |
68 | |
69 | === modified file 'src/ubuntuone-webservices.vala' |
70 | --- src/ubuntuone-webservices.vala 2012-12-06 15:39:38 +0000 |
71 | +++ src/ubuntuone-webservices.vala 2013-04-11 14:16:23 +0000 |
72 | @@ -21,26 +21,29 @@ |
73 | |
74 | [DBus (name = "com.ubuntuone.CredentialsManagement")] |
75 | interface CredentialsManagement : GLib.Object { |
76 | + public signal void authorization_denied (); |
77 | public signal void credentials_found (HashTable <string, string> info); |
78 | + public signal void credentials_not_found (); |
79 | public signal void credentials_error (); |
80 | |
81 | [DBus (name = "find_credentials")] |
82 | public abstract void find_credentials () throws IOError; |
83 | } |
84 | |
85 | -const string WEBAPI_URI = "https://edge.one.ubuntu.com/"; |
86 | -const string ACCOUNT_URI = WEBAPI_URI + "api/account"; |
87 | -const string PAYMENT_METHOD_URI = WEBAPI_URI + "music-store/api/1/user/retrieve-payment-method?purchase_sku=%s"; |
88 | -const string PURCHASE_WITH_DEFAULT_PAYMENT_URI = WEBAPI_URI + "music-store/api/1/user/purchase-with-default-payment?purchase_sku=%s&authentication=%s"; |
89 | -const string AUTHENTICATION_URI = "https://login.staging.ubuntu.com/api/1.1/authentications"; |
90 | +const string WEBAPI_SERVER = "https://one.ubuntu.com/"; |
91 | +const string ACCOUNT_PATH = "api/account"; |
92 | +const string PAYMENT_METHOD_PATH = "music-store-up/api/1/user/retrieve-payment-method?purchase_sku=%s"; |
93 | +const string PURCHASE_WITH_DEFAULT_PAYMENT_PATH = "music-store-up/api/1/user/purchase-with-default-payment?purchase_sku=%s&authentication=%s"; |
94 | +const string AUTHENTICATION_SERVER = "https://login.ubuntu.com/"; |
95 | +const string AUTHENTICATION_PATH = "api/1.1/authentications"; |
96 | const string AUTHENTICATE_PARAMS = "ws.op=authenticate&token_name=Purchase_Token"; |
97 | -const int PASSWORD_CACHE_SECONDS = 300; |
98 | -const int PAYMENT_METHOD_CACHE_SECONDS = 120; |
99 | + |
100 | |
101 | namespace Ubuntuone.Webservice |
102 | { |
103 | public errordomain PurchaseError |
104 | { |
105 | + MISSING_CREDENTIALS_ERROR, |
106 | PURCHASE_ERROR, |
107 | WRONG_PASSWORD_ERROR, |
108 | UNSPECIFIED_ERROR |
109 | @@ -56,17 +59,13 @@ |
110 | public string selected_payment_method { get; internal set; default = null; } |
111 | public string consumer_key { get; private set; default = null; } |
112 | public string token { get; private set; default = null; } |
113 | - internal DateTime _selected_payment_method_expiry; |
114 | - DateTime _password_expiry; |
115 | + public string open_url { get; private set; default = null; } |
116 | internal HashTable <string, string> _ubuntuone_credentials = null; |
117 | |
118 | construct { |
119 | http_session = build_http_session (); |
120 | http_session_sso = build_http_session (); |
121 | |
122 | - reset_payment_method_cache (0); |
123 | - reset_password_cache (0); |
124 | - |
125 | credentials_management = build_credentials_management (); |
126 | } |
127 | |
128 | @@ -77,24 +76,40 @@ |
129 | return session; |
130 | } |
131 | |
132 | - internal DateTime now () |
133 | - { |
134 | - return new DateTime.now_utc (); |
135 | - } |
136 | - |
137 | - internal bool expired_payment_method_cache () |
138 | - { |
139 | - return _selected_payment_method_expiry.compare (now ()) <= 0; |
140 | - } |
141 | - |
142 | - internal void reset_payment_method_cache (int seconds_from_now) |
143 | - { |
144 | - _selected_payment_method_expiry = now ().add_seconds (seconds_from_now); |
145 | - } |
146 | - |
147 | - internal void reset_password_cache (int seconds_from_now) |
148 | - { |
149 | - _password_expiry = now ().add_seconds (seconds_from_now); |
150 | + string webapi_server () |
151 | + { |
152 | + string staging_webapi = Environment.get_variable ("U1_STAGING_WEBAPI"); |
153 | + return staging_webapi != null ? staging_webapi : WEBAPI_SERVER; |
154 | + } |
155 | + |
156 | + string account_uri () |
157 | + { |
158 | + return webapi_server() + ACCOUNT_PATH; |
159 | + } |
160 | + |
161 | + string payment_method_uri () |
162 | + { |
163 | + return webapi_server() + PAYMENT_METHOD_PATH; |
164 | + } |
165 | + |
166 | + string purchase_with_default_payment_uri () |
167 | + { |
168 | + return webapi_server() + PURCHASE_WITH_DEFAULT_PAYMENT_PATH; |
169 | + } |
170 | + |
171 | + string authentication_server () |
172 | + { |
173 | + string staging_authentication = Environment.get_variable ("U1_STAGING_AUTHENTICATION"); |
174 | + return staging_authentication != null ? staging_authentication : AUTHENTICATION_SERVER; |
175 | + } |
176 | + |
177 | + string authentication_uri () |
178 | + { |
179 | + return authentication_server() + AUTHENTICATION_PATH; |
180 | + } |
181 | + |
182 | + public bool got_credentials () { |
183 | + return _ubuntuone_credentials != null; |
184 | } |
185 | |
186 | internal virtual CredentialsManagement build_credentials_management () |
187 | @@ -125,28 +140,38 @@ |
188 | email = root_object.get_string_member("email"); |
189 | } |
190 | |
191 | - internal void parse_payment_method_json (string json_string) throws GLib.Error |
192 | + internal void parse_payment_method_json (string json_string) throws GLib.Error, PurchaseError |
193 | { |
194 | + stdout.printf("Response is \n%s\n", json_string); |
195 | var root_object = parse_json (json_string); |
196 | - Json.Object payload = root_object.get_object_member("payload"); |
197 | - selected_payment_method = payload.get_string_member("selected_payment_method"); |
198 | + if (root_object.has_member ("selected_payment_method")) { |
199 | + selected_payment_method = root_object.get_string_member("selected_payment_method"); |
200 | + } else { |
201 | + open_url = root_object.get_string_member ("open_url"); |
202 | + var error_message = root_object.get_string_member ("error_message"); |
203 | + throw new PurchaseError.PURCHASE_ERROR (error_message); |
204 | + } |
205 | } |
206 | |
207 | internal void parse_authentication_json (string json_string) throws GLib.Error |
208 | { |
209 | + stdout.printf ("Creds are %s\n", json_string); |
210 | var root_object = parse_json (json_string); |
211 | - consumer_key = root_object.get_string_member("consumer_key"); |
212 | - token = root_object.get_string_member("token"); |
213 | + consumer_key = root_object.get_string_member ("consumer_key"); |
214 | + token = root_object.get_string_member ("token"); |
215 | } |
216 | |
217 | internal string parse_purchase_json (string json_string) throws GLib.Error |
218 | { |
219 | var root_object = parse_json (json_string); |
220 | - Json.Object payload = root_object.get_object_member("payload"); |
221 | - return payload.get_string_member("open_url"); |
222 | + if (root_object.has_member ("open_url")) { |
223 | + return root_object.get_string_member("open_url"); |
224 | + } else { |
225 | + return ""; |
226 | + } |
227 | } |
228 | |
229 | - internal virtual async void fetch_credentials () throws PurchaseError |
230 | + public virtual async void fetch_credentials () throws PurchaseError |
231 | { |
232 | PurchaseError error = null; |
233 | |
234 | @@ -155,8 +180,12 @@ |
235 | debug ("got credentials"); |
236 | fetch_credentials.callback (); |
237 | }); |
238 | + ulong not_found_handler = credentials_management.credentials_not_found.connect ((credentials) => { |
239 | + error = new PurchaseError.MISSING_CREDENTIALS_ERROR ("Can't get Ubuntu One tokens."); |
240 | + fetch_credentials.callback (); |
241 | + }); |
242 | ulong error_handler = credentials_management.credentials_error.connect (() => { |
243 | - error = new PurchaseError.PURCHASE_ERROR ("Can't get Ubuntu One tokens."); |
244 | + error = new PurchaseError.MISSING_CREDENTIALS_ERROR ("Can't get Ubuntu One tokens."); |
245 | fetch_credentials.callback (); |
246 | }); |
247 | |
248 | @@ -164,10 +193,11 @@ |
249 | credentials_management.find_credentials (); |
250 | yield; |
251 | } catch (IOError e) { |
252 | - error = new PurchaseError.PURCHASE_ERROR ("Can't get Ubuntu One tokens: %s", e.message); |
253 | + error = new PurchaseError.MISSING_CREDENTIALS_ERROR ("Can't get Ubuntu One tokens: %s", e.message); |
254 | } |
255 | |
256 | credentials_management.disconnect (found_handler); |
257 | + credentials_management.disconnect (not_found_handler); |
258 | credentials_management.disconnect (error_handler); |
259 | |
260 | if (error != null) { |
261 | @@ -208,7 +238,7 @@ |
262 | internal virtual async void fetch_account () throws PurchaseError |
263 | { |
264 | string response; |
265 | - PurchaseError error = yield call_api ("GET", ACCOUNT_URI, out response); |
266 | + PurchaseError error = yield call_api ("GET", account_uri(), out response); |
267 | |
268 | if (error != null) { |
269 | debug ("Error while fetching U1 account: %s.", error.message); |
270 | @@ -224,43 +254,40 @@ |
271 | } |
272 | } |
273 | |
274 | - internal virtual async void fetch_payment_method (string purchase_sku) throws PurchaseError |
275 | + internal virtual void fetch_payment_method (string purchase_sku) throws PurchaseError |
276 | { |
277 | - string response; |
278 | - var uri = PAYMENT_METHOD_URI.printf (purchase_sku); |
279 | - PurchaseError error = yield call_api ("GET", uri, out response); |
280 | + var uri = payment_method_uri().printf (purchase_sku); |
281 | |
282 | - if (error != null) { |
283 | - debug ("Error while fetching payment method: %s.", error.message); |
284 | - throw error; |
285 | + var message = send_signed_webservice_call ("GET", uri); |
286 | + if (message.status_code != Soup.KnownStatusCode.OK) { |
287 | + debug ("Purchase request failed: HTTP %u", message.status_code); |
288 | + debug ("Reason: %s", message.reason_phrase); |
289 | + try { |
290 | + message.response_body.flatten (); |
291 | + debug ("body: ------\n%s\n------\n", (string) message.response_body.data); |
292 | + } catch (Error e) { |
293 | + } |
294 | + throw new PurchaseError.PURCHASE_ERROR ("Retrieve payment method failed: %s".printf (message.reason_phrase)); |
295 | } |
296 | - |
297 | try { |
298 | - parse_payment_method_json (response); |
299 | - debug ("got payment method"); |
300 | + message.response_body.flatten (); |
301 | + var result = (string) message.response_body.data; |
302 | + parse_payment_method_json (result); |
303 | } catch (GLib.Error e) { |
304 | debug ("Error while getting payment method: %s.", e.message); |
305 | throw new PurchaseError.PURCHASE_ERROR (e.message); |
306 | } |
307 | } |
308 | |
309 | - internal virtual async void refetch_payment_info (string purchase_sku) throws PurchaseError |
310 | + public virtual async void fetch_account_info () throws PurchaseError |
311 | { |
312 | yield fetch_credentials (); |
313 | yield fetch_account (); |
314 | - yield fetch_payment_method (purchase_sku); |
315 | - reset_payment_method_cache (PAYMENT_METHOD_CACHE_SECONDS); |
316 | } |
317 | |
318 | - public async void fetch_payment_info (string purchase_sku) throws PurchaseError |
319 | + public void fetch_payment_info (string purchase_sku) throws PurchaseError |
320 | { |
321 | - if (expired_payment_method_cache ()) |
322 | - { |
323 | - debug ("refetching"); |
324 | - yield refetch_payment_info (purchase_sku); |
325 | - } else { |
326 | - debug ("in cache"); |
327 | - } |
328 | + fetch_payment_method (purchase_sku); |
329 | } |
330 | |
331 | internal virtual void _do_sso_webcall (Soup.Message message, string password) |
332 | @@ -286,6 +313,11 @@ |
333 | if (message.status_code == Soup.KnownStatusCode.UNAUTHORIZED) { |
334 | throw new PurchaseError.WRONG_PASSWORD_ERROR ("Wrong password"); |
335 | } |
336 | + try { |
337 | + message.response_body.flatten (); |
338 | + debug ("body: ------\n%s\n------\n", (string) message.response_body.data); |
339 | + } catch (Error e) { |
340 | + } |
341 | throw new PurchaseError.PURCHASE_ERROR (message.reason_phrase); |
342 | } |
343 | message.response_body.flatten (); |
344 | @@ -294,12 +326,14 @@ |
345 | |
346 | internal virtual string get_purchase_token (string password) throws PurchaseError |
347 | { |
348 | - var result = authenticated_sso_webcall ("POST", AUTHENTICATION_URI, AUTHENTICATE_PARAMS, password); |
349 | + var result = authenticated_sso_webcall ("POST", authentication_uri(), AUTHENTICATE_PARAMS, password); |
350 | try { |
351 | parse_authentication_json (result); |
352 | } catch (GLib.Error e) { |
353 | throw new PurchaseError.PURCHASE_ERROR (e.message); |
354 | } |
355 | + |
356 | + stdout.printf ("%s:%s\n", consumer_key, token); |
357 | return "%s:%s".printf (consumer_key, token); |
358 | } |
359 | |
360 | @@ -311,14 +345,24 @@ |
361 | return message; |
362 | } |
363 | |
364 | - internal virtual void purchase_with_default_payment (string sku, string purchase_token) throws PurchaseError |
365 | + internal virtual void purchase_with_default_payment (string album_id, string purchase_token) throws PurchaseError |
366 | { |
367 | - var uri = PURCHASE_WITH_DEFAULT_PAYMENT_URI.printf (sku, purchase_token); |
368 | + var uri = purchase_with_default_payment_uri().printf (album_id, purchase_token); |
369 | + stdout.printf("Uri is %s\n", uri); |
370 | + |
371 | var message = send_signed_webservice_call ("GET", uri); |
372 | |
373 | if (message.status_code != Soup.KnownStatusCode.OK) { |
374 | + stdout.printf("Purchase request failed: HTTP %u", message.status_code); |
375 | + stdout.printf("Reason: %s", message.reason_phrase); |
376 | debug ("Purchase request failed: HTTP %u", message.status_code); |
377 | debug ("Reason: %s", message.reason_phrase); |
378 | + try { |
379 | + message.response_body.flatten (); |
380 | + stdout.printf("body: ------\n%s\n------\n", (string) message.response_body.data); |
381 | + debug ("body: ------\n%s\n------\n", (string) message.response_body.data); |
382 | + } catch (Error e) { |
383 | + } |
384 | throw new PurchaseError.PURCHASE_ERROR ("Purchase failed: %s".printf (message.reason_phrase)); |
385 | } |
386 | try { |
387 | @@ -336,7 +380,9 @@ |
388 | public void purchase (string album_id, string password) throws PurchaseError |
389 | { |
390 | var purchase_token = get_purchase_token (password); |
391 | + debug ("purchasing..."); |
392 | purchase_with_default_payment (album_id, purchase_token); |
393 | + debug ("purchase completed."); |
394 | } |
395 | } |
396 | } |