Commit 762ad6f0 authored by Cédric Bellegarde's avatar Cédric Bellegarde

Move password management in extension

parent 750b3e6e
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkGrid" id="widget">
......@@ -24,31 +24,6 @@
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="username">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="password">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="visibility">False</property>
<property name="invisible_char">*</property>
<property name="input_purpose">password</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Save</property>
......@@ -59,7 +34,7 @@
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">4</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
......@@ -96,11 +71,5 @@
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</interface>
......@@ -677,9 +677,9 @@ class Application(Gtk.Application):
if views:
view = views.pop(0)
page_id = view.webview.get_page_id()
self.helper.call("FormsFilled",
self.helper.call("FormsFilled", page_id,
GLib.Variant("(i)", (page_id,)),
self.__on_forms_filled, page_id, window, views)
self.__on_forms_filled, window, views)
else:
self.__close_window(window)
......
......@@ -246,9 +246,9 @@ class Container(Gtk.Overlay):
@param view as View
"""
page_id = view.webview.get_page_id()
El().helper.call("FormsFilled",
El().helper.call("FormsFilled", page_id,
GLib.Variant("(i)", (page_id,)),
self.__on_forms_filled, page_id, view)
self.__on_forms_filled, view)
def close_view(self, view):
"""
......
......@@ -13,6 +13,7 @@
from gi.repository import Gio, GLib
from urllib.parse import urlparse
from uuid import uuid4
from eolie.define import PROXY_BUS, PROXY_PATH
from eolie.list import LinkedList
......@@ -91,10 +92,18 @@ class ProxyExtension(Server):
</method>
<method name="SetNextForm">
</method>
<method name="GetAuthForms">
<method name="FormSubmitted">
<arg type="aas" name="forms" direction="in" />
<arg type="s" name="uri" direction="in" />
<arg type="s" name="form_uri" direction="in" />
<arg type="i" name="page_id" direction="in" />
<arg type="as" name="results" direction="out" />
</method>
<method name="SaveCredentials">
<arg type="s" name="uuid" direction="in" />
<arg type="s" name="user_form_name" direction="in" />
<arg type="s" name="pass_form_name" direction="in" />
<arg type="s" name="uri" direction="in" />
<arg type="s" name="form_uri" direction="in" />
</method>
<method name="SetAuthForms">
<arg type="s" name="username" direction="in" />
......@@ -124,6 +133,13 @@ class ProxyExtension(Server):
<signal name='InputMouseDown'>
<arg type="as" name="forms" direction="out" />
</signal>
<signal name='AskSaveCredentials'>
<arg type="s" name="uuid" direction="out" />
<arg type="s" name="user_form_value" direction="out" />
<arg type="s" name="uri" direction="out" />
<arg type="s" name="form_uri" direction="out" />
<arg type="i" name="page_id" direction="out" />
</signal>
</interface>
</node>
'''
......@@ -141,7 +157,9 @@ class ProxyExtension(Server):
self.__password_forms = []
self.__listened_forms = []
self.__send_requests = []
self.__pending_credentials = None
self.__current_uri = None
self.__helper = PasswordsHelper()
extension.connect("page-created", self.__on_page_created)
self.__bus = None
......@@ -159,10 +177,12 @@ class ProxyExtension(Server):
return True
return False
def GetAuthForms(self, forms, page_id):
def FormSubmitted(self, forms, uri, form_uri, page_id):
"""
Get password forms for page id
Check for password in org.Freedesktop.Secrets
@param forms as [(str, str)]
@param uri as str
@param form_uri as str
@param page id as int
@return (username_form, password_form) as (str, str)
"""
......@@ -172,10 +192,10 @@ class ProxyExtension(Server):
self.__forms.update_inputs_list(page)
if page is None:
return ("", "", "", "")
user_form_name = ""
user_form_value = ""
pass_form_name = ""
pass_form_value = ""
user_form_name = None
user_form_value = None
pass_form_name = None
pass_form_value = None
for (name, value) in forms:
if self.__forms.is_input(name, "password", page):
pass_form_name = name
......@@ -183,13 +203,74 @@ class ProxyExtension(Server):
else:
user_form_name = name
user_form_value = value
return (user_form_name,
user_form_value,
pass_form_name,
pass_form_value)
if user_form_value is not None and\
pass_form_value is not None and\
user_form_value != pass_form_value:
self.__pending_credentials = (user_form_name,
user_form_value,
pass_form_name,
pass_form_value,
uri,
form_uri)
self.__helper.get(form_uri, user_form_name,
pass_form_name, self.__on_get_password,
user_form_name, user_form_value,
pass_form_name, pass_form_value,
uri,
page_id)
except Exception as e:
print("ProxyExtension::FormSubmitted():", e)
def SaveCredentials(self, uuid, user_form_name,
pass_form_name, uri, form_uri):
"""
Save credentials to org.freedesktop.Secrets
@param uuid as str
@param user_form_name as str
@param pass_form_name as str
@param uri as str
@param form_uri as str
"""
print(self.__pending_credentials, uuid, user_form_name)
if self.__pending_credentials is None:
return
try:
(_user_form_name, user_form_value,
_pass_form_name, pass_form_value,
_uri, _form_uri) = self.__pending_credentials
if user_form_name != _user_form_name or\
pass_form_name != _pass_form_name or\
uri != _uri or\
form_uri != _form_uri:
return
parsed = urlparse(uri)
parsed_form_uri = urlparse(form_uri)
uri = "%s://%s" % (parsed.scheme, parsed.netloc)
form_uri = "%s://%s" % (parsed_form_uri.scheme,
parsed_form_uri.netloc)
if not uuid:
uuid = str(uuid4())
self.__helper.store(user_form_name,
user_form_value,
pass_form_name,
pass_form_value,
uri,
form_uri,
uuid,
None)
else:
self.__helper.clear(uuid,
self.__helper.store,
user_form_name,
user_form_value,
pass_form_name,
pass_form_value,
uri,
form_uri,
uuid,
None)
except Exception as e:
print("ProxyExtension::GetAuthForms():", e)
return ("", "", "", "")
print("ProxyExtension::SaveCredentials():", e)
def SetAuthForms(self, userform, username, page_id):
"""
......@@ -204,14 +285,13 @@ class ProxyExtension(Server):
# Search form
for form_input in self.__forms.get_form_inputs(page):
if form_input["username"].get_name() == userform:
helper = PasswordsHelper()
helper.get(form_input["uri"],
userform,
form_input["password"].get_name(),
self.__forms.set_input_forms,
page,
form_input,
username)
self.__helper.get(form_input["uri"],
userform,
form_input["password"].get_name(),
self.__forms.set_input_forms,
page,
form_input,
username)
return
except Exception as e:
print("ProxyExtension::SetAuthForms():", e)
......@@ -523,3 +603,39 @@ class ProxyExtension(Server):
self.__current_uri = uri
self.__send_requests = []
self.__send_requests.append(request.get_uri())
def __on_get_password(self, attributes, password, form_uri, index, count,
user_form_name, user_form_value, pass_form_name,
pass_form_value, uri, page_id):
"""
Set user_form_name/pass_form_name input
@param attributes as {}
@param password as str
@param form_uri as str
@param index as int
@param count as int
@param user_form_name as str
@param user_form_value as str
@param pass_form_name as str
@param pass_form_value as str
@param uri as str
@param page_id as int
"""
try:
uuid = ""
if attributes is not None:
if password == pass_form_value:
return
else:
uuid = attributes["uuid"]
args = (uuid, user_form_name, user_form_value,
pass_form_name, uri, form_uri, page_id)
variant = GLib.Variant.new_tuple(GLib.Variant("(ssssssi)", args))
self.__bus.emit_signal(
None,
PROXY_PATH,
self.__proxy_bus,
"AskSaveCredentials",
variant)
except Exception as e:
print("ProxyExtension::__on_get_password()", e)
......@@ -23,13 +23,13 @@ class DBusHelper:
def __init__(self):
self.__signals = {}
def call(self, call, dbus_args, callback, page_id, *args):
def call(self, call, page_id, dbus_args=None, callback=None, *args):
"""
Call function
@param call as str
@param page_id as int
@param dbus_args as GLib.Variant()/None
@param callback as function
@param page_id as int
"""
try:
bus = El().get_dbus_connection()
......
......@@ -64,10 +64,8 @@ class FormMenu(Gio.Menu):
@param GVariant
@param attributes as {}
"""
El().helper.call("SetAuthForms",
El().helper.call("SetAuthForms", self.__page_id,
GLib.Variant("(ssi)",
(attributes["userform"],
attributes["login"],
self.__page_id)),
None,
self.__page_id)
self.__page_id)))
......@@ -31,9 +31,9 @@ class VideosMenu(Gio.Menu):
"""
Gio.Menu.__init__(self)
self.__window = window
El().helper.call("GetVideos",
El().helper.call("GetVideos", page_id,
GLib.Variant("(i)", (page_id,)),
self.__on_get_videos, page_id)
self.__on_get_videos)
#######################
# PRIVATE #
......
......@@ -10,11 +10,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from gi.repository import Gtk
from gi.repository import Gtk, GLib
from gettext import gettext as _
from urllib.parse import urlparse
from uuid import uuid4
from eolie.helper_passwords import PasswordsHelper
from eolie.define import El
......@@ -25,16 +24,17 @@ class CredentialsPopover(Gtk.Popover):
Tell user to save form credentials
"""
def __init__(self, user_form_name, user_form_value, pass_form_name,
pass_form_value, uri, form_uri, window):
def __init__(self, uuid, user_form_name, user_form_value, pass_form_name,
uri, form_uri, page_id, window):
"""
Init popover
@param uuid as str
@param user_form_name as str
@param user_form_value as str
@param pass_form_name as str
@param pass_form_value as str
@param uri as str
@param form_uri as str
@param page_id as int
@param window as Window
"""
Gtk.Popover.__init__(self)
......@@ -44,18 +44,18 @@ class CredentialsPopover(Gtk.Popover):
self.__user_form_name = user_form_name
self.__user_form_value = user_form_value
self.__pass_form_name = pass_form_name
self.__pass_form_value = pass_form_value
self.__uri = uri
self.__form_uri = form_uri
self.__uuid = None
self.__uuid = uuid
self.__page_id = page_id
builder = Gtk.Builder()
builder.add_from_resource('/org/gnome/Eolie/PopoverCredentials.ui')
builder.connect_signals(self)
self.__label = builder.get_object('label')
parsed = urlparse(uri)
builder.get_object('uri').set_text(parsed.netloc)
builder.get_object('username').set_text(user_form_value)
builder.get_object('password').set_text(pass_form_value)
if uuid:
self.__label.set_text(_("Do you want to modify this password?"))
self.add(builder.get_object('widget'))
#######################
......@@ -66,81 +66,51 @@ class CredentialsPopover(Gtk.Popover):
Save user_form_name and pass_form_name
@param button as Gtk.Button
"""
try:
parsed = urlparse(self.__uri)
parsed_form_uri = urlparse(self.__form_uri)
uri = "%s://%s" % (parsed.scheme, parsed.netloc)
form_uri = "%s://%s" % (parsed_form_uri.scheme,
parsed_form_uri.netloc)
if self.__uuid is None:
self.__uuid = str(uuid4())
self.__helper.store(self.__user_form_name,
self.__user_form_value,
self.__pass_form_name,
self.__pass_form_value,
uri,
form_uri,
self.__uuid,
None)
else:
self.__helper.clear(self.__uuid,
self.__helper.store,
self.__user_form_name,
self.__user_form_value,
self.__pass_form_name,
self.__pass_form_value,
uri,
form_uri,
self.__uuid,
None)
if El().sync_worker is not None:
El().sync_worker.push_password(self.__user_form_name,
self.__user_form_value,
self.__pass_form_name,
self.__pass_form_value,
uri,
form_uri,
self.__uuid)
self.destroy()
except Exception as e:
print("CredentialsPopover::_on_save_clicked()", e)
def popup(self):
"""
Overwrite popup
"""
self.__helper.get(self.__uri, self.__user_form_name,
self.__pass_form_name, self.__on_get_password,)
El().helper.call("SaveCredentials", self.__page_id,
GLib.Variant("(sssss)",
(self.__uuid, self.__user_form_name,
self.__pass_form_name, self.__uri,
self.__form_uri)),
self.__on_save_credentials,
self.__form_uri,
self.__user_form_name,
self.__pass_form_name)
self.destroy()
#######################
# PRIVATE #
#######################
def __on_get_password(self, attributes, password, uri, index, count):
def __on_get_password(self, attributes, password, form_uri, index, count):
"""
Set user_form_name/pass_form_name input
Push credential to sync
@param attributes as {}
@param password as str
@param uri as str
@param form_uri as str
@param index as int
@param count as int
"""
try:
# No saved pass_form_name
if attributes is None:
Gtk.Popover.popup(self)
# pass_form_name saved and unchanged
elif attributes["login"] == self.__user_form_value:
if password == self.__pass_form_value:
self.emit("closed")
# Prevent popover to be displayed
self.set_relative_to(None)
# login/password changed
else:
Gtk.Popover.popup(self)
self.__uuid = attributes["uuid"]
self.__label.set_text(_(
"Do you want to modify this password?"))
else:
Gtk.Popover.popup(self)
if attributes is not None and El().sync_worker is not None:
El().sync_worker.push_password(attributes["userform"],
attributes["login"],
attributes["passform"],
password,
attributes["hostname"],
attributes["formSubmitURL"],
attributes["uuid"])
except Exception as e:
print("CredentialsPopover::__on_get_password()", e)
print("CredentialsPopover::__on_get_password():", e)
def __on_save_credentials(self, source, result, form_uri,
user_form_name, pass_form_name):
"""
Get password and push credential to sync
@param source as GObject.Object
@param result as Gio.AsyncResult
@param form_uri as str
@param user_form_name as str
@param pass_form_name as str
"""
helper = PasswordsHelper()
helper.get(form_uri, user_form_name,
pass_form_name, self.__on_get_password)
......@@ -104,9 +104,9 @@ class ImagesPopover(Gtk.Popover):
self.__button = builder.get_object("button")
self.add(widget)
if Gio.NetworkMonitor.get_default().get_network_available():
El().helper.call("GetImages",
El().helper.call("GetImages", page_id,
GLib.Variant("(i)", (page_id,)),
self.__on_get_images, page_id)
self.__on_get_images)
(width, height) = El().active_window.get_size()
self.set_size_request(width / 2, height / 1.5)
self.connect("closed", self.__on_closed)
......@@ -144,13 +144,13 @@ class ImagesPopover(Gtk.Popover):
self.__links = button.get_active()
if Gio.NetworkMonitor.get_default().get_network_available():
if button.get_active():
El().helper.call("GetImageLinks",
El().helper.call("GetImageLinks", self.__page_id,
GLib.Variant("(i)", (self.__page_id,)),
self.__on_get_images, self.__page_id)
self.__on_get_images)
else:
El().helper.call("GetImages",
El().helper.call("GetImages", self.__page_id,
GLib.Variant("(i)", (self.__page_id,)),
self.__on_get_images, self.__page_id)
self.__on_get_images)
#######################
# PRIVATE #
......
......@@ -332,22 +332,25 @@ class ToolbarTitle(Gtk.Bin):
else:
self.__indicator_stack.hide()
def show_password(self, user_form_name, user_form_value, pass_form_name,
pass_form_value, uri, form_uri):
def show_password(self, uuid, user_form_name, user_form_value,
pass_form_name, uri, form_uri, page_id):
"""
Show a popover allowing user to save password
@param uuid as str
@param user_form_name as str
@param user_form_value as str
@param pass_form_name as str
@param pass_form_value as str
@param uri as str
@param form_uri as str
@param page_id as int
"""
from eolie.popover_credentials import CredentialsPopover
popover = CredentialsPopover(user_form_name, user_form_value,
pass_form_name, pass_form_value,
popover = CredentialsPopover(uuid, user_form_name, user_form_value,
pass_form_name,
uri,
form_uri,
page_id,
self.__window)
popover.set_relative_to(self.__entry)
popover.set_pointing_to(self.__entry.get_icon_area(
......
......@@ -189,9 +189,9 @@ class View(Gtk.Overlay):
page_id = self.webview.get_page_id()
if event.state & Gdk.ModifierType.CONTROL_MASK:
if event.keyval == Gdk.KEY_z:
El().helper.call("SetPreviousForm", None, None, page_id)
El().helper.call("SetPreviousForm", page_id)
elif event.keyval == Gdk.KEY_Z:
El().helper.call("SetNextForm", None, None, page_id)
El().helper.call("SetNextForm", page_id)
def __on_close(self, webview):
"""
......
......@@ -82,7 +82,6 @@ class WebViewDBusSignals:
@param webview as WebKit2.WebView
@param request as WebKit2.FormSubmissionRequest
"""
uri = self._navigation_uri
if self.ephemeral or not El().settings.get_value("remember-passwords"):
return
fields = request.get_text_fields()
......@@ -95,36 +94,10 @@ class WebViewDBusSignals:
if name and value:
forms.append((name, value))
page_id = webview.get_page_id()
El().helper.call("GetAuthForms",
GLib.Variant("(aasi)", (forms, page_id)),
self.__on_get_forms, page_id, request, uri)
def __on_get_forms(self, source, result, request, form_uri):
"""
Set forms value
@param source as GObject.Object
@param result as Gio.AsyncResult
@param request as WebKit2.FormSubmissionRequest
@param form_uri as str
"""
try:
(user_form_name,
user_form_value,
pass_form_name,
pass_form_value) = source.call_finish(result)[0]
if user_form_name and pass_form_name and\
user_form_value != pass_form_value:
self._window.close_popovers()
self._window.toolbar.title.show_password(
user_form_name,
user_form_value,
pass_form_name,
pass_form_value,
self.uri,
form_uri)
request.submit()
except Exception as e:
print("WebViewDBusSignals::__on_get_forms():", e)
form_uri = self._navigation_uri
El().helper.call("FormSubmitted", page_id,
GLib.Variant("(aasssi)",
(forms, self.uri, form_uri, page_id)))
def __on_signal(self, signal, params):
"""
......@@ -132,8 +105,22 @@ class WebViewDBusSignals:
@param signal as str
@params as []
"""
self_page_id = self.get_page_id()
if signal == "UnsecureFormFocused":
self._window.toolbar.title.show_input_warning(self)
elif signal == "AskSaveCredentials":
(uuid, user_form_name, user_form_value,
pass_form_name, uri, form_uri, page_id) = params[0]
if self_page_id == page_id:
self._window.close_popovers()
self._window.toolbar.title.show_password(
uuid,
user_form_name,
user_form_value,
pass_form_name,
uri,
form_uri,
page_id)
elif signal == "InputMouseDown":
if self._last_click_time:
userform = params[0]
......
......@@ -138,7 +138,5 @@ class WebViewJsSignals:
"""
self.__js_timeout_id = None
page_id = self.get_page_id()
El().helper.call("SetCredentials",
GLib.Variant("(i)", (page_id,)),
None,
page_id)
El().helper.call("SetCredentials", page_id,
GLib.Variant("(i)", (page_id,)))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment