Merge lp:~mhr3/unity-lens-shopping/secure-connection into lp:unity-lens-shopping

Proposed by Michal Hruby on 2012-09-26
Status: Merged
Approved by: Paweł Stołowski on 2012-09-26
Approved revision: 23
Merged at revision: 22
Proposed branch: lp:~mhr3/unity-lens-shopping/secure-connection
Merge into: lp:unity-lens-shopping
Diff against target: 309 lines (+141/-68)
5 files modified
configure.ac (+2/-0)
src/Makefile.am (+3/-0)
src/scope.vala (+123/-68)
vapi/Makefile.am (+5/-0)
vapi/libsoup-gnome-2.4.vapi (+8/-0)
To merge this branch: bzr merge lp:~mhr3/unity-lens-shopping/secure-connection
Reviewer Review Type Date Requested Status
Paweł Stołowski 2012-09-26 Approve on 2012-09-26
Review via email: mp+126396@code.launchpad.net

Commit message

Use secure connection to the server

Description of the change

Use secure connection to the server.

To post a comment you must log in.
22. By Michal Hruby on 2012-09-26

Use strict certificate checking

23. By Michal Hruby on 2012-09-26

Merge trunk, add more error reporting

Paweł Stołowski (stolowski) wrote :

Cool, we have SSL now! Looks good and works fine!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2012-07-25 15:18:43 +0000
3+++ configure.ac 2012-09-26 11:13:24 +0000
4@@ -62,6 +62,7 @@
5 gio-unix-2.0 >= $GLIB_REQUIRED
6 dee-1.0 >= 1.0.7
7 gee-1.0
8+ libsoup-gnome-2.4
9 json-glib-1.0
10 unity >= 5.93.0)
11
12@@ -118,6 +119,7 @@
13 data/Makefile
14 src/Makefile
15 src/config.vala
16+ vapi/Makefile
17 po/Makefile.in
18 ])
19 AC_OUTPUT
20
21=== modified file 'src/Makefile.am'
22--- src/Makefile.am 2012-09-24 16:17:01 +0000
23+++ src/Makefile.am 2012-09-26 11:13:24 +0000
24@@ -28,7 +28,10 @@
25 --pkg gio-unix-2.0 \
26 --pkg glib-2.0 \
27 --pkg json-glib-1.0 \
28+ --pkg libsoup-2.4 \
29 --vapidir $(srcdir) \
30+ --vapidir $(top_srcdir)/vapi \
31+ --pkg libsoup-gnome-2.4 \
32 --target-glib=2.26 \
33 $(MAINTAINER_VALAFLAGS) \
34 $(NULL)
35
36=== modified file 'src/scope.vala'
37--- src/scope.vala 2012-09-25 10:05:54 +0000
38+++ src/scope.vala 2012-09-26 11:13:24 +0000
39@@ -23,10 +23,11 @@
40 {
41 public class ShoppingScope : Unity.Scope
42 {
43- private const string OFFERS_BASE_URI = "http://productsearch.ubuntu.com";
44+ private const string OFFERS_BASE_URI = "https://productsearch.ubuntu.com";
45
46 private HashTable<string, string> results_details_map;
47 private HashTable<string, string> global_results_details_map;
48+ private Soup.Session session;
49 private PreviewPlayerHandler player;
50
51 public ShoppingScope ()
52@@ -36,6 +37,12 @@
53
54 protected override void constructed ()
55 {
56+ session = new Soup.SessionAsync ();
57+ session.ssl_use_system_ca_file = true;
58+ session.ssl_strict = true;
59+ session.user_agent = "Unity Shopping Lens " + Config.VERSION;
60+ session.add_feature_by_type (typeof (SoupGNOME.ProxyResolverGNOME));
61+
62 /* Listen for filter changes */
63 filters_changed.connect (() => {
64 queue_search_changed (SearchType.DEFAULT);
65@@ -94,6 +101,7 @@
66 process_search_reply_json (parser, Category.TREAT_YOURSELF,
67 search.results_model);
68 }
69+ catch (IOError.CANCELLED canc_err) { /* ignore */ }
70 catch (Error err)
71 {
72 warning ("Error: %s", err.message);
73@@ -122,6 +130,62 @@
74 }
75 }
76
77+ private async Preview? process_preview_request (string details_uri)
78+ {
79+ Json.Parser parser;
80+ try
81+ {
82+ parser = yield get_json_reply_async (details_uri, null);
83+ }
84+ catch (Error err)
85+ {
86+ return new GenericPreview (Path.get_basename (details_uri),
87+ err.message, null);
88+ }
89+
90+ if (U1MSPreviewFactory.is_u1ms_details (parser))
91+ {
92+ var u1mspf = new U1MSPreviewFactory ();
93+ var preview = u1mspf.create_preview (parser);
94+ u1mspf.add_download_action (preview); // download will be handled by normal activation
95+ if (player == null)
96+ player = new PreviewPlayerHandler ();
97+ player.music_preview = preview;
98+ return preview;
99+ }
100+ else
101+ {
102+ var root = parser.get_root ().get_object ();
103+ unowned string title = root.get_string_member ("title");
104+ unowned string description = root.get_string_member ("description_html");
105+
106+ unowned string price = null;
107+ if (root.has_member ("formatted_price"))
108+ price = root.get_string_member ("formatted_price");
109+ else if (root.has_member ("price"))
110+ price = root.get_string_member ("price");
111+
112+ var img_obj = root.get_object_member ("images");
113+ string image_uri = extract_image_uri (img_obj, int.MAX);
114+
115+ Icon? image = null;
116+ if (image_uri != "")
117+ {
118+ image = new FileIcon (File.new_for_uri (image_uri));
119+ }
120+
121+ var preview = new GenericPreview (title, MarkupCleaner.html_to_pango_markup (description), image);
122+ var icon_dir = File.new_for_path (ICON_PATH);
123+ var icon = new FileIcon (icon_dir.get_child ("service-amazon.svg"));
124+ var buy_action = new PreviewAction ("buy", _("Buy"), icon);
125+ if (price != null) buy_action.extra_text = price;
126+ /* Leaving the activation on unity for now */
127+ // buy_action.activated.connect ((uri) => { });
128+ preview.add_action (buy_action);
129+ return preview;
130+ }
131+ }
132+
133 private Preview? generate_preview_for_uri (string uri)
134 {
135 string? details_uri =
136@@ -133,52 +197,13 @@
137 "No data available", null);
138 }
139
140- try
141- {
142- var parser = get_json_reply (details_uri, null);
143-
144- if (U1MSPreviewFactory.is_u1ms_details (parser))
145- {
146- var u1mspf = new U1MSPreviewFactory ();
147- var preview = u1mspf.create_preview (parser);
148- u1mspf.add_download_action (preview); // download will be handled by normal activation
149- if (player == null)
150- player = new PreviewPlayerHandler ();
151- player.music_preview = preview;
152- return preview;
153- }
154- else
155- {
156- var root = parser.get_root ().get_object ();
157- unowned string title = root.get_string_member ("title");
158- unowned string description = root.get_string_member ("description_html");
159- unowned string price = root.get_string_member ("formatted_price");
160- if (price == null) price = root.get_string_member ("price");
161-
162- var img_obj = root.get_object_member ("images");
163- string image_uri = extract_image_uri (img_obj, int.MAX);
164-
165- Icon? image = null;
166- if (image_uri != "")
167- {
168- image = new FileIcon (File.new_for_uri (image_uri));
169- }
170-
171- var preview = new GenericPreview (title, MarkupCleaner.html_to_pango_markup (description), image);
172- var icon_dir = File.new_for_path (ICON_PATH);
173- var icon = new FileIcon (icon_dir.get_child ("service-amazon.svg"));
174- var buy_action = new PreviewAction ("buy", _("Buy"), icon);
175- if (price != null) buy_action.extra_text = price;
176- /* Leaving the activation on unity for now */
177- // buy_action.activated.connect ((uri) => { });
178- preview.add_action (buy_action);
179- return preview;
180- }
181- }
182- catch (Error err)
183- {
184- return new GenericPreview (Path.get_basename (uri), err.message, null);
185- }
186+ var preview = new AsyncPreview ();
187+ process_preview_request.begin (details_uri, (obj, res) =>
188+ {
189+ var real_preview = process_preview_request.end (res);
190+ preview.preview_ready (real_preview);
191+ });
192+ return preview;
193 }
194
195 private string build_search_uri (string query, SearchType search_type)
196@@ -199,29 +224,55 @@
197 }
198
199 private async Json.Parser get_json_reply_async (string uri,
200- Cancellable cancellable)
201+ Cancellable? cancellable)
202 throws Error
203 {
204 message ("Sending request: %s", uri);
205
206- var file = File.new_for_uri (uri);
207- var stream = yield file.read_async (Priority.DEFAULT, cancellable);
208- var parser = new Json.Parser ();
209- yield parser.load_from_stream_async (stream);
210-
211- return parser;
212- }
213-
214- private Json.Parser get_json_reply (string uri,
215- Cancellable? cancellable)
216- throws Error
217- {
218- message ("Sending sync request: %s", uri);
219-
220- var file = File.new_for_uri (uri);
221- var stream = file.read (cancellable);
222- var parser = new Json.Parser ();
223- parser.load_from_stream (stream);
224+ var msg = new Soup.Message ("GET", uri);
225+ session.queue_message (msg, (session_, msg_) =>
226+ {
227+ msg = msg_;
228+ get_json_reply_async.callback ();
229+ });
230+
231+ var cancelled = false;
232+ ulong cancel_id = 0;
233+ if (cancellable != null)
234+ {
235+ cancel_id = cancellable.connect (() =>
236+ {
237+ cancelled = true;
238+ session.cancel_message (msg, Soup.KnownStatusCode.CANCELLED);
239+ });
240+ }
241+
242+ yield;
243+
244+ if (cancelled)
245+ {
246+ // we can't disconnect right away, as that would deadlock (cause
247+ // cancel_message doesn't return before invoking the callback)
248+ Idle.add (get_json_reply_async.callback);
249+ yield;
250+ cancellable.disconnect (cancel_id);
251+ throw new IOError.CANCELLED ("Cancelled");
252+ }
253+
254+ if (msg.status_code < 100)
255+ {
256+ throw new IOError.FAILED ("Request failed with error %u", msg.status_code);
257+ }
258+ else if (msg.status_code != 200)
259+ {
260+ warning ("Request returned status code %u", msg.status_code);
261+ }
262+
263+ if (msg.response_body.data == null)
264+ throw new IOError.FAILED ("Request didn't return any content");
265+
266+ var parser = new Json.Parser ();
267+ parser.load_from_data ((string) msg.response_body.data);
268
269 return parser;
270 }
271@@ -308,8 +359,12 @@
272 var image_obj = result.get_object_member ("images");
273 string image_uri = extract_image_uri (image_obj, 128*128);
274
275- unowned string price = result.get_string_member ("formatted_price");
276- if (price == null) price = result.get_string_member ("price");
277+ unowned string price = null;
278+ if (result.has_member ("formatted_price"))
279+ price = result.get_string_member ("formatted_price");
280+ else if (result.has_member ("price"))
281+ price = result.get_string_member ("price");
282+
283 if (image_uri != "")
284 {
285 // TODO: what to do if we have price but no icon?
286
287=== added directory 'vapi'
288=== added file 'vapi/Makefile.am'
289--- vapi/Makefile.am 1970-01-01 00:00:00 +0000
290+++ vapi/Makefile.am 2012-09-26 11:13:24 +0000
291@@ -0,0 +1,5 @@
292+NULL =
293+BUILT_SOURCES =
294+CLEANFILES =
295+EXTRA_DIST = libsoup-gnome-2.4.vapi
296+
297
298=== added file 'vapi/libsoup-gnome-2.4.vapi'
299--- vapi/libsoup-gnome-2.4.vapi 1970-01-01 00:00:00 +0000
300+++ vapi/libsoup-gnome-2.4.vapi 2012-09-26 11:13:24 +0000
301@@ -0,0 +1,8 @@
302+[CCode (cprefix = "Soup", gir_namespace = "SoupGNOME", gir_version = "2.4", lower_case_cprefix = "soup_")]
303+namespace SoupGNOME {
304+ [CCode (cheader_filename = "libsoup/soup-gnome.h", type_id = "soup_proxy_resolver_gnome_get_type ()")]
305+ public class ProxyResolverGNOME : Soup.ProxyResolverDefault, Soup.ProxyURIResolver, Soup.SessionFeature {
306+ [CCode (has_construct_function = false)]
307+ protected ProxyResolverGNOME ();
308+ }
309+}

Subscribers

People subscribed via source and target branches

to all changes: