Ensure AccountInformation objects always have valid IMAP/SMTP services.
* src/engine/api/geary-engine.vala (Engine): Require a ServiceInformation object for IMAP and SMTP when creating orphan info objects. Update call sites. * src/client/accounts/account-manager.vala (AccountManager): provide factory methods for constructing local service info objects. Use these when re-constituting accounts. Use a singleton SecretMediator object instance as a bonus. * src/client/accounts/add-edit-page.vala (AddEditPage): Get ServiceInformation objects from the account manager, pass an instance of GearyApplication through so it has access to the manager. Update call chains back to GearyController to pass the app instance through.
This commit is contained in:
parent
91e85a6647
commit
4fdeb9db47
8 changed files with 117 additions and 69 deletions
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
// Add or edit an account. Used with AccountDialog.
|
||||
public class AccountDialogAddEditPane : AccountDialogPane {
|
||||
public AddEditPage add_edit_page { get; private set; default = new AddEditPage(); }
|
||||
|
||||
public AddEditPage add_edit_page { get; private set; }
|
||||
private Gtk.ButtonBox button_box = new Gtk.ButtonBox(Gtk.Orientation.HORIZONTAL);
|
||||
private Gtk.Button ok_button = new Gtk.Button.with_mnemonic(Stock._OK);
|
||||
private Gtk.Button cancel_button = new Gtk.Button.with_mnemonic(Stock._CANCEL);
|
||||
|
|
@ -19,9 +20,11 @@ public class AccountDialogAddEditPane : AccountDialogPane {
|
|||
|
||||
public signal void edit_alternate_emails(string id);
|
||||
|
||||
public AccountDialogAddEditPane(Gtk.Stack stack) {
|
||||
public AccountDialogAddEditPane(GearyApplication application, Gtk.Stack stack) {
|
||||
base(stack);
|
||||
|
||||
|
||||
this.add_edit_page = new AddEditPage(application);
|
||||
|
||||
button_box.set_layout(Gtk.ButtonBoxStyle.END);
|
||||
button_box.expand = false;
|
||||
button_box.spacing = 6;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public class AccountDialog : Gtk.Dialog {
|
|||
|
||||
// Add pages to stack.
|
||||
account_list_pane = new AccountDialogAccountListPane(application, stack);
|
||||
add_edit_pane = new AccountDialogAddEditPane(stack);
|
||||
add_edit_pane = new AccountDialogAddEditPane(application, stack);
|
||||
spinner_pane = new AccountDialogSpinnerPane(stack);
|
||||
remove_confirm_pane = new AccountDialogRemoveConfirmPane(stack);
|
||||
remove_fail_pane = new AccountDialogRemoveFailPane(stack);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@
|
|||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
errordomain AccountError {
|
||||
INVALID;
|
||||
}
|
||||
|
||||
public class AccountManager : GLib.Object {
|
||||
|
||||
|
||||
|
|
@ -11,6 +15,8 @@ public class AccountManager : GLib.Object {
|
|||
private GLib.File user_config_dir;
|
||||
private GLib.File user_data_dir;
|
||||
|
||||
private Geary.CredentialsMediator libsecret;
|
||||
|
||||
|
||||
public AccountManager(Geary.Engine engine,
|
||||
GLib.File user_config_dir,
|
||||
|
|
@ -18,6 +24,13 @@ public class AccountManager : GLib.Object {
|
|||
this.engine = engine;
|
||||
this.user_config_dir = user_config_dir;
|
||||
this.user_data_dir = user_data_dir;
|
||||
|
||||
this.libsecret = new SecretMediator();
|
||||
}
|
||||
|
||||
public Geary.ServiceInformation new_libsecret_service(Geary.Service service,
|
||||
Geary.CredentialsMethod method) {
|
||||
return new LocalServiceInformation(service, libsecret);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -101,20 +114,13 @@ public class AccountManager : GLib.Object {
|
|||
provider = Geary.CredentialsProvider.from_string(Geary.Config.get_string_value(key_file, Geary.Config.GROUP, Geary.Config.CREDENTIALS_PROVIDER_KEY, Geary.CredentialsProvider.LIBSECRET.to_string()));
|
||||
method = Geary.CredentialsMethod.from_string(Geary.Config.get_string_value(key_file, Geary.Config.GROUP, Geary.Config.CREDENTIALS_METHOD_KEY, Geary.CredentialsMethod.PASSWORD.to_string()));
|
||||
switch (provider) {
|
||||
case Geary.CredentialsProvider.LIBSECRET:
|
||||
mediator = new SecretMediator();
|
||||
imap_information = new LocalServiceInformation(
|
||||
Geary.Service.IMAP, mediator
|
||||
);
|
||||
smtp_information = new LocalServiceInformation(
|
||||
Geary.Service.SMTP, mediator
|
||||
);
|
||||
break;
|
||||
default:
|
||||
mediator = null;
|
||||
imap_information = null;
|
||||
smtp_information = null;
|
||||
break;
|
||||
case Geary.CredentialsProvider.LIBSECRET:
|
||||
imap_information = new_libsecret_service(Geary.Service.IMAP, method);
|
||||
smtp_information = new_libsecret_service(Geary.Service.SMTP, method);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new AccountError.INVALID("Unhandled credentials provider");
|
||||
}
|
||||
|
||||
Geary.AccountInformation info = new Geary.AccountInformation(
|
||||
|
|
|
|||
|
|
@ -154,7 +154,9 @@ public class AddEditPage : Gtk.Box {
|
|||
SSL = 1,
|
||||
STARTTLS = 2
|
||||
}
|
||||
|
||||
|
||||
private GearyApplication application;
|
||||
|
||||
private PageMode mode = PageMode.WELCOME;
|
||||
|
||||
private Gtk.Widget container_widget;
|
||||
|
|
@ -219,12 +221,13 @@ public class AddEditPage : Gtk.Box {
|
|||
public signal void size_changed();
|
||||
|
||||
public signal void edit_alternate_emails();
|
||||
|
||||
public AddEditPage() {
|
||||
|
||||
public AddEditPage(GearyApplication application) {
|
||||
Object(orientation: Gtk.Orientation.VERTICAL, spacing: 4);
|
||||
|
||||
Gtk.Builder builder = GearyApplication.instance.create_builder("login.glade");
|
||||
|
||||
this.application = application;
|
||||
|
||||
Gtk.Builder builder = GioUtil.create_builder("login.glade");
|
||||
|
||||
// Primary container.
|
||||
container_widget = (Gtk.Widget) builder.get_object("container");
|
||||
pack_start(container_widget);
|
||||
|
|
@ -272,7 +275,7 @@ public class AddEditPage : Gtk.Box {
|
|||
textview_email_signature = new Gtk.TextView();
|
||||
edit_window.add(textview_email_signature);
|
||||
|
||||
preview_webview = new ClientWebView(GearyApplication.instance.config);
|
||||
preview_webview = new ClientWebView(application.config);
|
||||
|
||||
Gtk.ScrolledWindow preview_window = new Gtk.ScrolledWindow(null, null);
|
||||
preview_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
|
||||
|
|
@ -665,7 +668,7 @@ public class AddEditPage : Gtk.Box {
|
|||
// encountered validation errors. So we need to deal with
|
||||
// both cases.
|
||||
try {
|
||||
info = Geary.Engine.instance.get_account(this.id);
|
||||
info = this.application.engine.get_account(this.id);
|
||||
} catch (Error err) {
|
||||
// id was for an orphan account
|
||||
}
|
||||
|
|
@ -673,8 +676,19 @@ public class AddEditPage : Gtk.Box {
|
|||
|
||||
if (info == null) {
|
||||
// New account
|
||||
Geary.ServiceInformation imap =
|
||||
this.application.controller.account_manager.new_libsecret_service(
|
||||
Geary.Service.IMAP,
|
||||
Geary.CredentialsMethod.PASSWORD
|
||||
);
|
||||
Geary.ServiceInformation smtp =
|
||||
this.application.controller.account_manager.new_libsecret_service(
|
||||
Geary.Service.SMTP,
|
||||
Geary.CredentialsMethod.PASSWORD
|
||||
);
|
||||
|
||||
try {
|
||||
info = Geary.Engine.instance.create_orphan_account();
|
||||
info = this.application.engine.create_orphan_account(imap, smtp);
|
||||
} catch (Error err) {
|
||||
debug("Unable to create account %s for %s: %s",
|
||||
this.id, this.email_address, err.message);
|
||||
|
|
|
|||
|
|
@ -6,16 +6,20 @@
|
|||
|
||||
// Displays a dialog for collecting the user's login data.
|
||||
public class LoginDialog : Gtk.Dialog {
|
||||
|
||||
|
||||
private Gtk.Button ok_button;
|
||||
private Gtk.Button cancel_button;
|
||||
private AddEditPage page = new AddEditPage();
|
||||
private AddEditPage page;
|
||||
private AccountSpinnerPage spinner_page = new AccountSpinnerPage();
|
||||
|
||||
public LoginDialog() {
|
||||
|
||||
public LoginDialog(GearyApplication application) {
|
||||
Object();
|
||||
set_type_hint(Gdk.WindowTypeHint.DIALOG);
|
||||
set_size_request(450, -1); // Sets min width.
|
||||
|
||||
|
||||
this.page = new AddEditPage(application);
|
||||
|
||||
page.margin = 5;
|
||||
spinner_page.margin = 5;
|
||||
get_content_area().pack_start(page, true, true, 0);
|
||||
|
|
@ -42,12 +46,13 @@ public class LoginDialog : Gtk.Dialog {
|
|||
|
||||
on_info_changed();
|
||||
}
|
||||
|
||||
public LoginDialog.from_account_information(Geary.AccountInformation initial_account_information) {
|
||||
this();
|
||||
set_account_information(initial_account_information);
|
||||
|
||||
public LoginDialog.from_account_information(GearyApplication application,
|
||||
Geary.AccountInformation initial) {
|
||||
this(application);
|
||||
set_account_information(initial);
|
||||
}
|
||||
|
||||
|
||||
public void set_account_information(Geary.AccountInformation info,
|
||||
Geary.Engine.ValidationResult result = Geary.Engine.ValidationResult.OK) {
|
||||
page.set_account_information(info, result);
|
||||
|
|
|
|||
|
|
@ -900,7 +900,7 @@ public class GearyController : Geary.BaseObject {
|
|||
Geary.AccountInformation? new_info = old_info;
|
||||
if (login_dialog == null) {
|
||||
// Create here so we know GTK is initialized.
|
||||
login_dialog = new LoginDialog();
|
||||
login_dialog = new LoginDialog(this.application);
|
||||
} else if (!login_dialog.get_visible()) {
|
||||
// If the dialog has been dismissed, exit here.
|
||||
this.application.exit();
|
||||
|
|
|
|||
|
|
@ -208,7 +208,9 @@ public class Geary.Engine : BaseObject {
|
|||
* Throws an error if the engine has not been opened or if an
|
||||
* invalid account id is generated.
|
||||
*/
|
||||
public AccountInformation create_orphan_account() throws Error {
|
||||
public AccountInformation create_orphan_account(ServiceInformation imap,
|
||||
ServiceInformation smtp)
|
||||
throws GLib.Error {
|
||||
check_opened();
|
||||
|
||||
// We might want to allow the client to specify the id, but
|
||||
|
|
@ -233,7 +235,7 @@ public class Geary.Engine : BaseObject {
|
|||
if (this.accounts.has_key(id))
|
||||
throw new EngineError.ALREADY_EXISTS("Account %s already exists", id);
|
||||
|
||||
return new AccountInformation(id, null, null);
|
||||
return new AccountInformation(id, imap, smtp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -63,19 +63,31 @@ class Geary.EngineTest : TestCase {
|
|||
|
||||
public void create_orphan_account() throws Error {
|
||||
try {
|
||||
AccountInformation info = this.engine.create_orphan_account();
|
||||
AccountInformation info = this.engine.create_orphan_account(
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
);
|
||||
assert(info.id == "account_01");
|
||||
this.engine.add_account(info, true);
|
||||
|
||||
info = this.engine.create_orphan_account();
|
||||
info = this.engine.create_orphan_account(
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
);
|
||||
assert(info.id == "account_02");
|
||||
this.engine.add_account(info, true);
|
||||
|
||||
info = this.engine.create_orphan_account();
|
||||
info = this.engine.create_orphan_account(
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
);
|
||||
assert(info.id == "account_03");
|
||||
this.engine.add_account(info, true);
|
||||
|
||||
info = this.engine.create_orphan_account();
|
||||
info = this.engine.create_orphan_account(
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
);
|
||||
assert(info.id == "account_04");
|
||||
} catch (Error err) {
|
||||
print("\nerr: %s\n", err.message);
|
||||
|
|
@ -84,36 +96,42 @@ class Geary.EngineTest : TestCase {
|
|||
}
|
||||
|
||||
public void create_orphan_account_with_legacy() throws Error {
|
||||
try {
|
||||
this.engine.add_account(
|
||||
new AccountInformation(
|
||||
"foo",
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
),
|
||||
true
|
||||
);
|
||||
this.engine.add_account(
|
||||
new AccountInformation(
|
||||
"foo",
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
AccountInformation info = this.engine.create_orphan_account();
|
||||
assert(info.id == "account_01");
|
||||
this.engine.add_account(info, true);
|
||||
AccountInformation info = this.engine.create_orphan_account(
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
);
|
||||
assert(info.id == "account_01");
|
||||
this.engine.add_account(info, true);
|
||||
|
||||
assert(this.engine.create_orphan_account().id == "account_02");
|
||||
info = this.engine.create_orphan_account(
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
);
|
||||
assert(info.id == "account_02");
|
||||
|
||||
this.engine.add_account(
|
||||
new AccountInformation(
|
||||
"bar",
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
),
|
||||
true
|
||||
);
|
||||
this.engine.add_account(
|
||||
new AccountInformation(
|
||||
"bar",
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
assert(this.engine.create_orphan_account().id == "account_02");
|
||||
} catch (Error err) {
|
||||
print("\nerr: %s\n", err.message);
|
||||
assert_not_reached();
|
||||
}
|
||||
info = this.engine.create_orphan_account(
|
||||
new MockServiceInformation(),
|
||||
new MockServiceInformation()
|
||||
);
|
||||
assert(info.id == "account_02");
|
||||
}
|
||||
|
||||
private void delete(File parent) throws Error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue