Merge lp:~mardy/shotwell/update-uoa into lp:~robert-ancell/shotwell/update-0.12.90

Proposed by Alberto Mardegan on 2012-08-28
Status: Merged
Merge reported by: Robert Ancell
Merged at revision: not available
Proposed branch: lp:~mardy/shotwell/update-uoa
Merge into: lp:~robert-ancell/shotwell/update-0.12.90
Diff against target: 1438 lines (+489/-601)
1 file modified
debian/patches/06_uoa.patch (+489/-601)
To merge this branch: bzr merge lp:~mardy/shotwell/update-uoa
Reviewer Review Type Date Requested Status
Robert Ancell 2012-08-28 Pending
Review via email: mp+121556@code.launchpad.net

Description of the change

Updated UOA patch.

To post a comment you must log in.
Sebastien Bacher (seb128) wrote :

Thanks mardy, I got that merged into the Ubuntu branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/patches/06_uoa.patch'
2--- debian/patches/06_uoa.patch 2012-08-24 03:46:31 +0000
3+++ debian/patches/06_uoa.patch 2012-08-28 08:16:23 +0000
4@@ -1,8 +1,11 @@
5+Description: use Ubuntu Online Accounts for Picasa, Facebook and Flickr export plugins
6+Author: Alberto Mardegan <alberto.mardegan@canonical.com>
7+
8 === modified file 'Makefile'
9 Index: shotwell-0.12.90/Makefile
10 ===================================================================
11---- shotwell-0.12.90.orig/Makefile 2012-08-24 15:04:46.000000000 +1200
12-+++ shotwell-0.12.90/Makefile 2012-08-24 15:15:23.963988123 +1200
13+--- shotwell-0.12.90.orig/Makefile 2012-08-28 10:25:15.248034132 +0300
14++++ shotwell-0.12.90/Makefile 2012-08-28 10:25:15.288033628 +0300
15 @@ -151,6 +151,7 @@
16 trash.ui
17
18@@ -22,8 +25,8 @@
19 mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps
20 Index: shotwell-0.12.90/misc/org.yorba.shotwell.gschema.xml
21 ===================================================================
22---- shotwell-0.12.90.orig/misc/org.yorba.shotwell.gschema.xml 2012-08-24 09:03:04.000000000 +1200
23-+++ shotwell-0.12.90/misc/org.yorba.shotwell.gschema.xml 2012-08-24 15:15:23.963988123 +1200
24+--- shotwell-0.12.90.orig/misc/org.yorba.shotwell.gschema.xml 2012-08-24 00:03:04.000000000 +0300
25++++ shotwell-0.12.90/misc/org.yorba.shotwell.gschema.xml 2012-08-28 10:25:15.288033628 +0300
26 @@ -304,6 +304,12 @@
27 <description>Facebook user i.d. for the currently logged in user, if any</description>
28 </key>
29@@ -40,7 +43,7 @@
30 Index: shotwell-0.12.90/misc/shotwell.application
31 ===================================================================
32 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
33-+++ shotwell-0.12.90/misc/shotwell.application 2012-08-24 15:15:23.967988123 +1200
34++++ shotwell-0.12.90/misc/shotwell.application 2012-08-28 10:25:15.292033578 +0300
35 @@ -0,0 +1,18 @@
36 +<?xml version="1.0" encoding="UTF-8" ?>
37 +<application id="shotwell">
38@@ -62,8 +65,8 @@
39 +</application>
40 Index: shotwell-0.12.90/plugins/Makefile
41 ===================================================================
42---- shotwell-0.12.90.orig/plugins/Makefile 2012-08-24 09:03:04.000000000 +1200
43-+++ shotwell-0.12.90/plugins/Makefile 2012-08-24 15:15:23.967988123 +1200
44+--- shotwell-0.12.90.orig/plugins/Makefile 2012-08-24 00:03:04.000000000 +0300
45++++ shotwell-0.12.90/plugins/Makefile 2012-08-28 10:25:15.292033578 +0300
46 @@ -4,7 +4,10 @@
47 DIST_FILES := \
48 Makefile \
49@@ -78,8 +81,8 @@
50 all: $(ALL_PLUGINS)
51 Index: shotwell-0.12.90/plugins/Makefile.plugin.mk
52 ===================================================================
53---- shotwell-0.12.90.orig/plugins/Makefile.plugin.mk 2012-08-24 09:03:04.000000000 +1200
54-+++ shotwell-0.12.90/plugins/Makefile.plugin.mk 2012-08-24 15:15:23.967988123 +1200
55+--- shotwell-0.12.90.orig/plugins/Makefile.plugin.mk 2012-08-24 00:03:04.000000000 +0300
56++++ shotwell-0.12.90/plugins/Makefile.plugin.mk 2012-08-28 10:25:15.292033578 +0300
57 @@ -27,6 +27,8 @@
58 # automatically include the shotwell-plugin-dev-1.0 package as a local dependency
59 EXT_PKGS := $(PKGS)
60@@ -91,8 +94,8 @@
61 SRC_FILES := ../common/Resources.vala $(SRC_FILES)
62 Index: shotwell-0.12.90/plugins/common/RESTSupport.vala
63 ===================================================================
64---- shotwell-0.12.90.orig/plugins/common/RESTSupport.vala 2012-08-24 09:03:04.000000000 +1200
65-+++ shotwell-0.12.90/plugins/common/RESTSupport.vala 2012-08-24 15:15:23.967988123 +1200
66+--- shotwell-0.12.90.orig/plugins/common/RESTSupport.vala 2012-08-24 00:03:04.000000000 +0300
67++++ shotwell-0.12.90/plugins/common/RESTSupport.vala 2012-08-28 10:25:15.296033528 +0300
68 @@ -314,7 +314,7 @@
69 old_url = message.get_uri().to_string(false);
70 url_with_query = get_endpoint_url() + "?" + formdata_string;
71@@ -105,7 +108,7 @@
72 Index: shotwell-0.12.90/plugins/common/accounts.vala
73 ===================================================================
74 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
75-+++ shotwell-0.12.90/plugins/common/accounts.vala 2012-08-24 15:15:23.967988123 +1200
76++++ shotwell-0.12.90/plugins/common/accounts.vala 2012-08-28 10:25:15.296033528 +0300
77 @@ -0,0 +1,54 @@
78 +/* Copyright 2009-2011 Yorba Foundation
79 + *
80@@ -163,8 +166,8 @@
81 +
82 Index: shotwell-0.12.90/plugins/shotwell-publishing/FacebookPublishing.vala
83 ===================================================================
84---- shotwell-0.12.90.orig/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-24 15:07:12.024005156 +1200
85-+++ shotwell-0.12.90/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-24 15:15:23.967988123 +1200
86+--- shotwell-0.12.90.orig/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-24 00:03:04.000000000 +0300
87++++ shotwell-0.12.90/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-28 11:11:00.554691926 +0300
88 @@ -4,6 +4,8 @@
89 * (version 2.1 or later). See the COPYING file in this distribution.
90 */
91@@ -186,7 +189,7 @@
92 }
93
94 namespace Publishing.Facebook {
95-@@ -163,14 +170,103 @@
96+@@ -163,11 +170,11 @@
97 private int publish_to_album = NO_ALBUM;
98 private weak Spit.Publishing.PluginHost host = null;
99 private FacebookRESTSession session = null;
100@@ -199,99 +202,7 @@
101
102 private Resolution target_resolution = Resolution.HIGH;
103
104-+ private struct LocaleLookup {
105-+ public string prefix;
106-+ public string translation;
107-+ public string? exception_code;
108-+ public string? exception_translation;
109-+ public string? exception_code_2;
110-+ public string? exception_translation_2;
111-+ }
112-+
113-+ private const LocaleLookup[] locale_lookup_table = {
114-+ { "es", "es-la", "ES", "es-es" },
115-+ { "en", "en-gb", "US", "en-us" },
116-+ { "fr", "fr-fr", "CA", "fr-ca" },
117-+ { "pt", "pt-br", "PT", "pt-pt" },
118-+ { "zh", "zh-cn", "HK", "zh-hk", "TW", "zh-tw" },
119-+ { "af", "af-za" },
120-+ { "ar", "ar-ar" },
121-+ { "nb", "nb-no" },
122-+ { "no", "nb-no" },
123-+ { "id", "id-id" },
124-+ { "ms", "ms-my" },
125-+ { "ca", "ca-es" },
126-+ { "cs", "cs-cz" },
127-+ { "cy", "cy-gb" },
128-+ { "da", "da-dk" },
129-+ { "de", "de-de" },
130-+ { "tl", "tl-ph" },
131-+ { "ko", "ko-kr" },
132-+ { "hr", "hr-hr" },
133-+ { "it", "it-it" },
134-+ { "lt", "lt-lt" },
135-+ { "hu", "hu-hu" },
136-+ { "nl", "nl-nl" },
137-+ { "ja", "ja-jp" },
138-+ { "nb", "nb-no" },
139-+ { "no", "nb-no" },
140-+ { "pl", "pl-pl" },
141-+ { "ro", "ro-ro" },
142-+ { "ru", "ru-ru" },
143-+ { "sk", "sk-sk" },
144-+ { "sl", "sl-sl" },
145-+ { "sv", "sv-se" },
146-+ { "th", "th-th" },
147-+ { "vi", "vi-vn" },
148-+ { "tr", "tr-tr" },
149-+ { "el", "el-gr" },
150-+ { "bg", "bg-bg" },
151-+ { "sr", "sr-rs" },
152-+ { "he", "he-il" },
153-+ { "hi", "hi-in" },
154-+ { "bn", "bn-in" },
155-+ { "pa", "pa-in" },
156-+ { "ta", "ta-in" },
157-+ { "te", "te-in" },
158-+ { "ml", "ml-in" }
159-+ };
160-+
161-+ private string get_system_locale_as_facebook_locale() {
162-+ unowned string? raw_system_locale = Intl.setlocale(LocaleCategory.ALL, "");
163-+ if (raw_system_locale == null || raw_system_locale == "")
164-+ return "www";
165-+
166-+ string system_locale = raw_system_locale.split(".")[0];
167-+
168-+ foreach (LocaleLookup locale_lookup in locale_lookup_table) {
169-+ if (!system_locale.has_prefix(locale_lookup.prefix))
170-+ continue;
171-+
172-+ if (locale_lookup.exception_code != null) {
173-+ assert(locale_lookup.exception_translation != null);
174-+
175-+ if (system_locale.contains(locale_lookup.exception_code))
176-+ return locale_lookup.exception_translation;
177-+ }
178-+
179-+ if (locale_lookup.exception_code_2 != null) {
180-+ assert(locale_lookup.exception_translation_2 != null);
181-+
182-+ if (system_locale.contains(locale_lookup.exception_code_2))
183-+ return locale_lookup.exception_translation_2;
184-+ }
185-+
186-+ return locale_lookup.translation;
187-+ }
188-+
189-+ // default
190-+ return "www";
191-+ }
192-+
193- public FacebookPublisher(Spit.Publishing.Service service,
194- Spit.Publishing.PluginHost host) {
195- debug("FacebookPublisher instantiated.");
196-@@ -402,37 +498,80 @@
197+@@ -402,37 +409,56 @@
198 start();
199 }
200
201@@ -347,46 +258,22 @@
202 + data = account.get_session_parameters(out mechanism);
203 + debug("Got account data");
204 + } catch (GLib.Error e) {
205-+ debug("EVENT: couldn't create session for account: %s",
206-+ e.message);
207-+ }
208-+ }
209-+
210-+ if (auth_session == null) {
211-+ debug("Creating unbound session");
212-+ try {
213-+ auth_session = new Signon.AuthSession(0, "oauth2");
214-+ } catch (GLib.Error e) {
215-+ debug("EVENT: AuthSession creation failed: %s", e.message);
216++ warning("EVENT: couldn't create session for account: %s",
217++ e.message);
218 + return;
219 + }
220 }
221 +
222 + if (data == null) {
223-+ debug("Using own params");
224-+ data = new HashTable<string,Value?>(str_hash, str_equal);
225-+ string facebook_locale = get_system_locale_as_facebook_locale();
226-+ string host_name = "%s.facebook.com".printf(facebook_locale);
227-+ data.insert("Host", host_name);
228-+ data.insert("AuthPath", "/dialog/oauth");
229-+ data.insert("ClientId", APPLICATION_ID);
230-+ data.insert("RedirectUri", "https://www.facebook.com/connect/login_success.html");
231-+ string[] scopes = {
232-+ "offline_access",
233-+ "publish_stream",
234-+ "user_photos",
235-+ "user_videos"
236-+ };
237-+ data.insert("Scope", scopes);
238-+ string[] response_type = {
239-+ "token"
240-+ };
241-+ data.insert("ResponseType", response_type);
242++ warning ("No account authentication data");
243++ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR(
244++ "Error while accessing the account"));
245++ return;
246 + }
247 +
248 + var windowId = host.get_dialog_xid();
249 + if (windowId != 0) {
250-+ data.insert("WindowId", windowId);
251++ data.insert("WindowId", (uint)windowId);
252 + }
253 +
254 + auth_session.process(data, mechanism, on_processed);
255@@ -394,7 +281,7 @@
256 }
257
258 private void do_save_session_information() {
259-@@ -562,30 +701,6 @@
260+@@ -562,30 +588,6 @@
261 host.post_error(err);
262 }
263
264@@ -425,7 +312,7 @@
265 private void on_session_authenticated() {
266 if (!is_running())
267 return;
268-@@ -773,14 +888,8 @@
269+@@ -773,14 +775,8 @@
270 get_persistent_uid(), get_persistent_user_name());
271 on_session_authenticated();
272 } else {
273@@ -442,13 +329,12 @@
274 }
275 }
276
277-@@ -909,39 +1018,14 @@
278+@@ -909,39 +905,14 @@
279 return (access_token != null && uid != null && user_name != null);
280 }
281
282 - public void authenticate_with_parameters(string access_token, string uid, string user_name) {
283-+ public void authenticate_with_parameters(string access_token, string? uid, string? user_name) {
284- this.access_token = access_token;
285+- this.access_token = access_token;
286 - this.uid = uid;
287 - this.user_name = user_name;
288 - }
289@@ -477,7 +363,8 @@
290 - access_token = access_token.replace("#access_token=", "");
291 -
292 - // we've got an access token!
293-- this.access_token = access_token;
294++ public void authenticate_with_parameters(string access_token, string? uid, string? user_name) {
295+ this.access_token = access_token;
296 -
297 - do_user_id_fetch_transaction();
298 + if (uid == null) {
299@@ -489,7 +376,7 @@
300 }
301
302 public string get_endpoint_url() {
303-@@ -1335,190 +1419,6 @@
304+@@ -1335,190 +1306,6 @@
305 }
306 }
307
308@@ -682,8 +569,8 @@
309 private Gtk.Box pane_widget = null;
310 Index: shotwell-0.12.90/plugins/shotwell-publishing/FlickrPublishing.vala
311 ===================================================================
312---- shotwell-0.12.90.orig/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-24 15:12:30.611994126 +1200
313-+++ shotwell-0.12.90/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-24 15:15:23.971988123 +1200
314+--- shotwell-0.12.90.orig/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-24 00:03:04.000000000 +0300
315++++ shotwell-0.12.90/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-28 11:11:16.866844467 +0300
316 @@ -4,6 +4,8 @@
317 * (version 2.1 or later). See the COPYING file in this distribution.
318 */
319@@ -748,8 +635,8 @@
320 + data = account.get_session_parameters(out mechanism);
321 + debug("Got account data");
322 + } catch (GLib.Error e) {
323-+ debug("EVENT: couldn't create session for account: %s",
324-+ e.message);
325++ warning("EVENT: couldn't create session for account: %s",
326++ e.message);
327 + }
328 + }
329
330@@ -774,7 +661,7 @@
331 - session.set_request_phase_credentials(token, token_secret);
332 + var windowId = host.get_dialog_xid();
333 + if (windowId != 0) {
334-+ data.insert("WindowId", windowId);
335++ data.insert("WindowId", (uint)windowId);
336 + }
337
338 - do_launch_system_browser(token);
339@@ -1099,8 +986,8 @@
340 return access_phase_token;
341 Index: shotwell-0.12.90/plugins/shotwell-publishing/Makefile
342 ===================================================================
343---- shotwell-0.12.90.orig/plugins/shotwell-publishing/Makefile 2012-08-24 15:13:53.000000000 +1200
344-+++ shotwell-0.12.90/plugins/shotwell-publishing/Makefile 2012-08-24 15:15:23.971988123 +1200
345+--- shotwell-0.12.90.orig/plugins/shotwell-publishing/Makefile 2012-08-24 00:03:04.000000000 +0300
346++++ shotwell-0.12.90/plugins/shotwell-publishing/Makefile 2012-08-28 10:25:15.300033478 +0300
347 @@ -18,6 +18,7 @@
348 FlickrPublishing.vala \
349 YouTubePublishing.vala \
350@@ -1111,8 +998,8 @@
351 ../common/ui.vala
352 Index: shotwell-0.12.90/plugins/shotwell-publishing/PicasaPublishing.vala
353 ===================================================================
354---- shotwell-0.12.90.orig/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-24 15:15:13.435988488 +1200
355-+++ shotwell-0.12.90/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-24 15:15:23.971988123 +1200
356+--- shotwell-0.12.90.orig/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-24 00:03:04.000000000 +0300
357++++ shotwell-0.12.90/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-28 11:10:22.379612657 +0300
358 @@ -4,6 +4,8 @@
359 * (version 2.1 or later). See the COPYING file in this distribution.
360 */
361@@ -1142,173 +1029,170 @@
362
363 public PicasaPublisher(Spit.Publishing.Service service,
364 Spit.Publishing.PluginHost host) {
365-@@ -123,6 +131,29 @@
366+@@ -83,18 +91,6 @@
367+ media_type |= p.get_media_type();
368+ }
369+
370+- private string get_user_authorization_url() {
371+- return "https://accounts.google.com/o/oauth2/auth?" +
372+- "response_type=code&" +
373+- "client_id=" + OAUTH_CLIENT_ID + "&" +
374+- "redirect_uri=" + Soup.URI.encode("urn:ietf:wg:oauth:2.0:oob", null) + "&" +
375+- "scope=" + Soup.URI.encode("http://picasaweb.google.com/data/", null) + "+" +
376+- Soup.URI.encode("https://www.googleapis.com/auth/userinfo.profile", null) + "&" +
377+- "state=connect&" +
378+- "access_type=offline&" +
379+- "approval_prompt=force";
380+- }
381+-
382+ private Album[] extract_albums(Xml.Node* document_root) throws Spit.Publishing.PublishingError {
383+ Album[] result = new Album[0];
384+
385+@@ -133,14 +129,6 @@
386 return result;
387 }
388
389-+ private string? extract_username(Xml.Node* document_root) throws Spit.Publishing.PublishingError {
390-+ Xml.Node* doc_node_iter = null;
391-+ if (document_root->name == "feed")
392-+ doc_node_iter = document_root->children;
393-+ else
394-+ throw new Spit.Publishing.PublishingError.MALFORMED_RESPONSE("response root node " +
395-+ "isn't a <feed>");
396-+
397-+ for ( ; doc_node_iter != null; doc_node_iter = doc_node_iter->next) {
398-+ if (doc_node_iter->name != "author")
399-+ continue;
400-+
401-+ Xml.Node* author_node_iter = doc_node_iter->children;
402-+ for ( ; author_node_iter != null; author_node_iter = author_node_iter->next) {
403-+ if (author_node_iter->name == "name")
404-+ return author_node_iter->get_content();
405-+ }
406-+
407-+ }
408-+
409-+ return null;
410-+ }
411-+
412- internal string? get_persistent_username() {
413- return host.get_config_string("user_name", null);
414- }
415-@@ -131,6 +162,10 @@
416- return host.get_config_string("auth_token", null);
417- }
418-
419-+ internal string? get_persistent_auth_method() {
420-+ return host.get_config_string("auth_method", null);
421-+ }
422-+
423- internal void set_persistent_username(string username) {
424- host.set_config_string("user_name", username);
425- }
426-@@ -139,11 +174,16 @@
427- host.set_config_string("auth_token", auth_token);
428- }
429-
430-+ internal void set_persistent_auth_method(string auth_method) {
431-+ host.set_config_string("auth_method", auth_method);
432-+ }
433-+
434- internal void invalidate_persistent_session() {
435- debug("invalidating persisted Picasa Web Albums session.");
436-
437-- host.unset_config_key("user_name");
438-- host.unset_config_key("auth_token");
439-+ set_persistent_username("");
440-+ set_persistent_auth_token("");
441-+ set_persistent_auth_method("");
442- }
443-
444- internal bool is_persistent_session_available() {
445-@@ -164,76 +204,89 @@
446+- internal string? get_persistent_refresh_token() {
447+- return host.get_config_string("refresh_token", null);
448+- }
449+-
450+- internal void set_persistent_refresh_token(string token) {
451+- host.set_config_string("refresh_token", token);
452+- }
453+-
454+ internal bool get_persistent_strip_metadata() {
455+ return host.get_config_bool("strip_metadata", false);
456+ }
457+@@ -149,16 +137,6 @@
458+ host.set_config_bool("strip_metadata", strip_metadata);
459+ }
460+
461+- internal void invalidate_persistent_session() {
462+- debug("invalidating persisted Picasa Web Albums session.");
463+-
464+- host.unset_config_key("refresh_token");
465+- }
466+-
467+- internal bool is_persistent_session_available() {
468+- return get_persistent_refresh_token() != null;
469+- }
470+-
471+ public bool is_running() {
472+ return running;
473+ }
474+@@ -173,92 +151,69 @@
475
476 debug("EVENT: user clicked 'Login' in welcome pane.");
477
478-- do_show_credentials_pane(CredentialsPane.Mode.INTRO);
479-- }
480--
481-- private void on_credentials_go_back() {
482-- if (!is_running())
483-- return;
484--
485-- debug("EVENT: user clicked 'Go Back' in credentials pane.");
486--
487-- do_show_service_welcome_pane();
488-- }
489--
490-- private void on_credentials_login(string username, string password) {
491-- if (!is_running())
492-- return;
493--
494-- debug("EVENT: user clicked 'Login' in credentials pane.");
495--
496-- this.username = username;
497--
498-- do_network_login(username, password);
499-- }
500--
501-- private void on_token_fetch_complete(Publishing.RESTSupport.Transaction txn) {
502-- txn.completed.disconnect(on_token_fetch_complete);
503-- txn.network_error.disconnect(on_token_fetch_error);
504--
505-- if (!is_running())
506-- return;
507--
508-- if (session.is_authenticated()) // ignore these events if the session is already auth'd
509-- return;
510--
511-- debug("EVENT: network transaction to fetch token for login completed successfully.");
512--
513-- int index = txn.get_response().index_of("Auth=");
514-- string auth_substring = (index >= 0) ? txn.get_response()[index:txn.get_response().length] : "";
515-- auth_substring = auth_substring.chomp();
516-- string auth_token = auth_substring.substring(5);
517+- do_launch_browser_for_authorization();
518 + do_hosted_web_authentication();
519-+ }
520-+
521+ }
522+
523+- private void on_auth_code_entry_pane_proceed(AuthCodeEntryPane sender, string code) {
524+- debug("EVENT: user clicked 'Continue' in authorization code entry pane.");
525+-
526+- sender.proceed.disconnect(on_auth_code_entry_pane_proceed);
527+-
528+- do_get_access_tokens(code);
529+- }
530+-
531+- private void on_browser_launched() {
532+- debug("EVENT: system web browser launched to solicit user authorization.");
533+-
534+- do_show_auth_code_entry_pane();
535+- }
536+-
537+- private void on_get_access_tokens_completed(Publishing.RESTSupport.Transaction txn) {
538+- txn.completed.disconnect(on_get_access_tokens_completed);
539+- txn.network_error.disconnect(on_get_access_tokens_error);
540 + public void on_processed(Signon.AuthSession self, owned HashTable<string,Value?>? session_data, GLib.Error error){
541 + if (error != null) {
542 + debug("got error: %s", error.message);
543 + /* TODO: handle errors */
544 + return;
545 + }
546-+
547+
548+- debug("EVENT: network transaction to exchange authorization code for access tokens " +
549+- "completed successfully.");
550 + host.set_service_locked(true);
551 + host.install_account_fetch_wait_pane();
552
553- session.authenticated.connect(on_session_authenticated);
554-- session.authenticate(auth_token, username);
555-+
556+- do_extract_tokens(txn.get_response());
557+- }
558+-
559+- private void on_get_access_tokens_error(Publishing.RESTSupport.Transaction txn,
560+- Spit.Publishing.PublishingError err) {
561+- txn.completed.disconnect(on_get_access_tokens_completed);
562+- txn.network_error.disconnect(on_get_access_tokens_error);
563++ session.authenticated.connect(on_session_authenticated);
564+
565+- debug("EVENT: network transaction to exchange authorization code for access tokens " +
566+- "failed; response = '%s'", txn.get_response());
567+- }
568+-
569+- private void on_refresh_token_available(string token) {
570+- debug("EVENT: an OAuth refresh token has become available.");
571+-
572+- do_save_refresh_token_to_configuration_system(token);
573+- }
574+-
575+- private void on_access_token_available(string token) {
576+- debug("EVENT: an OAuth access token has become available.");
577+-
578+- do_authenticate_session(token);
579+- }
580+-
581+- private void on_not_set_up_pane_proceed(NotSetUpMessagePane sender) {
582+- debug("EVENT: user clicked 'Continue' in Account Not Set Up Message Pane.");
583+-
584+- sender.proceed.disconnect(on_not_set_up_pane_proceed);
585+-
586+- do_launch_browser_for_authorization();
587 + if (session_data.lookup("AccessToken") != null) {
588 + string token = session_data.lookup("AccessToken").get_string();
589 + debug("OAuth Access Token: %s", token);
590-+ session.authenticate(token, null, "OAuth2");
591++ session.authenticate(token, "OAuth2");
592 + } else if (session_data.lookup("AuthToken") != null) {
593 + string token = session_data.lookup("AuthToken").get_string();
594 + debug("ClientLogin Access Token: %s", token);
595-+ session.authenticate(token, null, "ClientLogin");
596++ session.authenticate(token, "ClientLogin");
597 + } else {
598 + debug("Access token not present!");
599 + }
600 }
601+-
602+- private void on_refresh_access_token_transaction_completed(Publishing.RESTSupport.Transaction
603+- txn) {
604+- txn.completed.disconnect(on_refresh_access_token_transaction_completed);
605+- txn.network_error.disconnect(on_refresh_access_token_transaction_error);
606+-
607+- if (!is_running())
608+- return;
609
610-- private void on_token_fetch_error(Publishing.RESTSupport.Transaction bad_txn,
611-- Spit.Publishing.PublishingError err) {
612-- bad_txn.completed.disconnect(on_token_fetch_complete);
613-- bad_txn.network_error.disconnect(on_token_fetch_error);
614--
615-- if (!is_running())
616-- return;
617--
618 - if (session.is_authenticated()) // ignore these events if the session is already auth'd
619 - return;
620--
621-- debug("EVENT: network transaction to fetch token for login failed; response = '%s'.",
622-- bad_txn.get_response());
623--
624-- // HTTP error 403 is invalid authentication -- if we get this error during token fetch
625-- // then we can just show the login screen again with a retry message; if we get any error
626-- // other than 403 though, we can't recover from it, so just post the error to the user
627-- if (bad_txn.get_status_code() == 403) {
628-- if (bad_txn.get_response().contains("CaptchaRequired"))
629-- do_show_credentials_pane(CredentialsPane.Mode.ADDITIONAL_SECURITY);
630-- else
631-- do_show_credentials_pane(CredentialsPane.Mode.FAILED_RETRY);
632-- }
633-- else {
634-- host.post_error(err);
635-- }
636 + private void do_hosted_web_authentication() {
637 + debug("ACTION: doing hosted web authentication.");
638-+
639+
640+- debug("EVENT: refresh access token transaction completed successfully.");
641+-
642+- do_extract_tokens(txn.get_response());
643+- }
644+-
645+- private void on_refresh_access_token_transaction_error(Publishing.RESTSupport.Transaction txn,
646+- Spit.Publishing.PublishingError err) {
647+- txn.completed.disconnect(on_refresh_access_token_transaction_completed);
648+- txn.network_error.disconnect(on_refresh_access_token_transaction_error);
649+-
650+- if (!is_running())
651+- return;
652 + HashTable<string,Value?> data = null;
653 + string mechanism = "user_agent";
654 +
655 + SharingAccounts accounts =
656 + new SharingAccounts();
657-+
658+
659+- if (session.is_authenticated()) // ignore these events if the session is already auth'd
660 + SharingAccount? account = accounts.get_account_for_provider("google");
661 + if (account != null) {
662 + try {
663@@ -1316,41 +1200,24 @@
664 + data = account.get_session_parameters(out mechanism);
665 + debug("Got account data");
666 + } catch (GLib.Error e) {
667-+ debug("EVENT: couldn't create session for account: %s",
668-+ e.message);
669-+ }
670-+ }
671-+
672-+ if (auth_session == null) {
673-+ debug("Creating unbound session");
674-+ try {
675-+ auth_session = new Signon.AuthSession(0, "oauth2");
676-+ } catch (GLib.Error e) {
677-+ debug("EVENT: AuthSession creation failed: %s", e.message);
678-+ return;
679++ warning("EVENT: couldn't create session for account: %s",
680++ e.message);
681 + }
682 + }
683 +
684 + if (data == null) {
685-+ debug("Using own params");
686-+ data = new HashTable<string,Value?>(str_hash, str_equal);
687-+ data.insert("Host", "accounts.google.com");
688-+ data.insert("AuthPath", "o/oauth2/auth");
689-+ data.insert("ClientId", "1041829795610-htf69c529db58qcq8jvf58bijn1ie3oi.apps.googleusercontent.com");
690-+ data.insert("RedirectUri", "http://www.mardy.it/oauth2callback");
691-+ string[] scopes = {
692-+ "https://picasaweb.google.com/data/"
693-+ };
694-+ data.insert("Scope", scopes);
695-+ string[] response_type = {
696-+ "token"
697-+ };
698-+ data.insert("ResponseType", response_type);
699++ warning ("No account authentication data");
700++ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR(
701++ "Error while accessing the account"));
702+ return;
703 + }
704-+
705+
706+- debug("EVENT: refresh access token transaction caused a network error.");
707+-
708+- host.post_error(err);
709 + var windowId = host.get_dialog_xid();
710 + if (windowId != 0) {
711-+ data.insert("WindowId", windowId);
712++ data.insert("WindowId", (uint)windowId);
713 + }
714 +
715 + auth_session.process(data, mechanism, on_processed);
716@@ -1358,7 +1225,7 @@
717 }
718
719 private void on_session_authenticated() {
720-@@ -271,25 +324,7 @@
721+@@ -313,19 +268,7 @@
722 debug("EVENT: fetching account and album information failed; response = '%s'.",
723 bad_txn.get_response());
724
725@@ -1366,161 +1233,286 @@
726 - // if we get a 404 error (resource not found) on the initial album fetch, then the
727 - // user's album feed doesn't exist -- this occurs when the user has a valid Google
728 - // account but it hasn't yet been set up for use with Picasa. In this case, we
729-- // re-display the credentials capture pane with an "account not set up" message.
730-- // In addition, we deauthenticate the session. Deauth is neccessary because we
731-- // did previously auth the user's account. If we get any other kind of error, we can't
732-- // recover, so just post it to the user
733-- session.deauthenticate();
734-- do_show_credentials_pane(CredentialsPane.Mode.NOT_SET_UP);
735-- } else if (bad_txn.get_status_code() == 403) {
736-- // if we get a 403 error (authentication failed) then we need to return to the login
737-- // screen because the user's auth token is no longer valid and he or she needs to
738-- // login again to obtain a new one
739-- session.deauthenticate();
740-- do_show_credentials_pane(CredentialsPane.Mode.INTRO);
741+- // display an informational pane with an "account not set up" message. In addition, we
742+- // deauthenticate the session. Deauth is neccessary because must've previously auth'd
743+- // the user's account to even be able to query the album feed.
744+- session.deauthenticate();
745+- do_show_not_set_up_pane();
746 - } else {
747+- // If we get any other kind of error, we can't recover, so just post it to the user
748 - host.post_error(err);
749 - }
750 + host.post_error(err);
751 }
752
753 private void on_publishing_options_logout() {
754-@@ -414,34 +449,6 @@
755+@@ -335,7 +278,6 @@
756+ debug("EVENT: user clicked 'Logout' in the publishing options pane.");
757+
758+ session.deauthenticate();
759+- invalidate_persistent_session();
760+
761+ do_show_service_welcome_pane();
762+ }
763+@@ -453,94 +395,6 @@
764 host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_service_welcome_login);
765 }
766
767-- private void do_show_credentials_pane(CredentialsPane.Mode mode) {
768-- debug("ACTION: showing credentials capture pane in %s mode.", mode.to_string());
769--
770-- CredentialsPane creds_pane = new CredentialsPane(host, mode);
771-- creds_pane.go_back.connect(on_credentials_go_back);
772-- creds_pane.login.connect(on_credentials_login);
773--
774-- host.install_dialog_pane(creds_pane);
775-- }
776--
777-- private void do_network_login(string username, string password) {
778-- debug("ACTION: running network login transaction for user = '%s'.", username);
779+- private void do_launch_browser_for_authorization() {
780+- string auth_url = get_user_authorization_url();
781+-
782+- debug("ACTION: launching external web browser to get user authorization; " +
783+- "authorization URL = '%s'", auth_url);
784+-
785+- try {
786+- Process.spawn_command_line_async("xdg-open " + auth_url);
787+- } catch (SpawnError e) {
788+- host.post_error(new Spit.Publishing.PublishingError.LOCAL_FILE_ERROR(
789+- _("couldn't launch system web browser to complete Picasa Web Albums login")));
790+- return;
791+- }
792+-
793+- on_browser_launched();
794+- }
795+-
796+- private void do_show_auth_code_entry_pane() {
797+- debug("ACTION: showing OAuth authorization code entry pane.");
798+-
799+- Gtk.Builder builder = new Gtk.Builder();
800+-
801+- try {
802+- builder.add_from_file(host.get_module_file().get_parent().get_child(
803+- "picasa_auth_code_entry_pane.glade").get_path());
804+- } catch (Error e) {
805+- warning("Could not parse UI file! Error: %s.", e.message);
806+- host.post_error(
807+- new Spit.Publishing.PublishingError.LOCAL_FILE_ERROR(
808+- _("A file required for publishing is unavailable. Publishing to Picasa Web Albums can't continue.")));
809+- return;
810+- }
811+-
812+- AuthCodeEntryPane pane = new AuthCodeEntryPane(builder);
813+- pane.proceed.connect(on_auth_code_entry_pane_proceed);
814+- host.install_dialog_pane(pane);
815+- }
816+-
817+- private void do_get_access_tokens(string code) {
818+- debug("ACTION: exchanging OAuth authorization code '%s' for access token.", code);
819+-
820+- GetAccessTokensTransaction txn = new GetAccessTokensTransaction(session, code);
821+- txn.completed.connect(on_get_access_tokens_completed);
822+- txn.network_error.connect(on_get_access_tokens_error);
823+-
824+- try {
825+- txn.execute();
826+- } catch (Spit.Publishing.PublishingError err) {
827+- host.post_error(err);
828+- }
829+- }
830+-
831+- private void do_extract_tokens(string response_body) {
832+- debug("ACTION: extracting OAuth tokens from body of server response");
833+-
834+- Json.Parser parser = new Json.Parser();
835+-
836+- try {
837+- parser.load_from_data(response_body);
838+- } catch (Error err) {
839+- host.post_error(new Spit.Publishing.PublishingError.MALFORMED_RESPONSE(
840+- "Couldn't parse JSON response: " + err.message));
841+- return;
842+- }
843+-
844+- Json.Object response_obj = parser.get_root().get_object();
845+-
846+- if ((!response_obj.has_member("access_token")) && (!response_obj.has_member("refresh_token"))) {
847+- host.post_error(new Spit.Publishing.PublishingError.MALFORMED_RESPONSE(
848+- "neither access_token nor refresh_token not present in server response"));
849+- return;
850+- }
851+-
852+- if (response_obj.has_member("refresh_token")) {
853+- string refresh_token = response_obj.get_string_member("refresh_token");
854+-
855+- if (refresh_token != "")
856+- on_refresh_token_available(refresh_token);
857+- }
858+-
859+- if (response_obj.has_member("access_token")) {
860+- string access_token = response_obj.get_string_member("access_token");
861+-
862+- if (access_token != "")
863+- on_access_token_available(access_token);
864+- }
865+- }
866+-
867+ private void do_extract_username(string response_body) {
868+ debug("ACTION: extracting username from body of server response");
869+
870+@@ -562,66 +416,8 @@
871+ if (username != "")
872+ this.username = username;
873+ }
874+-
875+- if (response_obj.has_member("access_token")) {
876+- string access_token = response_obj.get_string_member("access_token");
877+-
878+- if (access_token != "")
879+- on_access_token_available(access_token);
880+- }
881+ }
882+
883+- private void do_save_refresh_token_to_configuration_system(string token) {
884+- debug("ACTION: saving OAuth refresh token to configuration system");
885+-
886+- set_persistent_refresh_token(token);
887+- }
888+-
889+- private void do_refresh_session(string refresh_token) {
890+- debug("ACTION: using OAuth refresh token to refresh session.");
891 -
892 - host.install_login_wait_pane();
893--
894-- TokenFetchTransaction fetch_trans = new TokenFetchTransaction(session, username, password);
895-- fetch_trans.network_error.connect(on_token_fetch_error);
896-- fetch_trans.completed.connect(on_token_fetch_complete);
897--
898+-
899+- RefreshAccessTokenTransaction txn = new RefreshAccessTokenTransaction(session, refresh_token);
900+-
901+- txn.completed.connect(on_refresh_access_token_transaction_completed);
902+- txn.network_error.connect(on_refresh_access_token_transaction_error);
903+-
904 - try {
905-- fetch_trans.execute();
906+- txn.execute();
907 - } catch (Spit.Publishing.PublishingError err) {
908-- // 403 errors are recoverable, so don't post the error to our host immediately;
909-- // instead, try to recover from it
910-- on_token_fetch_error(fetch_trans, err);
911-- }
912-- }
913--
914- private void do_save_auth_info() {
915- debug("ACTION: saving authentication information to configuration system.");
916-
917-@@ -449,6 +456,7 @@
918-
919- set_persistent_auth_token(session.get_auth_token());
920- set_persistent_username(session.get_username());
921-+ set_persistent_auth_method(session.get_auth_method());
922+- host.post_error(err);
923+- }
924+- }
925+-
926+- private void do_authenticate_session(string token) {
927+- debug("ACTION: authenticating session.");
928+-
929+- session.authenticated.connect(on_session_authenticated);
930+- session.authenticate(token);
931+- }
932+-
933+- private void do_show_not_set_up_pane() {
934+- debug("ACTION: showing account not set up message pane");
935+-
936+- Gtk.Builder builder = new Gtk.Builder();
937+-
938+- try {
939+- builder.add_from_file(host.get_module_file().get_parent().get_child(
940+- "picasa_not_set_up_pane.glade").get_path());
941+- } catch (Error e) {
942+- warning("Could not parse UI file! Error: %s.", e.message);
943+- host.post_error(
944+- new Spit.Publishing.PublishingError.LOCAL_FILE_ERROR(
945+- _("A file required for publishing is unavailable. Publishing to Picasa Web Albums can't continue.")));
946+- return;
947+- }
948+-
949+- NotSetUpMessagePane pane = new NotSetUpMessagePane(builder);
950+- pane.proceed.connect(on_not_set_up_pane_proceed);
951+- host.install_dialog_pane(pane);
952+- }
953+-
954+ private void do_fetch_username() {
955+ debug("ACTION: running network transaction to fetch username.");
956+
957+@@ -771,11 +567,7 @@
958+
959+ running = true;
960+
961+- if (is_persistent_session_available()) {
962+- do_refresh_session(get_persistent_refresh_token());
963+- } else {
964+- do_show_service_welcome_pane();
965+- }
966++ do_show_service_welcome_pane();
967 }
968
969- private void do_fetch_account_information() {
970-@@ -485,6 +493,8 @@
971-
972- try {
973- albums = extract_albums(response_doc.get_root_node());
974-+ username = extract_username(response_doc.get_root_node());
975-+ set_persistent_username(username);
976- } catch (Spit.Publishing.PublishingError err) {
977- host.post_error(err);
978- return;
979-@@ -567,7 +577,8 @@
980-
981- if (is_persistent_session_available()) {
982- username = get_persistent_username();
983-- session.authenticate(get_persistent_auth_token(), get_persistent_username());
984-+ session.authenticate(get_persistent_auth_token(), get_persistent_username(),
985-+ get_persistent_auth_method());
986- do_fetch_account_information();
987- } else {
988- do_show_service_welcome_pane();
989-@@ -598,6 +609,7 @@
990+ public void stop() {
991+@@ -801,6 +593,7 @@
992+
993 internal class Session : Publishing.RESTSupport.Session {
994 private string? auth_token = null;
995- private string? username = null;
996 + private string? auth_method = null;
997
998 public Session() {
999 }
1000-@@ -606,9 +618,10 @@
1001+@@ -809,45 +602,24 @@
1002 return (auth_token != null);
1003 }
1004
1005-- public void authenticate(string auth_token, string username) {
1006-+ public void authenticate(string auth_token, string? username, string auth_method) {
1007+- public void authenticate(string auth_token) {
1008++ public void authenticate(string auth_token, string auth_method) {
1009 this.auth_token = auth_token;
1010- this.username = username;
1011 + this.auth_method = auth_method;
1012
1013 notify_authenticated();
1014 }
1015-@@ -616,6 +629,7 @@
1016+
1017 public void deauthenticate() {
1018 auth_token = null;
1019- username = null;
1020 + auth_method = null;
1021 }
1022-
1023- public string? get_username() {
1024-@@ -625,19 +639,9 @@
1025+
1026 public string? get_auth_token() {
1027 return auth_token;
1028 }
1029 -}
1030--
1031--internal class TokenFetchTransaction : Publishing.RESTSupport.Transaction {
1032-- private const string ENDPOINT_URL = "https://www.google.com/accounts/ClientLogin";
1033--
1034-- public TokenFetchTransaction(Session session, string username, string password) {
1035-- base.with_endpoint_url(session, ENDPOINT_URL);
1036--
1037-- add_argument("accountType", "HOSTED_OR_GOOGLE");
1038-- add_argument("Email", username);
1039-- add_argument("Passwd", password);
1040-- add_argument("service", "lh2");
1041-- add_argument("source", "yorba-shotwell-" + _VERSION);
1042-+
1043+
1044+-internal class GetAccessTokensTransaction : Publishing.RESTSupport.Transaction {
1045+- private const string ENDPOINT_URL = "https://accounts.google.com/o/oauth2/token";
1046+-
1047+- public GetAccessTokensTransaction(Session session, string auth_code) {
1048+- base.with_endpoint_url(session, ENDPOINT_URL);
1049+-
1050+- add_argument("code", auth_code);
1051+- add_argument("client_id", OAUTH_CLIENT_ID);
1052+- add_argument("client_secret", OAUTH_CLIENT_SECRET);
1053+- add_argument("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");
1054+- add_argument("grant_type", "authorization_code");
1055+- }
1056+-}
1057+-
1058+-internal class RefreshAccessTokenTransaction : Publishing.RESTSupport.Transaction {
1059+- private const string ENDPOINT_URL = "https://accounts.google.com/o/oauth2/token";
1060+-
1061+- public RefreshAccessTokenTransaction(Session session, string refresh_token) {
1062+- base.with_endpoint_url(session, ENDPOINT_URL);
1063+-
1064+- add_argument("client_id", OAUTH_CLIENT_ID);
1065+- add_argument("client_secret", OAUTH_CLIENT_SECRET);
1066+- add_argument("refresh_token", refresh_token);
1067+- add_argument("grant_type", "refresh_token");
1068 + public string? get_auth_method() {
1069 + return auth_method;
1070 }
1071 }
1072
1073-@@ -652,12 +656,19 @@
1074+@@ -862,7 +634,13 @@
1075 base.with_endpoint_url(session, endpoint_url, method);
1076 assert(session.is_authenticated());
1077
1078-- add_header("Authorization", "GoogleLogin auth=%s".printf(session.get_auth_token()));
1079+- add_header("Authorization", "Bearer " + session.get_auth_token());
1080 + if (session.get_auth_method() == "ClientLogin") {
1081 + add_header("Authorization",
1082-+ "GoogleLogin auth=%s".printf(session.get_auth_token()));
1083++ "GoogleLogin auth=" + session.get_auth_token());
1084 + } else {
1085-+ add_argument("access_token", session.get_auth_token());
1086 + add_header("Authorization",
1087-+ "Bearer %s".printf(session.get_auth_token()));
1088++ "Bearer " + session.get_auth_token());
1089 + }
1090 }
1091 }
1092
1093+@@ -875,7 +653,7 @@
1094+ }
1095+
1096 internal class AlbumDirectoryTransaction : AuthenticatedTransaction {
1097 - private const string ENDPOINT_URL = "http://picasaweb.google.com/data/feed/api/user/" +
1098 + private const string ENDPOINT_URL = "https://picasaweb.google.com/data/feed/api/user/" +
1099 "default";
1100
1101 public AlbumDirectoryTransaction(Session session) {
1102-@@ -674,7 +685,7 @@
1103+@@ -892,7 +670,7 @@
1104 }
1105
1106 private class AlbumCreationTransaction : AuthenticatedTransaction {
1107@@ -1529,227 +1521,123 @@
1108 "default";
1109 private const string ALBUM_ENTRY_TEMPLATE = "<?xml version='1.0' encoding='utf-8'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:gphoto='http://schemas.google.com/photos/2007'><title type='text'>%s</title><gphoto:access>%s</gphoto:access><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'></category></entry>";
1110
1111-@@ -747,8 +758,14 @@
1112+@@ -971,9 +749,14 @@
1113 // that we've been building up
1114 Soup.Message outbound_message =
1115 soup_form_request_new_from_multipart(get_endpoint_url(), message_parts);
1116-- outbound_message.request_headers.append("Authorization", "GoogleLogin auth=%s".printf(session.get_auth_token()));
1117+- outbound_message.request_headers.append("Authorization", "Bearer " +
1118+- session.get_auth_token());
1119 set_message(outbound_message);
1120 + if (session.get_auth_method() == "ClientLogin") {
1121 + add_header("Authorization",
1122-+ "GoogleLogin auth=%s".printf(session.get_auth_token()));
1123++ "GoogleLogin auth=" + session.get_auth_token());
1124 + } else {
1125 + add_header("Authorization",
1126-+ "Bearer %s".printf(session.get_auth_token()));
1127++ "Bearer " + session.get_auth_token());
1128 + }
1129
1130 // send the message and get its response
1131 set_is_executed(true);
1132-@@ -756,199 +773,6 @@
1133+@@ -981,95 +764,6 @@
1134 }
1135 }
1136
1137--internal class CredentialsPane : Spit.Publishing.DialogPane, GLib.Object {
1138-- public enum Mode {
1139-- INTRO,
1140-- FAILED_RETRY,
1141-- NOT_SET_UP,
1142-- ADDITIONAL_SECURITY;
1143--
1144-- public string to_string() {
1145-- switch (this) {
1146-- case Mode.INTRO:
1147-- return "INTRO";
1148--
1149-- case Mode.FAILED_RETRY:
1150-- return "FAILED_RETRY";
1151--
1152-- case Mode.NOT_SET_UP:
1153-- return "NOT_SET_UP";
1154--
1155-- case Mode.ADDITIONAL_SECURITY:
1156-- return "ADDITIONAL_SECURITY";
1157--
1158-- default:
1159-- error("unrecognized CredentialsPane.Mode enumeration value");
1160-- }
1161-- }
1162-- }
1163--
1164-- private LegacyCredentialsPane wrapped = null;
1165--
1166-- public signal void go_back();
1167-- public signal void login(string email, string password);
1168--
1169-- public CredentialsPane(Spit.Publishing.PluginHost host, Mode mode = Mode.INTRO,
1170-- string? username = null) {
1171-- wrapped = new LegacyCredentialsPane(host, mode, username);
1172-- }
1173--
1174-- protected void notify_go_back() {
1175-- go_back();
1176-- }
1177--
1178-- protected void notify_login(string email, string password) {
1179-- login(email, password);
1180+-internal class AuthCodeEntryPane : Spit.Publishing.DialogPane, GLib.Object {
1181+- private Gtk.Box pane_widget = null;
1182+- private Gtk.Button continue_button = null;
1183+- private Gtk.Entry entry = null;
1184+- private Gtk.Label entry_caption = null;
1185+- private Gtk.Label explanatory_text = null;
1186+-
1187+- public signal void proceed(AuthCodeEntryPane sender, string authorization_code);
1188+-
1189+- public AuthCodeEntryPane(Gtk.Builder builder) {
1190+- assert(builder != null);
1191+- assert(builder.get_objects().length() > 0);
1192+-
1193+- explanatory_text = builder.get_object("explanatory_text") as Gtk.Label;
1194+- entry_caption = builder.get_object("entry_caption") as Gtk.Label;
1195+- entry = builder.get_object("entry") as Gtk.Entry;
1196+- continue_button = builder.get_object("continue_button") as Gtk.Button;
1197+-
1198+- pane_widget = builder.get_object("pane_widget") as Gtk.Box;
1199+-
1200+- pane_widget.show_all();
1201+-
1202+- on_entry_contents_changed();
1203+- }
1204+-
1205+- private void on_continue_clicked() {
1206+- proceed(this, entry.get_text());
1207+- }
1208+-
1209+- private void on_entry_contents_changed() {
1210+- continue_button.set_sensitive(entry.text_length > 0);
1211 - }
1212 -
1213 - public Gtk.Widget get_widget() {
1214-- return wrapped;
1215+- return pane_widget;
1216 - }
1217 -
1218 - public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() {
1219 - return Spit.Publishing.DialogPane.GeometryOptions.NONE;
1220 - }
1221--
1222-- public void on_pane_installed() {
1223-- wrapped.go_back.connect(notify_go_back);
1224-- wrapped.login.connect(notify_login);
1225--
1226-- wrapped.installed();
1227+-
1228+- public void on_pane_installed() {
1229+- continue_button.clicked.connect(on_continue_clicked);
1230+- entry.changed.connect(on_entry_contents_changed);
1231 - }
1232--
1233+-
1234 - public void on_pane_uninstalled() {
1235-- wrapped.go_back.disconnect(notify_go_back);
1236-- wrapped.login.disconnect(notify_login);
1237+- continue_button.clicked.disconnect(on_continue_clicked);
1238+- entry.changed.disconnect(on_entry_contents_changed);
1239 - }
1240 -}
1241 -
1242--internal class LegacyCredentialsPane : Gtk.VBox {
1243-- private const string INTRO_MESSAGE = _("Enter the email address and password associated with your Picasa Web Albums account.");
1244-- private const string FAILED_RETRY_MESSAGE = _("Picasa Web Albums didn't recognize the email address and password you entered. To try again, re-enter your email address and password below.");
1245-- private const string NOT_SET_UP_MESSAGE = _("The email address and password you entered correspond to a Google account that isn't set up for use with Picasa Web Albums. You can set up most accounts by using your browser to log into the Picasa Web Albums site at least once. To try again, re-enter your email address and password below.");
1246-- private const string ADDITIONAL_SECURITY_MESSAGE = _("The email address and password you entered correspond to a Google account that has been tagged as requiring additional security. You can clear this tag by using your browser to log into Picasa Web Albums. To try again, re-enter your email address and password below.");
1247--
1248-- private const int UNIFORM_ACTION_BUTTON_WIDTH = 102;
1249-- private const int VERTICAL_SPACE_HEIGHT = 32;
1250-- public const int STANDARD_CONTENT_LABEL_WIDTH = 500;
1251--
1252-- private weak Spit.Publishing.PluginHost host = null;
1253-- private Gtk.Entry email_entry;
1254-- private Gtk.Entry password_entry;
1255-- private Gtk.Button login_button;
1256-- private Gtk.Button go_back_button;
1257-- private string? username = null;
1258--
1259-- public signal void go_back();
1260-- public signal void login(string email, string password);
1261--
1262-- public LegacyCredentialsPane(Spit.Publishing.PluginHost host, CredentialsPane.Mode mode =
1263-- CredentialsPane.Mode.INTRO, string? username = null) {
1264-- this.host = host;
1265-- this.username = username;
1266--
1267-- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));
1268--
1269-- Gtk.Label intro_message_label = new Gtk.Label("");
1270-- intro_message_label.set_line_wrap(true);
1271-- add(intro_message_label);
1272-- intro_message_label.set_size_request(STANDARD_CONTENT_LABEL_WIDTH, -1);
1273-- intro_message_label.set_alignment(0.5f, 0.0f);
1274-- switch (mode) {
1275-- case CredentialsPane.Mode.INTRO:
1276-- intro_message_label.set_text(INTRO_MESSAGE);
1277-- break;
1278--
1279-- case CredentialsPane.Mode.FAILED_RETRY:
1280-- intro_message_label.set_markup("<b>%s</b>\n\n%s".printf(_(
1281-- "Unrecognized User"), FAILED_RETRY_MESSAGE));
1282-- break;
1283--
1284-- case CredentialsPane.Mode.NOT_SET_UP:
1285-- intro_message_label.set_markup("<b>%s</b>\n\n%s".printf(_("Account Not Ready"),
1286-- NOT_SET_UP_MESSAGE));
1287-- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));
1288-- break;
1289--
1290-- case CredentialsPane.Mode.ADDITIONAL_SECURITY:
1291-- intro_message_label.set_markup("<b>%s</b>\n\n%s".printf(_("Additional Security Required"),
1292-- ADDITIONAL_SECURITY_MESSAGE));
1293-- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));
1294-- break;
1295-- }
1296--
1297-- Gtk.Alignment entry_widgets_table_aligner = new Gtk.Alignment(0.5f, 0.5f, 0.0f, 0.0f);
1298-- Gtk.Table entry_widgets_table = new Gtk.Table(3,2, false);
1299-- Gtk.Label email_entry_label = new Gtk.Label.with_mnemonic(_("_Email address:"));
1300-- email_entry_label.set_alignment(0.0f, 0.5f);
1301-- Gtk.Label password_entry_label = new Gtk.Label.with_mnemonic(_("_Password:"));
1302-- password_entry_label.set_alignment(0.0f, 0.5f);
1303-- email_entry = new Gtk.Entry();
1304-- if (username != null)
1305-- email_entry.set_text(username);
1306-- email_entry.changed.connect(on_email_changed);
1307-- password_entry = new Gtk.Entry();
1308-- password_entry.set_visibility(false);
1309-- entry_widgets_table.attach(email_entry_label, 0, 1, 0, 1,
1310-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1311-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1312-- entry_widgets_table.attach(password_entry_label, 0, 1, 1, 2,
1313-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1314-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1315-- entry_widgets_table.attach(email_entry, 1, 2, 0, 1,
1316-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1317-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1318-- entry_widgets_table.attach(password_entry, 1, 2, 1, 2,
1319-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1320-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1321-- go_back_button = new Gtk.Button.with_mnemonic(_("Go _Back"));
1322-- go_back_button.clicked.connect(on_go_back_button_clicked);
1323-- Gtk.Alignment go_back_button_aligner = new Gtk.Alignment(0.0f, 0.5f, 0.0f, 0.0f);
1324-- go_back_button_aligner.add(go_back_button);
1325-- go_back_button.set_size_request(UNIFORM_ACTION_BUTTON_WIDTH, -1);
1326-- login_button = new Gtk.Button.with_mnemonic(_("_Login"));
1327-- login_button.clicked.connect(on_login_button_clicked);
1328-- login_button.set_sensitive(username != null);
1329-- Gtk.Alignment login_button_aligner = new Gtk.Alignment(1.0f, 0.5f, 0.0f, 0.0f);
1330-- login_button_aligner.add(login_button);
1331-- login_button.set_size_request(UNIFORM_ACTION_BUTTON_WIDTH, -1);
1332-- entry_widgets_table.attach(go_back_button_aligner, 0, 1, 2, 3,
1333-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1334-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, VERTICAL_SPACE_HEIGHT);
1335-- entry_widgets_table.attach(login_button_aligner, 1, 2, 2, 3,
1336-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1337-- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, VERTICAL_SPACE_HEIGHT);
1338-- entry_widgets_table_aligner.add(entry_widgets_table);
1339-- add(entry_widgets_table_aligner);
1340--
1341-- email_entry_label.set_mnemonic_widget(email_entry);
1342-- password_entry_label.set_mnemonic_widget(password_entry);
1343--
1344-- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));
1345-- }
1346--
1347-- private void on_login_button_clicked() {
1348-- login(email_entry.get_text(), password_entry.get_text());
1349-- }
1350--
1351-- private void on_go_back_button_clicked() {
1352-- go_back();
1353-- }
1354--
1355-- private void on_email_changed() {
1356-- login_button.set_sensitive(email_entry.get_text() != "");
1357-- }
1358--
1359-- public void installed() {
1360-- host.set_service_locked(false);
1361--
1362-- email_entry.grab_focus();
1363-- password_entry.set_activates_default(true);
1364-- login_button.can_default = true;
1365-- host.set_dialog_default_widget(login_button);
1366+-internal class NotSetUpMessagePane : Spit.Publishing.DialogPane, GLib.Object {
1367+- private Gtk.Box pane_widget = null;
1368+- private Gtk.Button continue_button = null;
1369+-
1370+- public signal void proceed(NotSetUpMessagePane sender);
1371+-
1372+- public NotSetUpMessagePane(Gtk.Builder builder) {
1373+- assert(builder != null);
1374+- assert(builder.get_objects().length() > 0);
1375+-
1376+- continue_button = builder.get_object("continue_button") as Gtk.Button;
1377+- pane_widget = builder.get_object("pane_widget") as Gtk.Box;
1378+-
1379+- pane_widget.show_all();
1380+- }
1381+-
1382+- private void on_continue_clicked() {
1383+- proceed(this);
1384+- }
1385+-
1386+- public Gtk.Widget get_widget() {
1387+- return pane_widget;
1388+- }
1389+-
1390+- public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() {
1391+- return Spit.Publishing.DialogPane.GeometryOptions.NONE;
1392+- }
1393+-
1394+- public void on_pane_installed() {
1395+- continue_button.clicked.connect(on_continue_clicked);
1396+- }
1397+-
1398+- public void on_pane_uninstalled() {
1399+- continue_button.clicked.disconnect(on_continue_clicked);
1400 - }
1401 -}
1402 -
1403 internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object {
1404- private LegacyPublishingOptionsPane wrapped = null;
1405-
1406-
1407+ private class SizeDescription {
1408+ public string name;
1409 Index: shotwell-0.12.90/src/plugins/PublishingInterfaces.vala
1410 ===================================================================
1411---- shotwell-0.12.90.orig/src/plugins/PublishingInterfaces.vala 2012-08-24 09:03:04.000000000 +1200
1412-+++ shotwell-0.12.90/src/plugins/PublishingInterfaces.vala 2012-08-24 15:15:23.971988123 +1200
1413+--- shotwell-0.12.90.orig/src/plugins/PublishingInterfaces.vala 2012-08-24 00:03:04.000000000 +0300
1414++++ shotwell-0.12.90/src/plugins/PublishingInterfaces.vala 2012-08-28 10:25:15.300033478 +0300
1415 @@ -494,6 +494,7 @@
1416 */
1417 public abstract Spit.Publishing.Publisher.MediaType get_publishable_media_type();
1418@@ -1776,8 +1664,8 @@
1419 protected virtual void reserved3() {}
1420 Index: shotwell-0.12.90/src/publishing/PublishingPluginHost.vala
1421 ===================================================================
1422---- shotwell-0.12.90.orig/src/publishing/PublishingPluginHost.vala 2012-08-24 09:03:04.000000000 +1200
1423-+++ shotwell-0.12.90/src/publishing/PublishingPluginHost.vala 2012-08-24 15:15:23.971988123 +1200
1424+--- shotwell-0.12.90.orig/src/publishing/PublishingPluginHost.vala 2012-08-24 00:03:04.000000000 +0300
1425++++ shotwell-0.12.90/src/publishing/PublishingPluginHost.vala 2012-08-28 10:25:15.300033478 +0300
1426 @@ -232,6 +232,13 @@
1427
1428 return report_plugin_upload_progress;
1429@@ -1794,8 +1682,8 @@
1430 }
1431 Index: shotwell-0.12.90/src/publishing/PublishingUI.vala
1432 ===================================================================
1433---- shotwell-0.12.90.orig/src/publishing/PublishingUI.vala 2012-08-24 09:03:04.000000000 +1200
1434-+++ shotwell-0.12.90/src/publishing/PublishingUI.vala 2012-08-24 15:15:23.971988123 +1200
1435+--- shotwell-0.12.90.orig/src/publishing/PublishingUI.vala 2012-08-24 00:03:04.000000000 +0300
1436++++ shotwell-0.12.90/src/publishing/PublishingUI.vala 2012-08-28 10:25:15.300033478 +0300
1437 @@ -296,6 +296,7 @@
1438 Spit.Publishing.Service[] all_services = load_all_services();
1439

Subscribers

People subscribed via source and target branches