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