Merge ~osomon/oxide:autofill-profiles-management into oxide:master
- Git
- lp:~osomon/oxide
- autofill-profiles-management
- Merge into master
Status: | Needs review | ||||||||
---|---|---|---|---|---|---|---|---|---|
Proposed branch: | ~osomon/oxide:autofill-profiles-management | ||||||||
Merge into: | oxide:master | ||||||||
Prerequisite: | ~osomon/oxide:autofill | ||||||||
Diff against target: |
1095 lines (+773/-7) 15 files modified
qt/core/browser/oxide_qt_web_context.cc (+144/-1) qt/core/browser/oxide_qt_web_context.h (+13/-1) qt/core/glue/oxide_qt_web_context_proxy.h (+8/-0) qt/core/glue/oxide_qt_web_context_proxy_client.h (+3/-1) qt/qmlplugin/oxide.qmltypes (+32/-0) qt/qmlplugin/oxide_qml_plugin.cc (+4/-0) qt/quick/CMakeLists.txt (+2/-1) qt/quick/api/oxideqquickautofillprofiles.cc (+193/-0) qt/quick/api/oxideqquickautofillprofiles.h (+68/-0) qt/quick/api/oxideqquickautofillprofiles_p.h (+80/-0) qt/quick/api/oxideqquickwebcontext.cc (+21/-2) qt/quick/api/oxideqquickwebcontext.h (+4/-0) qt/quick/api/oxideqquickwebcontext_p.h (+7/-1) qt/tests/qmltests/api/tst_WebContext_autofillProfiles.qml (+141/-0) qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml (+53/-0) |
||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Oxide Developers | Pending | ||
Review via email:
|
Commit message
New API on WebContext for autofill profiles management.
Description of the change
- 2861ed9... by Olivier Tilloy
-
Ensure that the autofill profiles have been loaded before accessing them.
- f4c0d6a... by Olivier Tilloy
-
Reduce the height of the autofill entries.
- ef4fb16... by Olivier Tilloy
-
Preview autofill entry under mouse cursor.
- f943678... by Olivier Tilloy
-
Highlight currently selected suggestion.
- 06c7bad... by Olivier Tilloy
-
Simplify focus handling.
- 818af21... by Olivier Tilloy
-
Fix FTBFS.
- c60a7e8... by Olivier Tilloy
-
Handle validation when no suggestion is selected.
- daa6b3b... by Olivier Tilloy
-
Add a unit test for autofill popup destruction.
- 5859240... by Olivier Tilloy
-
Ensure unit tests are locale-independent.
- 1c3531f... by Olivier Tilloy
-
Fix build errors when rebased on latest master.
- 67d903b... by Olivier Tilloy
-
Always use an InMemoryPrefStore.
Persisting the value of OxideQQuickWebC
ontext: :autofillEnable d would be
inconsistent with every other setting exposed by the API
(eg, we don't persist popupBlockerEnabled or doNotTrackEnabled). - a508ed9... by Olivier Tilloy
-
Move CreateAutofillPopup to WebContentsClient.
- d9ff4e9... by Olivier Tilloy
-
Bump version for new WebContext API to 1.23.
- bfac2c5... by Olivier Tilloy
-
Drop default case as there's already a branch for every value.
- 8d05925... by Olivier Tilloy
-
Do not modify oxide::
ContentClient to access the application locale. Instead, expose the application locale as a new method on BrowserPlatform
Integration. - d613e81... by Olivier Tilloy
-
Marked a private helper private.
- e6dde29... by Olivier Tilloy
-
Ensure that autofill works in incognito mode, as expected.
- 559bd23... by Olivier Tilloy
-
Add tests for autofill in incognito webviews.
- cb4b1d5... by Olivier Tilloy
-
Make WebAutofillPopu
pHost:: Init not return anything, for consistency. - d4ec246... by Olivier Tilloy
-
Remove redundant std::move().
- 9b8a3c0... by Olivier Tilloy
-
Rename methods to start with an uppercase letter, for consistency with newly-written code.
- 7b47f20... by Olivier Tilloy
-
Take timeout into account.
- 75307e9... by Olivier Tilloy
-
Do not depend on the omnibox component in release builds.
- f85f34f... by Olivier Tilloy
-
Rename files for consistency with newly-added code.
- ea88035... by Olivier Tilloy
-
Remove unused references to gfx::NativeView (always null) in AutofillPopupCo
ntroller. - 0c5a23f... by Olivier Tilloy
-
Remove unused method.
- 867131f... by Olivier Tilloy
-
Make ownership of AutofillPopupCo
ntroller explicit. - becd872... by Olivier Tilloy
-
Updated test.
- 3f0f3aa... by Olivier Tilloy
-
Fork WebDataServiceW
rapper to remove bits that oxide doesn't need. - 2283d7f... by Olivier Tilloy
-
New FilteredPrefStore class that stores all preferences in memory except for a selected set which are persisted on disk.
- 370bace... by Olivier Tilloy
-
Updated oxide.qmltypes.
Unmerged commits
- 370bace... by Olivier Tilloy
-
Updated oxide.qmltypes.
- becd872... by Olivier Tilloy
-
Updated test.
- 2861ed9... by Olivier Tilloy
-
Ensure that the autofill profiles have been loaded before accessing them.
- 1925106... by Olivier Tilloy
-
New API on WebContext for autofill profiles management.
- 2283d7f... by Olivier Tilloy
-
New FilteredPrefStore class that stores all preferences in memory except for a selected set which are persisted on disk.
- 3f0f3aa... by Olivier Tilloy
-
Fork WebDataServiceW
rapper to remove bits that oxide doesn't need. - 867131f... by Olivier Tilloy
-
Make ownership of AutofillPopupCo
ntroller explicit. - 0c5a23f... by Olivier Tilloy
-
Remove unused method.
- ea88035... by Olivier Tilloy
-
Remove unused references to gfx::NativeView (always null) in AutofillPopupCo
ntroller. - f85f34f... by Olivier Tilloy
-
Rename files for consistency with newly-added code.
Preview Diff
1 | diff --git a/qt/core/browser/oxide_qt_web_context.cc b/qt/core/browser/oxide_qt_web_context.cc |
2 | index fc1492f..678ec86 100644 |
3 | --- a/qt/core/browser/oxide_qt_web_context.cc |
4 | +++ b/qt/core/browser/oxide_qt_web_context.cc |
5 | @@ -20,7 +20,6 @@ |
6 | #include <vector> |
7 | |
8 | #include <QDateTime> |
9 | -#include <QDebug> |
10 | #include <QMetaMethod> |
11 | #include <QNetworkCookie> |
12 | #include <QObject> |
13 | @@ -30,10 +29,13 @@ |
14 | |
15 | #include "base/auto_reset.h" |
16 | #include "base/files/file_path.h" |
17 | +#include "base/guid.h" |
18 | #include "base/logging.h" |
19 | #include "base/strings/string_util.h" |
20 | +#include "base/strings/utf_string_conversions.h" |
21 | #include "base/synchronization/lock.h" |
22 | #include "base/threading/thread_task_runner_handle.h" |
23 | +#include "components/autofill/core/browser/personal_data_manager.h" |
24 | #include "content/public/browser/browser_thread.h" |
25 | #include "content/public/browser/cookie_store_factory.h" |
26 | #include "content/public/browser/resource_request_info.h" |
27 | @@ -59,6 +61,7 @@ |
28 | #include "shared/browser/oxide_user_agent_settings.h" |
29 | #include "shared/browser/oxide_user_script_master.h" |
30 | #include "shared/browser/permissions/oxide_temporary_saved_permission_context.h" |
31 | +#include "shared/browser/personal_data_manager_factory.h" |
32 | |
33 | #include "oxide_qt_browser_startup.h" |
34 | |
35 | @@ -85,6 +88,28 @@ int GetNextCookieRequestId() { |
36 | return id++; |
37 | } |
38 | |
39 | +const char kAutofillOrigin[] = "oxide autofill"; |
40 | + |
41 | +void PopulateAutofillProfileFromVariant(autofill::AutofillProfile* profile, |
42 | + const QVariantMap& map) { |
43 | +#define SET_PROFILE_FIELD(field, key) \ |
44 | + profile->SetRawInfo(autofill::field, base::UTF8ToUTF16( \ |
45 | + map.value(QStringLiteral(key)).toString().toStdString())) |
46 | + SET_PROFILE_FIELD(NAME_FIRST, "firstName"); |
47 | + SET_PROFILE_FIELD(NAME_MIDDLE, "middleName"); |
48 | + SET_PROFILE_FIELD(NAME_LAST, "lastName"); |
49 | + SET_PROFILE_FIELD(NAME_FULL, "fullName"); |
50 | + SET_PROFILE_FIELD(COMPANY_NAME, "companyName"); |
51 | + SET_PROFILE_FIELD(ADDRESS_HOME_STREET_ADDRESS, "address"); |
52 | + SET_PROFILE_FIELD(ADDRESS_HOME_CITY, "city"); |
53 | + SET_PROFILE_FIELD(ADDRESS_HOME_STATE, "state"); |
54 | + SET_PROFILE_FIELD(ADDRESS_HOME_ZIP, "zip"); |
55 | + SET_PROFILE_FIELD(ADDRESS_HOME_COUNTRY, "country"); |
56 | + SET_PROFILE_FIELD(PHONE_HOME_WHOLE_NUMBER, "phone"); |
57 | + SET_PROFILE_FIELD(EMAIL_ADDRESS, "email"); |
58 | +#undef SET_PROFILE_FIELD |
59 | +} |
60 | + |
61 | } |
62 | |
63 | class WebContext::BrowserContextDelegate |
64 | @@ -453,7 +478,13 @@ WebContext::WebContext(WebContextProxyClient* client, |
65 | WebContext::~WebContext() { |
66 | if (context_.get()) { |
67 | context_->SetDelegate(nullptr); |
68 | + |
69 | MediaCaptureDevicesContext::Get(context_.get())->set_client(nullptr); |
70 | + |
71 | + autofill::PersonalDataManager* manager = |
72 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
73 | + DCHECK(manager); |
74 | + manager->RemoveObserver(this); |
75 | } |
76 | } |
77 | |
78 | @@ -538,6 +569,12 @@ BrowserContext* WebContext::GetContext() { |
79 | |
80 | UpdateUserScripts(); |
81 | |
82 | + autofill::PersonalDataManager* manager = |
83 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
84 | + DCHECK(manager); |
85 | + manager->AddObserver(this); |
86 | + client_->AutofillProfilesChanged(); |
87 | + |
88 | return context_.get(); |
89 | } |
90 | |
91 | @@ -1001,6 +1038,10 @@ void WebContext::DefaultVideoDeviceChanged() { |
92 | client_->DefaultVideoCaptureDeviceChanged(); |
93 | } |
94 | |
95 | +void WebContext::OnPersonalDataChanged() { |
96 | + client_->AutofillProfilesChanged(); |
97 | +} |
98 | + |
99 | bool WebContext::doNotTrack() const { |
100 | if (IsInitialized()) { |
101 | return UserAgentSettings::Get(context_.get())->GetDoNotTrack(); |
102 | @@ -1033,5 +1074,107 @@ void WebContext::setAutofillEnabled(bool enabled) { |
103 | } |
104 | } |
105 | |
106 | +bool WebContext::autofillProfilesLoaded() const { |
107 | + if (!IsInitialized()) { |
108 | + return false; |
109 | + } |
110 | + |
111 | + autofill::PersonalDataManager* manager = |
112 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
113 | + DCHECK(manager); |
114 | + return manager->IsDataLoaded(); |
115 | +} |
116 | + |
117 | +QStringList WebContext::getAutofillProfiles() const { |
118 | + if (!autofillProfilesLoaded()) { |
119 | + return QStringList(); |
120 | + } |
121 | + |
122 | + autofill::PersonalDataManager* manager = |
123 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
124 | + QStringList rv; |
125 | + for (auto profile : manager->GetProfiles()) { |
126 | + rv.append(QString::fromStdString(profile->guid())); |
127 | + } |
128 | + return rv; |
129 | +} |
130 | + |
131 | +QVariant WebContext::getAutofillProfile(const QString& guid) const { |
132 | + if (!autofillProfilesLoaded()) { |
133 | + return QVariant(); |
134 | + } |
135 | + |
136 | + autofill::PersonalDataManager* manager = |
137 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
138 | + autofill::AutofillProfile* profile = |
139 | + manager->GetProfileByGUID(guid.toStdString()); |
140 | + if (!profile) { |
141 | + return QVariant(); |
142 | + } |
143 | + |
144 | + QVariantMap rv; |
145 | + const std::string& locale = manager->app_locale(); |
146 | + rv[QStringLiteral("guid")] = QString::fromStdString(profile->guid()); |
147 | + rv[QStringLiteral("origin")] = QString::fromStdString(profile->origin()); |
148 | +#define GET_PROFILE_FIELD(key, field) \ |
149 | + rv[QStringLiteral(key)] = QString::fromStdString(base::UTF16ToUTF8( \ |
150 | + profile->GetInfo(autofill::AutofillType(autofill::field), locale))) |
151 | + GET_PROFILE_FIELD("firstName", NAME_FIRST); |
152 | + GET_PROFILE_FIELD("middleName", NAME_MIDDLE); |
153 | + GET_PROFILE_FIELD("lastName", NAME_LAST); |
154 | + GET_PROFILE_FIELD("fullName", NAME_FULL); |
155 | + GET_PROFILE_FIELD("companyName", COMPANY_NAME); |
156 | + GET_PROFILE_FIELD("address", ADDRESS_HOME_STREET_ADDRESS); |
157 | + GET_PROFILE_FIELD("city", ADDRESS_HOME_CITY); |
158 | + GET_PROFILE_FIELD("state", ADDRESS_HOME_STATE); |
159 | + GET_PROFILE_FIELD("zip", ADDRESS_HOME_ZIP); |
160 | + GET_PROFILE_FIELD("country", ADDRESS_HOME_COUNTRY); |
161 | + GET_PROFILE_FIELD("phone", PHONE_HOME_WHOLE_NUMBER); |
162 | + GET_PROFILE_FIELD("email", EMAIL_ADDRESS); |
163 | +#undef GET_PROFILE_FIELD |
164 | + return rv; |
165 | +} |
166 | + |
167 | +void WebContext::addAutofillProfile(const QVariant& profile) { |
168 | + if (!autofillProfilesLoaded()) { |
169 | + return; |
170 | + } |
171 | + |
172 | + autofill::PersonalDataManager* manager = |
173 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
174 | + autofill::AutofillProfile ap(base::GenerateGUID(), kAutofillOrigin); |
175 | + PopulateAutofillProfileFromVariant(&ap, profile.toMap()); |
176 | + manager->AddProfile(ap); |
177 | +} |
178 | + |
179 | +void WebContext::removeAutofillProfile(const QString& guid) { |
180 | + if (!autofillProfilesLoaded()) { |
181 | + return; |
182 | + } |
183 | + |
184 | + autofill::PersonalDataManager* manager = |
185 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
186 | + manager->RemoveByGUID(guid.toStdString()); |
187 | +} |
188 | + |
189 | +void WebContext::updateAutofillProfile(const QVariant& profile) { |
190 | + if (!autofillProfilesLoaded()) { |
191 | + return; |
192 | + } |
193 | + |
194 | + QVariantMap map = profile.toMap(); |
195 | + if (!map.contains(QStringLiteral("guid"))) { |
196 | + return; |
197 | + } |
198 | + |
199 | + autofill::PersonalDataManager* manager = |
200 | + PersonalDataManagerFactory::GetForContext(context_.get()); |
201 | + autofill::AutofillProfile ap( |
202 | + map.value(QStringLiteral("guid")).toString().toStdString(), |
203 | + map.value(QStringLiteral("origin")).toString().toStdString()); |
204 | + PopulateAutofillProfileFromVariant(&ap, profile.toMap()); |
205 | + manager->UpdateProfile(ap); |
206 | +} |
207 | + |
208 | } // namespace qt |
209 | } // namespace oxide |
210 | diff --git a/qt/core/browser/oxide_qt_web_context.h b/qt/core/browser/oxide_qt_web_context.h |
211 | index 1dd4134..ef5817c 100644 |
212 | --- a/qt/core/browser/oxide_qt_web_context.h |
213 | +++ b/qt/core/browser/oxide_qt_web_context.h |
214 | @@ -29,6 +29,7 @@ |
215 | #include "base/macros.h" |
216 | #include "base/memory/ref_counted.h" |
217 | #include "base/memory/weak_ptr.h" |
218 | +#include "components/autofill/core/browser/personal_data_manager_observer.h" |
219 | #include "net/cookies/canonical_cookie.h" |
220 | |
221 | #include "qt/core/glue/oxide_qt_web_context_proxy.h" |
222 | @@ -67,7 +68,8 @@ class WebContextGetter : public base::RefCountedThreadSafe<WebContextGetter> { |
223 | }; |
224 | |
225 | class WebContext : public WebContextProxy, |
226 | - public oxide::MediaCaptureDevicesContextClient { |
227 | + public oxide::MediaCaptureDevicesContextClient, |
228 | + public autofill::PersonalDataManagerObserver { |
229 | public: |
230 | WebContext(WebContextProxyClient* client, QObject* handle); |
231 | ~WebContext(); |
232 | @@ -147,10 +149,20 @@ class WebContext : public WebContextProxy, |
233 | bool autofillEnabled() const override; |
234 | void setAutofillEnabled(bool enabled) override; |
235 | |
236 | + bool autofillProfilesLoaded() const override; |
237 | + QStringList getAutofillProfiles() const override; |
238 | + QVariant getAutofillProfile(const QString& guid) const override; |
239 | + void addAutofillProfile(const QVariant& profile) override; |
240 | + void removeAutofillProfile(const QString& guid) override; |
241 | + void updateAutofillProfile(const QVariant& profile) override; |
242 | + |
243 | // oxide::MediaCaptureDevicesContextClient implementation |
244 | void DefaultAudioDeviceChanged() override; |
245 | void DefaultVideoDeviceChanged() override; |
246 | |
247 | + // autofill::PersonalDataManagerObserver implementation |
248 | + void OnPersonalDataChanged() override; |
249 | + |
250 | WebContextProxyClient* client_; |
251 | |
252 | BrowserContext::UniquePtr context_; |
253 | diff --git a/qt/core/glue/oxide_qt_web_context_proxy.h b/qt/core/glue/oxide_qt_web_context_proxy.h |
254 | index 49f0180..59b9b6b 100644 |
255 | --- a/qt/core/glue/oxide_qt_web_context_proxy.h |
256 | +++ b/qt/core/glue/oxide_qt_web_context_proxy.h |
257 | @@ -23,6 +23,7 @@ |
258 | #include <QStringList> |
259 | #include <QtGlobal> |
260 | #include <QUrl> |
261 | +#include <QVariant> |
262 | #include <QWeakPointer> |
263 | |
264 | #include "qt/core/api/oxideqglobal.h" |
265 | @@ -140,6 +141,13 @@ class OXIDE_QTCORE_EXPORT WebContextProxy : public ProxyBase<WebContext> { |
266 | |
267 | virtual bool autofillEnabled() const = 0; |
268 | virtual void setAutofillEnabled(bool enabled) = 0; |
269 | + |
270 | + virtual bool autofillProfilesLoaded() const = 0; |
271 | + virtual QStringList getAutofillProfiles() const = 0; |
272 | + virtual QVariant getAutofillProfile(const QString& guid) const = 0; |
273 | + virtual void addAutofillProfile(const QVariant& profile) = 0; |
274 | + virtual void removeAutofillProfile(const QString& guid) = 0; |
275 | + virtual void updateAutofillProfile(const QVariant& profile) = 0; |
276 | }; |
277 | |
278 | } // namespace qt |
279 | diff --git a/qt/core/glue/oxide_qt_web_context_proxy_client.h b/qt/core/glue/oxide_qt_web_context_proxy_client.h |
280 | index a449c60..9c710d9 100644 |
281 | --- a/qt/core/glue/oxide_qt_web_context_proxy_client.h |
282 | +++ b/qt/core/glue/oxide_qt_web_context_proxy_client.h |
283 | @@ -1,5 +1,5 @@ |
284 | // vim:expandtab:shiftwidth=2:tabstop=2: |
285 | -// Copyright (C) 2013-2015 Canonical Ltd. |
286 | +// Copyright (C) 2013-2017 Canonical Ltd. |
287 | |
288 | // This library is free software; you can redistribute it and/or |
289 | // modify it under the terms of the GNU Lesser General Public |
290 | @@ -51,6 +51,8 @@ class WebContextProxyClient { |
291 | |
292 | virtual void DefaultVideoCaptureDeviceChanged() = 0; |
293 | |
294 | + virtual void AutofillProfilesChanged() = 0; |
295 | + |
296 | class IOClient { |
297 | public: |
298 | virtual ~IOClient() {} |
299 | diff --git a/qt/qmlplugin/oxide.qmltypes b/qt/qmlplugin/oxide.qmltypes |
300 | index 1d7d164..2adbde8 100644 |
301 | --- a/qt/qmlplugin/oxide.qmltypes |
302 | +++ b/qt/qmlplugin/oxide.qmltypes |
303 | @@ -186,6 +186,31 @@ Module { |
304 | Method { name: "deny" } |
305 | } |
306 | Component { |
307 | + name: "OxideQQuickAutofillProfiles" |
308 | + prototype: "QAbstractListModel" |
309 | + exports: ["AutofillProfiles 1.22"] |
310 | + isCreatable: false |
311 | + exportMetaObjectRevisions: [0] |
312 | + Property { name: "ready"; type: "bool"; isReadonly: true } |
313 | + Method { |
314 | + name: "get" |
315 | + type: "QVariant" |
316 | + Parameter { name: "guid"; type: "string" } |
317 | + } |
318 | + Method { |
319 | + name: "add" |
320 | + Parameter { name: "profile"; type: "QVariant" } |
321 | + } |
322 | + Method { |
323 | + name: "remove" |
324 | + Parameter { name: "guid"; type: "string" } |
325 | + } |
326 | + Method { |
327 | + name: "update" |
328 | + Parameter { name: "profile"; type: "QVariant" } |
329 | + } |
330 | + } |
331 | + Component { |
332 | name: "OxideQQuickCookieManager" |
333 | prototype: "QObject" |
334 | exports: ["CookieManager 1.0", "CookieManager 1.3"] |
335 | @@ -477,6 +502,13 @@ Module { |
336 | Property { name: "userAgentOverrides"; revision: 3; type: "QVariantList" } |
337 | Property { name: "doNotTrackEnabled"; revision: 3; type: "bool" } |
338 | Property { name: "autofillEnabled"; revision: 4; type: "bool" } |
339 | + Property { |
340 | + name: "autofillProfiles" |
341 | + revision: 4 |
342 | + type: "OxideQQuickAutofillProfiles" |
343 | + isReadonly: true |
344 | + isPointer: true |
345 | + } |
346 | Signal { name: "devtoolsBindIpChanged" } |
347 | Signal { name: "hostMappingRulesChanged"; revision: 1 } |
348 | Signal { name: "allowedExtraUrlSchemesChanged"; revision: 1 } |
349 | diff --git a/qt/qmlplugin/oxide_qml_plugin.cc b/qt/qmlplugin/oxide_qml_plugin.cc |
350 | index cf2e41c..749d66f 100644 |
351 | --- a/qt/qmlplugin/oxide_qml_plugin.cc |
352 | +++ b/qt/qmlplugin/oxide_qml_plugin.cc |
353 | @@ -34,6 +34,7 @@ |
354 | #include "qt/core/api/oxideqsecuritystatus.h" |
355 | #include "qt/core/api/oxideqsslcertificate.h" |
356 | #include "qt/core/api/oxideqwebpreferences.h" |
357 | +#include "qt/quick/api/oxideqquickautofillprofiles.h" |
358 | #include "qt/quick/api/oxideqquickcookiemanager_p.h" |
359 | #include "qt/quick/api/oxideqquickglobal_p.h" |
360 | #include "qt/quick/api/oxideqquicklocationbarcontroller.h" |
361 | @@ -217,6 +218,9 @@ class OxideQmlPlugin : public QQmlExtensionPlugin { |
362 | "NavigationHistory is accessed via WebView.navigationHistory"); |
363 | |
364 | qmlRegisterType<OxideQQuickWebContext, 4>(uri, 1, 22, "WebContext"); |
365 | + qmlRegisterUncreatableType<OxideQQuickAutofillProfiles>( |
366 | + uri, 1, 22, "AutofillProfiles", |
367 | + "AutofillProfiles is accessed via WebContext.autofillProfiles"); |
368 | } |
369 | }; |
370 | |
371 | diff --git a/qt/quick/CMakeLists.txt b/qt/quick/CMakeLists.txt |
372 | index 3737b68..416a7ce 100644 |
373 | --- a/qt/quick/CMakeLists.txt |
374 | +++ b/qt/quick/CMakeLists.txt |
375 | @@ -1,6 +1,6 @@ |
376 | # vim:expandtab:shiftwidth=2:tabstop=2: |
377 | |
378 | -# Copyright (C) 2014-2016 Canonical Ltd. |
379 | +# Copyright (C) 2014-2017 Canonical Ltd. |
380 | |
381 | # This library is free software; you can redistribute it and/or |
382 | # modify it under the terms of the GNU Lesser General Public |
383 | @@ -20,6 +20,7 @@ qt5_wrap_cpp(MOC_EXTRA |
384 | api/oxideqquickwebcontextdelegateworker_p_p.h) |
385 | |
386 | set(OXIDE_QUICKLIB_SRCS |
387 | + api/oxideqquickautofillprofiles.cc |
388 | api/oxideqquickcookiemanager.cc |
389 | api/oxideqquickglobal.cc |
390 | api/oxideqquicklocationbarcontroller.cc |
391 | diff --git a/qt/quick/api/oxideqquickautofillprofiles.cc b/qt/quick/api/oxideqquickautofillprofiles.cc |
392 | new file mode 100644 |
393 | index 0000000..835984c |
394 | --- /dev/null |
395 | +++ b/qt/quick/api/oxideqquickautofillprofiles.cc |
396 | @@ -0,0 +1,193 @@ |
397 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
398 | +// Copyright (C) 2017 Canonical Ltd. |
399 | + |
400 | +// This library is free software; you can redistribute it and/or |
401 | +// modify it under the terms of the GNU Lesser General Public |
402 | +// License as published by the Free Software Foundation; either |
403 | +// version 2.1 of the License, or (at your option) any later version. |
404 | + |
405 | +// This library is distributed in the hope that it will be useful, |
406 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
407 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
408 | +// Lesser General Public License for more details. |
409 | + |
410 | +// You should have received a copy of the GNU Lesser General Public |
411 | +// License along with this library; if not, write to the Free Software |
412 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
413 | + |
414 | +#include "oxideqquickautofillprofiles.h" |
415 | +#include "oxideqquickautofillprofiles_p.h" |
416 | + |
417 | +#include <QString> |
418 | + |
419 | +#include "qt/core/glue/oxide_qt_web_context_proxy.h" |
420 | + |
421 | +OxideQQuickAutofillProfilesPrivate::OxideQQuickAutofillProfilesPrivate( |
422 | + OxideQQuickAutofillProfiles* q) |
423 | + : q_ptr(q), |
424 | + model_items_need_rebuilding_(true) {} |
425 | + |
426 | +void OxideQQuickAutofillProfilesPrivate::ensureModelItemsAreBuilt() { |
427 | + if (!model_items_need_rebuilding_) { |
428 | + return; |
429 | + } |
430 | + |
431 | + Q_ASSERT(model_items_.isEmpty()); |
432 | + model_items_need_rebuilding_ = false; |
433 | + |
434 | + QStringList guids = web_context_proxy_->getAutofillProfiles(); |
435 | + for (const auto& guid : guids) { |
436 | + model_items_.append(web_context_proxy_->getAutofillProfile(guid)); |
437 | + } |
438 | +} |
439 | + |
440 | +void OxideQQuickAutofillProfilesPrivate::AutofillProfilesChanged() { |
441 | + Q_Q(OxideQQuickAutofillProfiles); |
442 | + |
443 | + model_items_need_rebuilding_ = false; |
444 | + q->beginResetModel(); |
445 | + model_items_need_rebuilding_ = true; |
446 | + model_items_.clear(); |
447 | + q->endResetModel(); |
448 | + |
449 | + Q_EMIT q->readyChanged(); |
450 | +} |
451 | + |
452 | +OxideQQuickAutofillProfilesPrivate |
453 | + ::~OxideQQuickAutofillProfilesPrivate() = default; |
454 | + |
455 | +// static |
456 | +OxideQQuickAutofillProfilesPrivate* OxideQQuickAutofillProfilesPrivate::get( |
457 | + OxideQQuickAutofillProfiles* q) { |
458 | + return q->d_func(); |
459 | +} |
460 | + |
461 | +// static |
462 | +std::unique_ptr<OxideQQuickAutofillProfiles> |
463 | +OxideQQuickAutofillProfilesPrivate::Create() { |
464 | + return std::unique_ptr<OxideQQuickAutofillProfiles>( |
465 | + new OxideQQuickAutofillProfiles()); |
466 | +} |
467 | + |
468 | +void OxideQQuickAutofillProfilesPrivate::SetWebContextProxy( |
469 | + oxide::qt::WebContextProxy* proxy) { |
470 | + web_context_proxy_ = proxy; |
471 | +} |
472 | + |
473 | +OxideQQuickAutofillProfiles::OxideQQuickAutofillProfiles() |
474 | + : d_ptr(new OxideQQuickAutofillProfilesPrivate(this)) {} |
475 | + |
476 | +bool OxideQQuickAutofillProfiles::ready() const { |
477 | + Q_D(const OxideQQuickAutofillProfiles); |
478 | + |
479 | + return d->web_context_proxy_->autofillProfilesLoaded(); |
480 | +} |
481 | + |
482 | +QHash<int, QByteArray> OxideQQuickAutofillProfiles::roleNames() const { |
483 | + static QHash<int, QByteArray> roles; |
484 | + if (roles.isEmpty()) { |
485 | + roles[OxideQQuickAutofillProfilesPrivate::Guid] = "guid"; |
486 | + roles[OxideQQuickAutofillProfilesPrivate::Origin] = "origin"; |
487 | + roles[OxideQQuickAutofillProfilesPrivate::FirstName] = "firstName"; |
488 | + roles[OxideQQuickAutofillProfilesPrivate::MiddleName] = "middleName"; |
489 | + roles[OxideQQuickAutofillProfilesPrivate::LastName] = "lastName"; |
490 | + roles[OxideQQuickAutofillProfilesPrivate::FullName] = "fullName"; |
491 | + roles[OxideQQuickAutofillProfilesPrivate::CompanyName] = "companyName"; |
492 | + roles[OxideQQuickAutofillProfilesPrivate::Address] = "address"; |
493 | + roles[OxideQQuickAutofillProfilesPrivate::City] = "city"; |
494 | + roles[OxideQQuickAutofillProfilesPrivate::State] = "state"; |
495 | + roles[OxideQQuickAutofillProfilesPrivate::Zip] = "zip"; |
496 | + roles[OxideQQuickAutofillProfilesPrivate::Country] = "country"; |
497 | + roles[OxideQQuickAutofillProfilesPrivate::Phone] = "phone"; |
498 | + roles[OxideQQuickAutofillProfilesPrivate::Email] = "email"; |
499 | + } |
500 | + return roles; |
501 | +} |
502 | + |
503 | +int OxideQQuickAutofillProfiles::rowCount(const QModelIndex& parent) const { |
504 | + Q_UNUSED(parent); |
505 | + Q_D(const OxideQQuickAutofillProfiles); |
506 | + |
507 | + const_cast<OxideQQuickAutofillProfiles*>(this) |
508 | + ->d_func()->ensureModelItemsAreBuilt(); |
509 | + |
510 | + return d->model_items_.size(); |
511 | +} |
512 | + |
513 | +QVariant OxideQQuickAutofillProfiles::data(const QModelIndex& index, |
514 | + int role) const { |
515 | + Q_D(const OxideQQuickAutofillProfiles); |
516 | + |
517 | + const_cast<OxideQQuickAutofillProfiles*>(this) |
518 | + ->d_func()->ensureModelItemsAreBuilt(); |
519 | + |
520 | + if (!index.isValid()) { |
521 | + return QVariant(); |
522 | + } |
523 | + |
524 | + int row = index.row(); |
525 | + if ((row < 0) || (row >= d->model_items_.size())) { |
526 | + return QVariant(); |
527 | + } |
528 | + |
529 | + const QVariantMap& item = d->model_items_[row].toMap(); |
530 | + |
531 | + switch (role) { |
532 | + case OxideQQuickAutofillProfilesPrivate::Guid: |
533 | + return item.value(QStringLiteral("guid")); |
534 | + case OxideQQuickAutofillProfilesPrivate::Origin: |
535 | + return item.value(QStringLiteral("origin")); |
536 | + case OxideQQuickAutofillProfilesPrivate::FirstName: |
537 | + return item.value(QStringLiteral("firstName")); |
538 | + case OxideQQuickAutofillProfilesPrivate::MiddleName: |
539 | + return item.value(QStringLiteral("middleName")); |
540 | + case OxideQQuickAutofillProfilesPrivate::LastName: |
541 | + return item.value(QStringLiteral("lastName")); |
542 | + case OxideQQuickAutofillProfilesPrivate::FullName: |
543 | + return item.value(QStringLiteral("fullName")); |
544 | + case OxideQQuickAutofillProfilesPrivate::CompanyName: |
545 | + return item.value(QStringLiteral("companyName")); |
546 | + case OxideQQuickAutofillProfilesPrivate::Address: |
547 | + return item.value(QStringLiteral("address")); |
548 | + case OxideQQuickAutofillProfilesPrivate::City: |
549 | + return item.value(QStringLiteral("city")); |
550 | + case OxideQQuickAutofillProfilesPrivate::State: |
551 | + return item.value(QStringLiteral("state")); |
552 | + case OxideQQuickAutofillProfilesPrivate::Zip: |
553 | + return item.value(QStringLiteral("zip")); |
554 | + case OxideQQuickAutofillProfilesPrivate::Country: |
555 | + return item.value(QStringLiteral("country")); |
556 | + case OxideQQuickAutofillProfilesPrivate::Phone: |
557 | + return item.value(QStringLiteral("phone")); |
558 | + case OxideQQuickAutofillProfilesPrivate::Email: |
559 | + return item.value(QStringLiteral("email")); |
560 | + default: |
561 | + return QVariant(); |
562 | + } |
563 | +} |
564 | + |
565 | +OxideQQuickAutofillProfiles::~OxideQQuickAutofillProfiles() = default; |
566 | + |
567 | +QVariant OxideQQuickAutofillProfiles::get(const QString& guid) const { |
568 | + Q_D(const OxideQQuickAutofillProfiles); |
569 | + |
570 | + return d->web_context_proxy_->getAutofillProfile(guid); |
571 | +} |
572 | + |
573 | +void OxideQQuickAutofillProfiles::add(const QVariant& profile) { |
574 | + Q_D(OxideQQuickAutofillProfiles); |
575 | + |
576 | + d->web_context_proxy_->addAutofillProfile(profile); |
577 | +} |
578 | + |
579 | +void OxideQQuickAutofillProfiles::remove(const QString& guid) { |
580 | + Q_D(OxideQQuickAutofillProfiles); |
581 | + |
582 | + d->web_context_proxy_->removeAutofillProfile(guid); |
583 | +} |
584 | + |
585 | +void OxideQQuickAutofillProfiles::update(const QVariant& profile) { |
586 | + Q_D(OxideQQuickAutofillProfiles); |
587 | + |
588 | + d->web_context_proxy_->updateAutofillProfile(profile); |
589 | +} |
590 | diff --git a/qt/quick/api/oxideqquickautofillprofiles.h b/qt/quick/api/oxideqquickautofillprofiles.h |
591 | new file mode 100644 |
592 | index 0000000..7022037 |
593 | --- /dev/null |
594 | +++ b/qt/quick/api/oxideqquickautofillprofiles.h |
595 | @@ -0,0 +1,68 @@ |
596 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
597 | +// Copyright (C) 2017 Canonical Ltd. |
598 | + |
599 | +// This library is free software; you can redistribute it and/or |
600 | +// modify it under the terms of the GNU Lesser General Public |
601 | +// License as published by the Free Software Foundation; either |
602 | +// version 2.1 of the License, or (at your option) any later version. |
603 | + |
604 | +// This library is distributed in the hope that it will be useful, |
605 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
606 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
607 | +// Lesser General Public License for more details. |
608 | + |
609 | +// You should have received a copy of the GNU Lesser General Public |
610 | +// License along with this library; if not, write to the Free Software |
611 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
612 | + |
613 | +#ifndef OXIDE_QTQUICK_AUTOFILL_PROFILES |
614 | +#define OXIDE_QTQUICK_AUTOFILL_PROFILES |
615 | + |
616 | +#include <QtCore/QAbstractListModel> |
617 | +#include <QtCore/QScopedPointer> |
618 | +#include <QtCore/QVariant> |
619 | +#include <QtQml/QtQml> |
620 | + |
621 | +#include <OxideQtQuick/oxideqquickglobal.h> |
622 | + |
623 | +class QString; |
624 | + |
625 | +class OxideQQuickAutofillProfilesPrivate; |
626 | + |
627 | +class OXIDE_QTQUICK_EXPORT OxideQQuickAutofillProfiles |
628 | + : public QAbstractListModel { |
629 | + Q_OBJECT |
630 | + |
631 | + Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) |
632 | + |
633 | + Q_DECLARE_PRIVATE(OxideQQuickAutofillProfiles) |
634 | + Q_DISABLE_COPY(OxideQQuickAutofillProfiles) |
635 | + |
636 | + public: |
637 | + ~OxideQQuickAutofillProfiles() Q_DECL_OVERRIDE; |
638 | + |
639 | + bool ready() const; |
640 | + |
641 | + public Q_SLOTS: |
642 | + QVariant get(const QString& guid) const; |
643 | + void add(const QVariant& profile); |
644 | + void remove(const QString& guid); |
645 | + void update(const QVariant& profile); |
646 | + |
647 | + Q_SIGNALS: |
648 | + void readyChanged(); |
649 | + |
650 | + private: |
651 | + OxideQQuickAutofillProfiles(); |
652 | + |
653 | + // reimplemented from QAbstractListModel |
654 | + QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; |
655 | + int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; |
656 | + QVariant data(const QModelIndex& index, int role) const Q_DECL_OVERRIDE; |
657 | + |
658 | + QScopedPointer<OxideQQuickAutofillProfilesPrivate> d_ptr; |
659 | +}; |
660 | + |
661 | +QML_DECLARE_TYPE(OxideQQuickAutofillProfiles) |
662 | + |
663 | +#endif // OXIDE_QTQUICK_AUTOFILL_PROFILES |
664 | diff --git a/qt/quick/api/oxideqquickautofillprofiles_p.h b/qt/quick/api/oxideqquickautofillprofiles_p.h |
665 | new file mode 100644 |
666 | index 0000000..d47b60b |
667 | --- /dev/null |
668 | +++ b/qt/quick/api/oxideqquickautofillprofiles_p.h |
669 | @@ -0,0 +1,80 @@ |
670 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
671 | +// Copyright (C) 2017 Canonical Ltd. |
672 | + |
673 | +// This library is free software; you can redistribute it and/or |
674 | +// modify it under the terms of the GNU Lesser General Public |
675 | +// License as published by the Free Software Foundation; either |
676 | +// version 2.1 of the License, or (at your option) any later version. |
677 | + |
678 | +// This library is distributed in the hope that it will be useful, |
679 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
680 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
681 | +// Lesser General Public License for more details. |
682 | + |
683 | +// You should have received a copy of the GNU Lesser General Public |
684 | +// License along with this library; if not, write to the Free Software |
685 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
686 | + |
687 | +#ifndef _OXIDE_QT_QUICK_API_AUTOFILL_PROFILES_P_H_ |
688 | +#define _OXIDE_QT_QUICK_API_AUTOFILL_PROFILES_P_H_ |
689 | + |
690 | +#include <memory> |
691 | + |
692 | +#include <QtGlobal> |
693 | +#include <QVariantList> |
694 | + |
695 | +namespace oxide { |
696 | +namespace qt { |
697 | +class WebContextProxy; |
698 | +} |
699 | +} |
700 | + |
701 | +class OxideQQuickAutofillProfiles; |
702 | + |
703 | +class OxideQQuickAutofillProfilesPrivate { |
704 | + Q_DECLARE_PUBLIC(OxideQQuickAutofillProfiles) |
705 | + Q_DISABLE_COPY(OxideQQuickAutofillProfilesPrivate) |
706 | + |
707 | + public: |
708 | + ~OxideQQuickAutofillProfilesPrivate(); |
709 | + |
710 | + static OxideQQuickAutofillProfilesPrivate* get( |
711 | + OxideQQuickAutofillProfiles* q); |
712 | + |
713 | + static std::unique_ptr<OxideQQuickAutofillProfiles> Create(); |
714 | + |
715 | + void SetWebContextProxy(oxide::qt::WebContextProxy* proxy); |
716 | + |
717 | + void AutofillProfilesChanged(); |
718 | + |
719 | + private: |
720 | + OxideQQuickAutofillProfilesPrivate(OxideQQuickAutofillProfiles* q); |
721 | + |
722 | + void ensureModelItemsAreBuilt(); |
723 | + |
724 | + enum Roles { |
725 | + Guid = Qt::UserRole + 1, |
726 | + Origin, |
727 | + FirstName, |
728 | + MiddleName, |
729 | + LastName, |
730 | + FullName, |
731 | + CompanyName, |
732 | + Address, |
733 | + City, |
734 | + State, |
735 | + Zip, |
736 | + Country, |
737 | + Phone, |
738 | |
739 | + }; |
740 | + |
741 | + OxideQQuickAutofillProfiles* q_ptr; |
742 | + |
743 | + oxide::qt::WebContextProxy* web_context_proxy_; |
744 | + |
745 | + bool model_items_need_rebuilding_; |
746 | + QVariantList model_items_; |
747 | +}; |
748 | + |
749 | +#endif // _OXIDE_QT_QUICK_API_AUTOFILL_PROFILES_P_H_ |
750 | diff --git a/qt/quick/api/oxideqquickwebcontext.cc b/qt/quick/api/oxideqquickwebcontext.cc |
751 | index 1946af0..92b99ee 100644 |
752 | --- a/qt/quick/api/oxideqquickwebcontext.cc |
753 | +++ b/qt/quick/api/oxideqquickwebcontext.cc |
754 | @@ -1,5 +1,5 @@ |
755 | // vim:expandtab:shiftwidth=2:tabstop=2: |
756 | -// Copyright (C) 2013-2016 Canonical Ltd. |
757 | +// Copyright (C) 2013-2017 Canonical Ltd. |
758 | |
759 | // This library is free software; you can redistribute it and/or |
760 | // modify it under the terms of the GNU Lesser General Public |
761 | @@ -35,6 +35,8 @@ |
762 | #include "qt/core/glue/oxide_qt_web_context_proxy.h" |
763 | #include "qt/quick/oxide_qquick_init.h" |
764 | |
765 | +#include "oxideqquickautofillprofiles.h" |
766 | +#include "oxideqquickautofillprofiles_p.h" |
767 | #include "oxideqquickcookiemanager_p.h" |
768 | #include "oxideqquickuserscript.h" |
769 | #include "oxideqquickuserscript_p.h" |
770 | @@ -213,7 +215,11 @@ OxideQQuickWebContextPrivate::OxideQQuickWebContextPrivate( |
771 | proxy_(WebContextProxy::create(this, q)), |
772 | constructed_(false), |
773 | io_(new oxide::qquick::WebContextIODelegate()), |
774 | - cookie_manager_(nullptr) {} |
775 | + cookie_manager_(nullptr), |
776 | + autofill_profiles_(OxideQQuickAutofillProfilesPrivate::Create()) { |
777 | + OxideQQuickAutofillProfilesPrivate::get(autofill_profiles_.get()) |
778 | + ->SetWebContextProxy(proxy_.data()); |
779 | +} |
780 | |
781 | void OxideQQuickWebContextPrivate::userScriptUpdated() { |
782 | proxy_->updateUserScripts(); |
783 | @@ -391,6 +397,13 @@ void OxideQQuickWebContextPrivate::DefaultVideoCaptureDeviceChanged() { |
784 | emit q->defaultVideoCaptureDeviceIdChanged(); |
785 | } |
786 | |
787 | +void OxideQQuickWebContextPrivate::AutofillProfilesChanged() { |
788 | + Q_Q(OxideQQuickWebContext); |
789 | + |
790 | + OxideQQuickAutofillProfilesPrivate::get(autofill_profiles_.get()) |
791 | + ->AutofillProfilesChanged(); |
792 | +} |
793 | + |
794 | OxideQQuickWebContextPrivate::~OxideQQuickWebContextPrivate() {} |
795 | |
796 | void OxideQQuickWebContextPrivate::delegateWorkerDestroyed( |
797 | @@ -1592,4 +1605,10 @@ void OxideQQuickWebContext::setAutofillEnabled(bool enabled) { |
798 | emit autofillEnabledChanged(); |
799 | } |
800 | |
801 | +OxideQQuickAutofillProfiles* OxideQQuickWebContext::autofillProfiles() const { |
802 | + Q_D(const OxideQQuickWebContext); |
803 | + |
804 | + return d->autofill_profiles_.get(); |
805 | +} |
806 | + |
807 | #include "moc_oxideqquickwebcontext.cpp" |
808 | diff --git a/qt/quick/api/oxideqquickwebcontext.h b/qt/quick/api/oxideqquickwebcontext.h |
809 | index f8ca6fa..85c1773 100644 |
810 | --- a/qt/quick/api/oxideqquickwebcontext.h |
811 | +++ b/qt/quick/api/oxideqquickwebcontext.h |
812 | @@ -30,6 +30,7 @@ |
813 | |
814 | #include <OxideQtQuick/oxideqquickglobal.h> |
815 | |
816 | +class OxideQQuickAutofillProfiles; |
817 | class OxideQQuickCookieManager; |
818 | class OxideQQuickWebContextDelegateWorker; |
819 | class OxideQQuickUserScript; |
820 | @@ -78,6 +79,7 @@ class OXIDE_QTQUICK_EXPORT OxideQQuickWebContext : public QObject, |
821 | Q_PROPERTY(bool doNotTrackEnabled READ doNotTrack WRITE setDoNotTrack NOTIFY doNotTrackEnabledChanged REVISION 3) |
822 | |
823 | Q_PROPERTY(bool autofillEnabled READ autofillEnabled WRITE setAutofillEnabled NOTIFY autofillEnabledChanged REVISION 4) |
824 | + Q_PROPERTY(OxideQQuickAutofillProfiles* autofillProfiles READ autofillProfiles CONSTANT REVISION 4) |
825 | |
826 | Q_ENUMS(CookiePolicy) |
827 | Q_ENUMS(SessionCookieMode) |
828 | @@ -178,6 +180,8 @@ class OXIDE_QTQUICK_EXPORT OxideQQuickWebContext : public QObject, |
829 | bool autofillEnabled() const; |
830 | void setAutofillEnabled(bool enabled); |
831 | |
832 | + OxideQQuickAutofillProfiles* autofillProfiles() const; |
833 | + |
834 | Q_SIGNALS: |
835 | void productChanged(); |
836 | void userAgentChanged(); |
837 | diff --git a/qt/quick/api/oxideqquickwebcontext_p.h b/qt/quick/api/oxideqquickwebcontext_p.h |
838 | index 262e132..4e9f34a 100644 |
839 | --- a/qt/quick/api/oxideqquickwebcontext_p.h |
840 | +++ b/qt/quick/api/oxideqquickwebcontext_p.h |
841 | @@ -1,5 +1,5 @@ |
842 | // vim:expandtab:shiftwidth=2:tabstop=2: |
843 | -// Copyright (C) 2013-2016 Canonical Ltd. |
844 | +// Copyright (C) 2013-2017 Canonical Ltd. |
845 | |
846 | // This library is free software; you can redistribute it and/or |
847 | // modify it under the terms of the GNU Lesser General Public |
848 | @@ -25,10 +25,13 @@ |
849 | #include <QStringList> |
850 | #include <QtGlobal> |
851 | |
852 | +#include <memory> |
853 | + |
854 | #include "qt/core/glue/oxide_qt_web_context_proxy_client.h" |
855 | |
856 | #include "qt/quick/api/oxideqquickwebcontext.h" |
857 | |
858 | +class OxideQQuickAutofillProfiles; |
859 | class OxideQQuickWebContextDelegateWorker; |
860 | class OxideQQuickUserScript; |
861 | |
862 | @@ -108,6 +111,7 @@ class Q_DECL_EXPORT OxideQQuickWebContextPrivate |
863 | QNetworkAccessManager* GetCustomNetworkAccessManager() override; |
864 | void DefaultAudioCaptureDeviceChanged() override; |
865 | void DefaultVideoCaptureDeviceChanged() override; |
866 | + void AutofillProfilesChanged() override; |
867 | |
868 | OxideQQuickWebContext* q_ptr; |
869 | |
870 | @@ -125,6 +129,8 @@ class Q_DECL_EXPORT OxideQQuickWebContextPrivate |
871 | |
872 | QStringList allowed_extra_url_schemes_; |
873 | |
874 | + std::unique_ptr<OxideQQuickAutofillProfiles> autofill_profiles_; |
875 | + |
876 | Q_DISABLE_COPY(OxideQQuickWebContextPrivate); |
877 | }; |
878 | |
879 | diff --git a/qt/tests/qmltests/api/tst_WebContext_autofillProfiles.qml b/qt/tests/qmltests/api/tst_WebContext_autofillProfiles.qml |
880 | new file mode 100644 |
881 | index 0000000..3c38ec2 |
882 | --- /dev/null |
883 | +++ b/qt/tests/qmltests/api/tst_WebContext_autofillProfiles.qml |
884 | @@ -0,0 +1,141 @@ |
885 | +import QtQuick 2.0 |
886 | +import QtTest 1.0 |
887 | +import com.canonical.Oxide 1.22 |
888 | +import Oxide.testsupport 1.0 |
889 | +import Ubuntu.Components 1.3 |
890 | + |
891 | +TestWebView { |
892 | + id: webView |
893 | + |
894 | + ListView { |
895 | + id: listView |
896 | + anchors.fill: parent |
897 | + model: SortFilterModel { |
898 | + model: webView.context ? webView.context.autofillProfiles: null |
899 | + sort.property: "fullName" |
900 | + } |
901 | + delegate: Item { |
902 | + objectName: "profile_delegate_%1".arg(index) |
903 | + readonly property string guid: model.guid |
904 | + readonly property string fullName: model.fullName |
905 | + } |
906 | + } |
907 | + |
908 | + TestCase { |
909 | + name: "WebContext_autofillProfiles" |
910 | + when: windowShown |
911 | + |
912 | + function makeProfile(firstName, lastName, companyName, address, |
913 | + city, zip, country, phone, email) { |
914 | + var profile = new Object; |
915 | + profile.firstName = firstName; |
916 | + profile.lastName = lastName; |
917 | + profile.companyName = companyName; |
918 | + profile.address = address; |
919 | + profile.city = city; |
920 | + profile.zip = zip; |
921 | + profile.country = country; |
922 | + profile.phone = phone; |
923 | + profile.email = email; |
924 | + return profile; |
925 | + } |
926 | + |
927 | + function compareProfile(profile, fullName, firstName, lastName, companyName, |
928 | + address, city, zip, phone, email) { |
929 | + compare(profile.fullName, fullName); |
930 | + compare(profile.firstName, firstName); |
931 | + compare(profile.lastName, lastName); |
932 | + compare(profile.companyName, companyName); |
933 | + compare(profile.address, address); |
934 | + compare(profile.city, city); |
935 | + compare(profile.zip, zip); |
936 | + compare(profile.phone, phone); |
937 | + compare(profile.email, email); |
938 | + } |
939 | + |
940 | + function getDelegate(index) { |
941 | + return TestSupport.findItemInScene(listView, |
942 | + "profile_delegate_%1".arg(index)); |
943 | + } |
944 | + |
945 | + function initTestCase() { |
946 | + webView.context.autofillEnabled = true; |
947 | + tryCompare(webView.context.autofillProfiles, "ready", true); |
948 | + } |
949 | + |
950 | + function init() { |
951 | + compare(listView.count, 0); |
952 | + } |
953 | + |
954 | + function test_WebContext_autofillProfiles_get_nonexistent_profile() { |
955 | + compare(webView.context.autofillProfiles.get("I-DONT-EXIST"), undefined); |
956 | + } |
957 | + |
958 | + function test_WebContext_autofillProfiles_add_and_remove_profiles() { |
959 | + var p1 = makeProfile("John", "Lennon", "Apple Records", |
960 | + "Beaconsfield Road", "Liverpool", "L25 6DA", |
961 | + "England", "+440151234567", "john@thebeatles.com"); |
962 | + webView.context.autofillProfiles.add(p1); |
963 | + tryCompare(listView, "count", 1); |
964 | + compare(getDelegate(0).fullName, "John Lennon"); |
965 | + |
966 | + var p2 = makeProfile("John", "Doe", "", "Park Avenue", "NYC", "NY 10016", |
967 | + "USA", "", "john.doe@nospam.org"); |
968 | + webView.context.autofillProfiles.add(p2); |
969 | + tryCompare(listView, "count", 2); |
970 | + verify(TestUtils.waitFor(function() { |
971 | + return (getDelegate(0).fullName == "John Doe"); })); |
972 | + compare(getDelegate(1).fullName, "John Lennon"); |
973 | + |
974 | + var guid0 = getDelegate(0).guid; |
975 | + var guid1 = getDelegate(1).guid; |
976 | + compareProfile(webView.context.autofillProfiles.get(guid0), |
977 | + "John Doe", "John", "Doe", "", "Park Avenue", "NYC", |
978 | + "NY 10016", "", "john.doe@nospam.org"); |
979 | + compareProfile(webView.context.autofillProfiles.get(guid1), |
980 | + "John Lennon", "John", "Lennon", "Apple Records", |
981 | + "Beaconsfield Road", "Liverpool", "L25 6DA", |
982 | + "+440151234567", "john@thebeatles.com"); |
983 | + |
984 | + webView.context.autofillProfiles.remove("I-DONT-EXIST"); |
985 | + compare(listView.count, 2); |
986 | + |
987 | + webView.context.autofillProfiles.remove(guid1); |
988 | + tryCompare(listView, "count", 1); |
989 | + webView.context.autofillProfiles.remove(guid0); |
990 | + tryCompare(listView, "count", 0); |
991 | + } |
992 | + |
993 | + function test_WebContext_autofillProfiles_update_profile() { |
994 | + var p = makeProfile("John", "Lennon", "Apple Records", |
995 | + "Beaconsfield Road", "Liverpool", "L25 6DA", |
996 | + "England", "+440151234567", "john@thebeatles.com"); |
997 | + webView.context.autofillProfiles.add(p); |
998 | + tryCompare(listView, "count", 1); |
999 | + var delegate = getDelegate(0); |
1000 | + compare(delegate.fullName, "John Lennon"); |
1001 | + var guid = delegate.guid; |
1002 | + |
1003 | + // Try updating without specifying the GUID, nothing should happen |
1004 | + p.firstName = "Paul"; |
1005 | + compare(p.guid, undefined); |
1006 | + webView.context.autofillProfiles.update(p); |
1007 | + compare(webView.context.autofillProfiles.get(guid).firstName, "John"); |
1008 | + |
1009 | + // Try updating with an invalid GUID, nothing should happen |
1010 | + p.guid = "I-DONT-EXIST"; |
1011 | + webView.context.autofillProfiles.update(p); |
1012 | + compare(webView.context.autofillProfiles.get(guid).firstName, "John"); |
1013 | + |
1014 | + // Update the profile with its GUID |
1015 | + p.lastName = "McCartney"; |
1016 | + p.guid = guid; |
1017 | + webView.context.autofillProfiles.update(p); |
1018 | + verify(TestUtils.waitFor(function() { |
1019 | + return (getDelegate(0).fullName == "Paul McCartney"); })); |
1020 | + |
1021 | + webView.context.autofillProfiles.remove(guid); |
1022 | + tryCompare(listView, "count", 0); |
1023 | + } |
1024 | + } |
1025 | +} |
1026 | diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml |
1027 | index 8001673..e1954b0 100644 |
1028 | --- a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml |
1029 | +++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml |
1030 | @@ -14,6 +14,21 @@ UbuntuTestWebView { |
1031 | |
1032 | focus: true |
1033 | |
1034 | + Component { |
1035 | + id: profilesViewFactory |
1036 | + |
1037 | + ListView { |
1038 | + anchors.fill: parent |
1039 | + model: SortFilterModel { |
1040 | + model: webView.context ? webView.context.autofillProfiles: null |
1041 | + } |
1042 | + delegate: Item { |
1043 | + objectName: "profile_delegate_%1".arg(index) |
1044 | + readonly property string guid: model.guid |
1045 | + } |
1046 | + } |
1047 | + } |
1048 | + |
1049 | TestCase { |
1050 | name: "WebViewAutofillPopup_autofill_profiles" |
1051 | when: windowShown |
1052 | @@ -224,5 +239,43 @@ UbuntuTestWebView { |
1053 | tryCompare(popup, "count", 1); |
1054 | compare(getSuggestion(0).label, "Beaconsfield Road"); |
1055 | } |
1056 | + |
1057 | + function test_use_profile_added_from_settings() { |
1058 | + // Add a new profile |
1059 | + tryCompare(webView.context.autofillProfiles, "ready", true); |
1060 | + var profile = new Object; |
1061 | + profile.firstName = "Paul"; |
1062 | + profile.lastName = "McCartney"; |
1063 | + profile.address = "Penny Lane"; |
1064 | + profile.city = "Liverpool"; |
1065 | + profile.zip = "L18 1DE"; |
1066 | + profile.email = "paul@thebeatles.com"; |
1067 | + webView.context.autofillProfiles.add(profile); |
1068 | + |
1069 | + typeStringInField("p", "firstname"); |
1070 | + var popup = getAutofillPopup(); |
1071 | + compare(popup.count, 1); |
1072 | + compare(getSuggestion(0).value, "Paul"); |
1073 | + var item = getSuggestion(0); |
1074 | + mouseClick(item); |
1075 | + verify(waitForAutofillPopupToClose()); |
1076 | + compare_field_value("firstname", "Paul"); |
1077 | + compare_field_value("lastname", "McCartney"); |
1078 | + compare_field_value("email", "paul@thebeatles.com"); |
1079 | + compare_field_value("zipcode", "L18 1DE"); |
1080 | + compare_field_value("city", "Liverpool"); |
1081 | + compare_field_value("street", "Penny Lane"); |
1082 | + |
1083 | + // Remove the profile |
1084 | + var profilesView = profilesViewFactory.createObject(webView); |
1085 | + profilesView.model.filter.property = "firstName"; |
1086 | + profilesView.model.filter.pattern = /^Paul$/; |
1087 | + tryCompare(profilesView, "count", 1); |
1088 | + var delegate = TestSupport.findItemInScene(profilesView, |
1089 | + "profile_delegate_0"); |
1090 | + webView.context.autofillProfiles.remove(delegate.guid); |
1091 | + tryCompare(profilesView, "count", 0); |
1092 | + profilesView.destroy(); |
1093 | + } |
1094 | } |
1095 | } |