Merge ~osomon/oxide:autofill into oxide:master

Proposed by Olivier Tilloy
Status: Needs review
Proposed branch: ~osomon/oxide:autofill
Merge into: oxide:master
Diff against target: 5836 lines (+4175/-459)
69 files modified
qt/core/BUILD.gn (+7/-0)
qt/core/browser/contents_view_impl.cc (+1/-1)
qt/core/browser/oxide_qt_browser_platform_integration.cc (+6/-1)
qt/core/browser/oxide_qt_browser_platform_integration.h (+2/-1)
qt/core/browser/oxide_qt_web_context.cc (+22/-3)
qt/core/browser/oxide_qt_web_context.h (+4/-1)
qt/core/browser/oxide_qt_web_view.cc (+26/-1)
qt/core/browser/oxide_qt_web_view.h (+5/-1)
qt/core/browser/web_autofill_popup_host.cc (+139/-0)
qt/core/browser/web_autofill_popup_host.h (+78/-0)
qt/core/glue/autofill_suggestion.cc (+30/-0)
qt/core/glue/autofill_suggestion.h (+50/-0)
qt/core/glue/auxiliary_ui_factory.h (+10/-1)
qt/core/glue/oxide_qt_web_context_proxy.h (+4/-1)
qt/core/glue/web_autofill_popup.h (+43/-0)
qt/core/glue/web_autofill_popup_client.h (+40/-0)
qt/qmlplugin/oxide.qmltypes (+7/-423)
qt/qmlplugin/oxide_qml_plugin.cc (+3/-1)
qt/quick/api/oxideqquickwebcontext.cc (+31/-0)
qt/quick/api/oxideqquickwebcontext.h (+7/-1)
qt/quick/qquick_legacy_auxiliary_ui_factory.cc (+13/-1)
qt/quick/qquick_legacy_auxiliary_ui_factory.h (+5/-1)
qt/tests/qmltests/api/tst_WebContext_autofillEnabled.qml (+38/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.html (+23/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml (+300/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.html (+37/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.qml (+157/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.html (+11/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.qml (+105/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.html (+11/-0)
qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.qml (+359/-0)
qt/uitk/lib/CMakeLists.txt (+2/-1)
qt/uitk/lib/resources.qrc (+1/-0)
qt/uitk/lib/resources/WebAutofillPopup.qml (+139/-0)
qt/uitk/lib/uitk_auxiliary_ui_factory.cc (+12/-1)
qt/uitk/lib/uitk_auxiliary_ui_factory.h (+5/-1)
qt/uitk/lib/uitk_web_autofill_popup.cc (+297/-0)
qt/uitk/lib/uitk_web_autofill_popup.h (+87/-0)
shared/BUILD.gn (+30/-1)
shared/browser/autofill/autofill_client.cc (+272/-0)
shared/browser/autofill/autofill_client.h (+116/-0)
shared/browser/autofill/autofill_popup_controller.cc (+163/-0)
shared/browser/autofill/autofill_popup_controller.h (+92/-0)
shared/browser/autofill/web_autofill_popup.h (+42/-0)
shared/browser/autofill/web_autofill_popup_client.h (+41/-0)
shared/browser/filtered_pref_store.cc (+181/-0)
shared/browser/filtered_pref_store.h (+107/-0)
shared/browser/filtered_pref_store_unittest.cc (+209/-0)
shared/browser/oxide_browser_context.cc (+100/-4)
shared/browser/oxide_browser_context.h (+26/-2)
shared/browser/oxide_browser_platform_integration.cc (+6/-1)
shared/browser/oxide_browser_platform_integration.h (+4/-1)
shared/browser/oxide_content_browser_client.cc (+41/-0)
shared/browser/oxide_content_browser_client.h (+6/-2)
shared/browser/oxide_user_agent_settings.cc (+45/-1)
shared/browser/oxide_user_agent_settings.h (+10/-1)
shared/browser/oxide_web_view.cc (+10/-2)
shared/browser/personal_data_manager_factory.cc (+72/-0)
shared/browser/personal_data_manager_factory.h (+60/-0)
shared/browser/resources/browser_manifest_overlay.json (+15/-0)
shared/browser/resources/renderer_manifest_overlay.json (+14/-0)
shared/browser/web_contents_client.cc (+9/-1)
shared/browser/web_contents_client.h (+13/-1)
shared/browser/web_data_service_factory.cc (+100/-0)
shared/browser/web_data_service_factory.h (+63/-0)
shared/browser/web_data_service_wrapper.cc (+114/-0)
shared/browser/web_data_service_wrapper.h (+83/-0)
shared/oxide_resources.grd (+2/-0)
shared/renderer/oxide_content_renderer_client.cc (+12/-1)
Reviewer Review Type Date Requested Status
Chris Coulson Needs Fixing
Review via email: mp+318166@code.launchpad.net

Commit message

Add support for autofill popups in UbuntuWebView (LP: #1214048).

This initial implementation supports single text fields, datalist entries and autofill profiles.
Credit cards and passwords are not supported.
There is no API to manage stored profiles, this will be implemented as a followup feature.

To post a comment you must log in.
~osomon/oxide:autofill updated
8f3dace... by Olivier Tilloy

Fix a unit test when run in single process mode.

acc726e... by Olivier Tilloy

Reduce the height of the autofill entries.

2bf8c7c... by Olivier Tilloy

Preview autofill entry under mouse cursor.

fca284a... by Olivier Tilloy

Highlight currently selected suggestion.

32f4f1e... by Olivier Tilloy

Simplify focus handling.

0fd49b9... by Olivier Tilloy

Fix FTBFS.

305a4b1... by Olivier Tilloy

Handle validation when no suggestion is selected.

c6f3be8... by Olivier Tilloy

Add a unit test for autofill popup destruction.

ff81c57... by Olivier Tilloy

Ensure unit tests are locale-independent.

Revision history for this message
Chris Coulson (chrisccoulson) wrote :

I haven't had time to complete the review of this yet, so I've left you a few comments in the meantime to unblock you :)

review: Needs Fixing
Revision history for this message
Chris Coulson (chrisccoulson) wrote :

I've left a few more comments now. I've not yet finished reviewing it though, so there will most likely be some more later.

review: Needs Fixing
~osomon/oxide:autofill updated
f7170cf... by Olivier Tilloy

Fix build errors when rebased on latest master.

12ec53f... by Olivier Tilloy

Always use an InMemoryPrefStore.

Persisting the value of OxideQQuickWebContext::autofillEnabled would be
inconsistent with every other setting exposed by the API
(eg, we don't persist popupBlockerEnabled or doNotTrackEnabled).

2c47ca7... by Olivier Tilloy

Move CreateAutofillPopup to WebContentsClient.

bd0082a... by Olivier Tilloy

Bump version for new WebContext API to 1.23.

b7f468f... by Olivier Tilloy

Drop default case as there's already a branch for every value.

579a028... by Olivier Tilloy

Do not modify oxide::ContentClient to access the application locale.

Instead, expose the application locale as a new method on BrowserPlatformIntegration.

e1aa089... by Olivier Tilloy

Marked a private helper private.

f0aa5a2... by Olivier Tilloy

Ensure that autofill works in incognito mode, as expected.

Revision history for this message
Olivier Tilloy (osomon) wrote :

I addressed the first round of comments from two days ago. Still pending: add tests for autofill behaviour in incognito mode.

~osomon/oxide:autofill updated
1d7be1b... by Olivier Tilloy

Add tests for autofill in incognito webviews.

e48baae... by Olivier Tilloy

Make WebAutofillPopupHost::Init not return anything, for consistency.

4017f9d... by Olivier Tilloy

Remove redundant std::move().

4116cd7... by Olivier Tilloy

Rename methods to start with an uppercase letter, for consistency with newly-written code.

31d4425... by Olivier Tilloy

Take timeout into account.

dc3f850... by Olivier Tilloy

Do not depend on the omnibox component in release builds.

f4c8cba... by Olivier Tilloy

Rename files for consistency with newly-added code.

4fd1d34... by Olivier Tilloy

Remove unused references to gfx::NativeView (always null) in AutofillPopupController.

88dfc51... by Olivier Tilloy

Remove unused method.

31c9a11... by Olivier Tilloy

Make ownership of AutofillPopupController explicit.

Revision history for this message
Olivier Tilloy (osomon) wrote :

I addressed all comments (and answered questions) in the second review round except for the last one (the suggestion to re-implement a custom WebDataServiceWrapper), which is pending.

~osomon/oxide:autofill updated
8dcafd5... by Olivier Tilloy

Fork WebDataServiceWrapper to remove bits that oxide doesn't need.

Revision history for this message
Olivier Tilloy (osomon) wrote :

WebDataServiceWrapper has been forked to remove all the bits that oxide doesn't need, thus removing the need for the dependency on omnibox in a component build.

~osomon/oxide:autofill updated
bc34ffb... by Olivier Tilloy

New FilteredPrefStore class that stores all preferences in memory except for a selected set which are persisted on disk.

133ba6a... by Olivier Tilloy

Unit tests for FilteredPrefStore.

1ac8924... by Olivier Tilloy

Remove stale line that remained after rebasing on master.

Unmerged commits

1ac8924... by Olivier Tilloy

Remove stale line that remained after rebasing on master.

133ba6a... by Olivier Tilloy

Unit tests for FilteredPrefStore.

bc34ffb... by Olivier Tilloy

New FilteredPrefStore class that stores all preferences in memory except for a selected set which are persisted on disk.

8dcafd5... by Olivier Tilloy

Fork WebDataServiceWrapper to remove bits that oxide doesn't need.

31c9a11... by Olivier Tilloy

Make ownership of AutofillPopupController explicit.

88dfc51... by Olivier Tilloy

Remove unused method.

4fd1d34... by Olivier Tilloy

Remove unused references to gfx::NativeView (always null) in AutofillPopupController.

f4c8cba... by Olivier Tilloy

Rename files for consistency with newly-added code.

dc3f850... by Olivier Tilloy

Do not depend on the omnibox component in release builds.

31d4425... by Olivier Tilloy

Take timeout into account.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/qt/core/BUILD.gn b/qt/core/BUILD.gn
index 4a12427..6dd0eb2 100644
--- a/qt/core/BUILD.gn
+++ b/qt/core/BUILD.gn
@@ -92,6 +92,7 @@ source_set("core_sources") {
92 ":core_moc_gen",92 ":core_moc_gen",
93 ":oxide_version",93 ":oxide_version",
94 "//base",94 "//base",
95 "//components/autofill/core/browser",
95 "//components/sessions",96 "//components/sessions",
96 "//content/public/browser",97 "//content/public/browser",
97 "//content/public/common",98 "//content/public/common",
@@ -269,6 +270,8 @@ source_set("core_sources") {
269 "browser/touch_selection/touch_editing_menu_host.h",270 "browser/touch_selection/touch_editing_menu_host.h",
270 "browser/touch_selection/touch_handle_drawable_host.cc",271 "browser/touch_selection/touch_handle_drawable_host.cc",
271 "browser/touch_selection/touch_handle_drawable_host.h",272 "browser/touch_selection/touch_handle_drawable_host.h",
273 "browser/web_autofill_popup_host.cc",
274 "browser/web_autofill_popup_host.h",
272 "browser/web_contents_id_tracker.cc",275 "browser/web_contents_id_tracker.cc",
273 "browser/web_contents_id_tracker.h",276 "browser/web_contents_id_tracker.h",
274 "browser/web_context_menu_host.cc",277 "browser/web_context_menu_host.cc",
@@ -278,6 +281,8 @@ source_set("core_sources") {
278 "browser/web_preferences.cc",281 "browser/web_preferences.cc",
279 "browser/web_preferences.h",282 "browser/web_preferences.h",
280 "common/oxide_qt_export.h",283 "common/oxide_qt_export.h",
284 "glue/autofill_suggestion.cc",
285 "glue/autofill_suggestion.h",
281 "glue/chrome_controller.cc",286 "glue/chrome_controller.cc",
282 "glue/chrome_controller.h",287 "glue/chrome_controller.h",
283 "glue/chrome_controller_client.h",288 "glue/chrome_controller_client.h",
@@ -325,6 +330,8 @@ source_set("core_sources") {
325 "glue/screen_utils.h",330 "glue/screen_utils.h",
326 "glue/touch_editing_menu.h",331 "glue/touch_editing_menu.h",
327 "glue/touch_editing_menu_client.h",332 "glue/touch_editing_menu_client.h",
333 "glue/web_autofill_popup.h",
334 "glue/web_autofill_popup_client.h",
328 "glue/web_context_menu.h",335 "glue/web_context_menu.h",
329 "glue/web_context_menu_actions.h",336 "glue/web_context_menu_actions.h",
330 "glue/web_context_menu_client.h",337 "glue/web_context_menu_client.h",
diff --git a/qt/core/browser/contents_view_impl.cc b/qt/core/browser/contents_view_impl.cc
index e683c42..b648fc6 100644
--- a/qt/core/browser/contents_view_impl.cc
+++ b/qt/core/browser/contents_view_impl.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016 Canonical Ltd.2// Copyright (C) 2016-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
diff --git a/qt/core/browser/oxide_qt_browser_platform_integration.cc b/qt/core/browser/oxide_qt_browser_platform_integration.cc
index 8c6455e..ee2226c 100644
--- a/qt/core/browser/oxide_qt_browser_platform_integration.cc
+++ b/qt/core/browser/oxide_qt_browser_platform_integration.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2014-2016 Canonical Ltd.2// Copyright (C) 2014-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -20,6 +20,7 @@
20#include <QDesktopServices>20#include <QDesktopServices>
21#include <QEvent>21#include <QEvent>
22#include <QGuiApplication>22#include <QGuiApplication>
23#include <QLocale>
23#include <QStyleHints>24#include <QStyleHints>
24#include <QPointer>25#include <QPointer>
25#include <QString>26#include <QString>
@@ -183,6 +184,10 @@ std::string BrowserPlatformIntegration::GetApplicationName() {
183 return application_name_;184 return application_name_;
184}185}
185186
187std::string BrowserPlatformIntegration::GetApplicationLocale() {
188 return QLocale::system().name().toStdString();
189}
190
186std::unique_ptr<oxide::DragSource> BrowserPlatformIntegration::CreateDragSource(191std::unique_ptr<oxide::DragSource> BrowserPlatformIntegration::CreateDragSource(
187 oxide::DragSourceClient* client) {192 oxide::DragSourceClient* client) {
188 return base::WrapUnique(new DragSource(client));193 return base::WrapUnique(new DragSource(client));
diff --git a/qt/core/browser/oxide_qt_browser_platform_integration.h b/qt/core/browser/oxide_qt_browser_platform_integration.h
index 0f7eeb1..f676a1d 100644
--- a/qt/core/browser/oxide_qt_browser_platform_integration.h
+++ b/qt/core/browser/oxide_qt_browser_platform_integration.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2014-2015 Canonical Ltd.2// Copyright (C) 2014-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -63,6 +63,7 @@ class BrowserPlatformIntegration : public QObject,
63 ApplicationState GetApplicationState() override;63 ApplicationState GetApplicationState() override;
64 virtual int GetClickInterval() override;64 virtual int GetClickInterval() override;
65 std::string GetApplicationName() override;65 std::string GetApplicationName() override;
66 std::string GetApplicationLocale() override;
66 std::unique_ptr<oxide::DragSource> CreateDragSource(67 std::unique_ptr<oxide::DragSource> CreateDragSource(
67 oxide::DragSourceClient* client) override;68 oxide::DragSourceClient* client) override;
68 void CreateVibrationManager(69 void CreateVibrationManager(
diff --git a/qt/core/browser/oxide_qt_web_context.cc b/qt/core/browser/oxide_qt_web_context.cc
index 504d165..fc1492f 100644
--- a/qt/core/browser/oxide_qt_web_context.cc
+++ b/qt/core/browser/oxide_qt_web_context.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -138,7 +138,8 @@ struct WebContext::ConstructProperties {
138 devtools_enabled(false),138 devtools_enabled(false),
139 devtools_port(-1),139 devtools_port(-1),
140 legacy_user_agent_override_enabled(false),140 legacy_user_agent_override_enabled(false),
141 do_not_track(false) {}141 do_not_track(false),
142 autofill_enabled(false) {}
142143
143 std::string product;144 std::string product;
144 std::string user_agent;145 std::string user_agent;
@@ -158,6 +159,7 @@ struct WebContext::ConstructProperties {
158 std::vector<UserAgentSettings::UserAgentOverride> user_agent_overrides;159 std::vector<UserAgentSettings::UserAgentOverride> user_agent_overrides;
159 bool legacy_user_agent_override_enabled;160 bool legacy_user_agent_override_enabled;
160 bool do_not_track;161 bool do_not_track;
162 bool autofill_enabled;
161};163};
162164
163class SetCookiesContext : public base::RefCounted<SetCookiesContext> {165class SetCookiesContext : public base::RefCounted<SetCookiesContext> {
@@ -499,6 +501,7 @@ BrowserContext* WebContext::GetContext() {
499 ua_settings->SetIsPopupBlockerEnabled(501 ua_settings->SetIsPopupBlockerEnabled(
500 construct_props_->popup_blocker_enabled);502 construct_props_->popup_blocker_enabled);
501 ua_settings->SetDoNotTrack(construct_props_->do_not_track);503 ua_settings->SetDoNotTrack(construct_props_->do_not_track);
504 ua_settings->SetAutofillEnabled(construct_props_->autofill_enabled);
502505
503 context_->SetCookiePolicy(construct_props_->cookie_policy);506 context_->SetCookiePolicy(construct_props_->cookie_policy);
504507
@@ -999,7 +1002,7 @@ void WebContext::DefaultVideoDeviceChanged() {
999}1002}
10001003
1001bool WebContext::doNotTrack() const {1004bool WebContext::doNotTrack() const {
1002 if (IsInitialized()) {1005 if (IsInitialized()) {
1003 return UserAgentSettings::Get(context_.get())->GetDoNotTrack();1006 return UserAgentSettings::Get(context_.get())->GetDoNotTrack();
1004 }1007 }
10051008
@@ -1014,5 +1017,21 @@ void WebContext::setDoNotTrack(bool dnt) {
1014 }1017 }
1015}1018}
10161019
1020bool WebContext::autofillEnabled() const {
1021 if (IsInitialized()) {
1022 return UserAgentSettings::Get(context_.get())->IsAutofillEnabled();
1023 }
1024
1025 return construct_props_->autofill_enabled;
1026}
1027
1028void WebContext::setAutofillEnabled(bool enabled) {
1029 if (IsInitialized()) {
1030 UserAgentSettings::Get(context_.get())->SetAutofillEnabled(enabled);
1031 } else {
1032 construct_props_->autofill_enabled = enabled;
1033 }
1034}
1035
1017} // namespace qt1036} // namespace qt
1018} // namespace oxide1037} // namespace oxide
diff --git a/qt/core/browser/oxide_qt_web_context.h b/qt/core/browser/oxide_qt_web_context.h
index 1425b38..1dd4134 100644
--- a/qt/core/browser/oxide_qt_web_context.h
+++ b/qt/core/browser/oxide_qt_web_context.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -144,6 +144,9 @@ class WebContext : public WebContextProxy,
144 bool doNotTrack() const override;144 bool doNotTrack() const override;
145 void setDoNotTrack(bool dnt) override;145 void setDoNotTrack(bool dnt) override;
146146
147 bool autofillEnabled() const override;
148 void setAutofillEnabled(bool enabled) override;
149
147 // oxide::MediaCaptureDevicesContextClient implementation150 // oxide::MediaCaptureDevicesContextClient implementation
148 void DefaultAudioDeviceChanged() override;151 void DefaultAudioDeviceChanged() override;
149 void DefaultVideoDeviceChanged() override;152 void DefaultVideoDeviceChanged() override;
diff --git a/qt/core/browser/oxide_qt_web_view.cc b/qt/core/browser/oxide_qt_web_view.cc
index ab4d2d2..dd97d3d 100644
--- a/qt/core/browser/oxide_qt_web_view.cc
+++ b/qt/core/browser/oxide_qt_web_view.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -25,6 +25,7 @@
2525
26#include <QGuiApplication>26#include <QGuiApplication>
27#include <QInputEvent>27#include <QInputEvent>
28#include <QRectF>
28#include <QScreen>29#include <QScreen>
29#include <QString>30#include <QString>
30#include <QtDebug>31#include <QtDebug>
@@ -75,6 +76,7 @@
75#include "qt/core/glue/oxide_qt_web_frame_proxy_client.h"76#include "qt/core/glue/oxide_qt_web_frame_proxy_client.h"
76#include "qt/core/glue/oxide_qt_web_view_proxy_client.h"77#include "qt/core/glue/oxide_qt_web_view_proxy_client.h"
77#include "qt/core/glue/touch_editing_menu.h"78#include "qt/core/glue/touch_editing_menu.h"
79#include "qt/core/glue/web_autofill_popup.h"
78#include "qt/core/glue/web_context_menu.h"80#include "qt/core/glue/web_context_menu.h"
79#include "qt/core/glue/web_context_menu_params.h"81#include "qt/core/glue/web_context_menu_params.h"
80#include "shared/browser/oxide_browser_process_main.h"82#include "shared/browser/oxide_browser_process_main.h"
@@ -103,6 +105,7 @@
103#include "oxide_qt_type_conversions.h"105#include "oxide_qt_type_conversions.h"
104#include "oxide_qt_web_context.h"106#include "oxide_qt_web_context.h"
105#include "oxide_qt_web_frame.h"107#include "oxide_qt_web_frame.h"
108#include "web_autofill_popup_host.h"
106#include "web_contents_id_tracker.h"109#include "web_contents_id_tracker.h"
107#include "web_context_menu_host.h"110#include "web_context_menu_host.h"
108#include "web_preferences.h"111#include "web_preferences.h"
@@ -693,6 +696,28 @@ std::unique_ptr<oxide::WebContextMenu> WebView::CreateContextMenu(
693 return std::move(host);696 return std::move(host);
694}697}
695698
699std::unique_ptr<oxide::WebAutofillPopup> WebView::CreateAutofillPopup(
700 const std::vector<autofill::Suggestion>& suggestions,
701 const gfx::RectF& bounds,
702 oxide::WebAutofillPopupClient* client) {
703 std::unique_ptr<WebAutofillPopupHost> host =
704 base::MakeUnique<WebAutofillPopupHost>(client);
705 QRectF qt_bounds = ToQt(
706 DpiUtils::ConvertChromiumPixelsToQt(bounds, contents_view_->GetScreen()));
707 std::unique_ptr<WebAutofillPopup> popup =
708 aux_ui_factory_->CreateWebAutofillPopup(
709 WebAutofillPopupHost::BuildSuggestions(suggestions),
710 qt_bounds,
711 host.get());
712 if (!popup) {
713 return nullptr;
714 }
715
716 host->Init(std::move(popup));
717
718 return std::move(host);
719}
720
696std::unique_ptr<oxide::TouchEditingMenuController>721std::unique_ptr<oxide::TouchEditingMenuController>
697WebView::CreateOverrideTouchEditingMenuController(722WebView::CreateOverrideTouchEditingMenuController(
698 oxide::TouchEditingMenuControllerClient* client) {723 oxide::TouchEditingMenuControllerClient* client) {
diff --git a/qt/core/browser/oxide_qt_web_view.h b/qt/core/browser/oxide_qt_web_view.h
index 5da67af..f0d3e50 100644
--- a/qt/core/browser/oxide_qt_web_view.h
+++ b/qt/core/browser/oxide_qt_web_view.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -154,6 +154,10 @@ class WebView : public oxide::WebViewClient,
154 const content::ContextMenuParams& params,154 const content::ContextMenuParams& params,
155 const std::vector<content::MenuItem>& items,155 const std::vector<content::MenuItem>& items,
156 oxide::WebContextMenuClient* client) override;156 oxide::WebContextMenuClient* client) override;
157 std::unique_ptr<oxide::WebAutofillPopup> CreateAutofillPopup(
158 const std::vector<autofill::Suggestion>& suggestions,
159 const gfx::RectF& bounds,
160 oxide::WebAutofillPopupClient* client) override;
157 std::unique_ptr<oxide::TouchEditingMenuController>161 std::unique_ptr<oxide::TouchEditingMenuController>
158 CreateOverrideTouchEditingMenuController(162 CreateOverrideTouchEditingMenuController(
159 oxide::TouchEditingMenuControllerClient* client) override;163 oxide::TouchEditingMenuControllerClient* client) override;
diff --git a/qt/core/browser/web_autofill_popup_host.cc b/qt/core/browser/web_autofill_popup_host.cc
160new file mode 100644164new file mode 100644
index 0000000..05fe479
--- /dev/null
+++ b/qt/core/browser/web_autofill_popup_host.cc
@@ -0,0 +1,139 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#include "web_autofill_popup_host.h"
19
20#include "base/logging.h"
21#include "base/strings/utf_string_conversions.h"
22#include "components/autofill/core/browser/popup_item_ids.h"
23#include "components/autofill/core/browser/suggestion.h"
24
25#include "qt/core/glue/web_autofill_popup.h"
26#include "shared/browser/autofill/web_autofill_popup_client.h"
27
28namespace oxide {
29namespace qt {
30
31void WebAutofillPopupHost::Show() {
32 popup_->Show();
33}
34
35void WebAutofillPopupHost::UpdateDataListValues(
36 const std::vector<base::string16>& values,
37 const std::vector<base::string16>& labels) {
38 std::vector<AutofillSuggestion> suggestions;
39 for (unsigned int i = 0; i < values.size(); ++i) {
40 AutofillSuggestion suggestion;
41 suggestion.frontend_id = autofill::POPUP_ITEM_ID_DATALIST_ENTRY;
42 suggestion.type = AutofillSuggestion::Type::DataListEntry;
43 suggestion.value = QString::fromStdString(base::UTF16ToUTF8(values[i]));
44 suggestion.label = QString::fromStdString(base::UTF16ToUTF8(labels[i]));
45 suggestions.push_back(suggestion);
46 }
47
48 if (suggestions.size() >
49 static_cast<size_t>(std::numeric_limits<int>::max() + 1)) {
50 LOG(WARNING)
51 << "Truncating autofill popup - there are too many suggestions!";
52 suggestions.resize(std::numeric_limits<int>::max() + 1);
53 }
54
55 popup_->UpdateDataListValues(suggestions);
56}
57
58void WebAutofillPopupHost::Hide() {
59 popup_->Hide();
60}
61
62void WebAutofillPopupHost::Close() {
63 client_->Close();
64}
65
66void WebAutofillPopupHost::SelectSuggestion(
67 const AutofillSuggestion& suggestion) {
68 client_->SelectSuggestion(suggestion.frontend_id,
69 base::UTF8ToUTF16(suggestion.value.toStdString()));
70}
71
72void WebAutofillPopupHost::ClearSelection() {
73 client_->ClearSelection();
74}
75
76void WebAutofillPopupHost::AcceptSuggestion(
77 const AutofillSuggestion& suggestion) {
78 client_->AcceptSuggestion(suggestion.frontend_id,
79 base::UTF8ToUTF16(suggestion.value.toStdString()));
80}
81
82bool WebAutofillPopupHost::RemoveSuggestion(
83 const AutofillSuggestion& suggestion) {
84 return client_->RemoveSuggestion(
85 suggestion.frontend_id,
86 base::UTF8ToUTF16(suggestion.value.toStdString()));
87}
88
89WebAutofillPopupHost::WebAutofillPopupHost(
90 oxide::WebAutofillPopupClient* client)
91 : client_(client) {}
92
93WebAutofillPopupHost::~WebAutofillPopupHost() = default;
94
95void WebAutofillPopupHost::Init(std::unique_ptr<qt::WebAutofillPopup> popup) {
96 popup_ = std::move(popup);
97}
98
99// static
100std::vector<AutofillSuggestion> WebAutofillPopupHost::BuildSuggestions(
101 const std::vector<autofill::Suggestion>& suggestions) {
102 std::vector<autofill::Suggestion> local_suggestions = suggestions;
103 if (local_suggestions.size() >
104 static_cast<size_t>(std::numeric_limits<int>::max() + 1)) {
105 LOG(WARNING)
106 << "Truncating autofill popup - there are too many suggestions!";
107 local_suggestions.resize(std::numeric_limits<int>::max() + 1);
108 }
109
110 std::vector<AutofillSuggestion> rv;
111 for (const auto& suggestion : local_suggestions) {
112 int fid = suggestion.frontend_id;
113 if (fid > 0 ||
114 fid == autofill::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY ||
115 fid == autofill::POPUP_ITEM_ID_PASSWORD_ENTRY ||
116 fid == autofill::POPUP_ITEM_ID_DATALIST_ENTRY) {
117 AutofillSuggestion as;
118 as.frontend_id = fid;
119 if (fid > 0) {
120 as.type = AutofillSuggestion::Type::ProfileEntry;
121 } else if (fid == autofill::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
122 as.type = AutofillSuggestion::Type::AutoCompleteEntry;
123 } else if (fid == autofill::POPUP_ITEM_ID_PASSWORD_ENTRY) {
124 as.type = AutofillSuggestion::Type::PasswordEntry;
125 } else if (fid == autofill::POPUP_ITEM_ID_DATALIST_ENTRY) {
126 as.type = AutofillSuggestion::Type::DataListEntry;
127 }
128 as.value = QString::fromStdString(base::UTF16ToUTF8(suggestion.value));
129 as.label = QString::fromStdString(base::UTF16ToUTF8(suggestion.label));
130 as.icon = QString::fromStdString(base::UTF16ToUTF8(suggestion.icon));
131 rv.push_back(as);
132 }
133 }
134
135 return std::move(rv);
136}
137
138} // namespace qt
139} // namespace oxide
diff --git a/qt/core/browser/web_autofill_popup_host.h b/qt/core/browser/web_autofill_popup_host.h
0new file mode 100644140new file mode 100644
index 0000000..513e778
--- /dev/null
+++ b/qt/core/browser/web_autofill_popup_host.h
@@ -0,0 +1,78 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_QT_CORE_BROWSER_WEB_AUTOFILL_POPUP_HOST_H_
19#define _OXIDE_QT_CORE_BROWSER_WEB_AUTOFILL_POPUP_HOST_H_
20
21#include <memory>
22#include <vector>
23
24#include "base/macros.h"
25
26#include "qt/core/glue/autofill_suggestion.h"
27#include "qt/core/glue/web_autofill_popup_client.h"
28#include "shared/browser/autofill/web_autofill_popup.h"
29
30namespace autofill {
31struct Suggestion;
32}
33
34namespace oxide {
35
36class WebAutofillPopupClient;
37
38namespace qt {
39
40class WebAutofillPopup;
41
42class WebAutofillPopupHost : public oxide::WebAutofillPopup,
43 public WebAutofillPopupClient {
44 public:
45 WebAutofillPopupHost(oxide::WebAutofillPopupClient* client);
46 ~WebAutofillPopupHost() override;
47
48 void Init(std::unique_ptr<qt::WebAutofillPopup> popup);
49
50 static std::vector<AutofillSuggestion> BuildSuggestions(
51 const std::vector<autofill::Suggestion>& suggestions);
52
53 private:
54 // oxide::WebAutofillPopup implementation
55 void Show() override;
56 void UpdateDataListValues(
57 const std::vector<base::string16>& values,
58 const std::vector<base::string16>& labels) override;
59 void Hide() override;
60
61 // WebAutofillPopupClient implementation
62 void Close() override;
63 void SelectSuggestion(const AutofillSuggestion& suggestion) override;
64 void ClearSelection() override;
65 void AcceptSuggestion(const AutofillSuggestion& suggestion) override;
66 bool RemoveSuggestion(const AutofillSuggestion& suggestion) override;
67
68 oxide::WebAutofillPopupClient* client_; // Owns us
69
70 std::unique_ptr<qt::WebAutofillPopup> popup_;
71
72 DISALLOW_COPY_AND_ASSIGN(WebAutofillPopupHost);
73};
74
75} // namespace qt
76} // namespace oxide
77
78#endif // _OXIDE_QT_CORE_BROWSER_WEB_AUTOFILL_POPUP_HOST_H_
diff --git a/qt/core/glue/autofill_suggestion.cc b/qt/core/glue/autofill_suggestion.cc
0new file mode 10064479new file mode 100644
index 0000000..5344a3d
--- /dev/null
+++ b/qt/core/glue/autofill_suggestion.cc
@@ -0,0 +1,30 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#include "autofill_suggestion.h"
19
20namespace oxide {
21namespace qt {
22
23AutofillSuggestion::AutofillSuggestion() = default;
24
25AutofillSuggestion::AutofillSuggestion(const AutofillSuggestion& other) = default;
26
27AutofillSuggestion::~AutofillSuggestion() = default;
28
29} // namespace qt
30} // namespace oxide
diff --git a/qt/core/glue/autofill_suggestion.h b/qt/core/glue/autofill_suggestion.h
0new file mode 10064431new file mode 100644
index 0000000..01e4ad2
--- /dev/null
+++ b/qt/core/glue/autofill_suggestion.h
@@ -0,0 +1,50 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_QT_CORE_GLUE_AUTOFILL_SUGGESTION_H_
19#define _OXIDE_QT_CORE_GLUE_AUTOFILL_SUGGESTION_H_
20
21#include <QString>
22
23#include "qt/core/api/oxideqglobal.h"
24
25namespace oxide {
26namespace qt {
27
28struct OXIDE_QTCORE_EXPORT AutofillSuggestion {
29 AutofillSuggestion();
30 AutofillSuggestion(const AutofillSuggestion& other);
31 ~AutofillSuggestion();
32
33 enum class Type {
34 ProfileEntry,
35 AutoCompleteEntry,
36 PasswordEntry,
37 DataListEntry
38 };
39
40 int frontend_id;
41 Type type;
42 QString value;
43 QString label;
44 QString icon;
45};
46
47} // namespace qt
48} // namespace oxide
49
50#endif // _OXIDE_QT_CORE_GLUE_AUTOFILL_SUGGESTION_H_
diff --git a/qt/core/glue/auxiliary_ui_factory.h b/qt/core/glue/auxiliary_ui_factory.h
index 4150b1b..557cbcf 100644
--- a/qt/core/glue/auxiliary_ui_factory.h
+++ b/qt/core/glue/auxiliary_ui_factory.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016 Canonical Ltd.2// Copyright (C) 2016-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -23,10 +23,12 @@
2323
24#include <QtGlobal>24#include <QtGlobal>
2525
26#include "qt/core/glue/autofill_suggestion.h"
26#include "qt/core/glue/edit_capability_flags.h"27#include "qt/core/glue/edit_capability_flags.h"
27#include "qt/core/glue/menu_item.h"28#include "qt/core/glue/menu_item.h"
2829
29QT_BEGIN_NAMESPACE30QT_BEGIN_NAMESPACE
31class QRectF;
30class QString;32class QString;
31class QUrl;33class QUrl;
32QT_END_NAMESPACE34QT_END_NAMESPACE
@@ -39,6 +41,8 @@ class JavaScriptDialogClient;
39enum class JavaScriptDialogType;41enum class JavaScriptDialogType;
40class TouchEditingMenu;42class TouchEditingMenu;
41class TouchEditingMenuClient;43class TouchEditingMenuClient;
44class WebAutofillPopup;
45class WebAutofillPopupClient;
42class WebContextMenu;46class WebContextMenu;
43class WebContextMenuClient;47class WebContextMenuClient;
44struct WebContextMenuParams;48struct WebContextMenuParams;
@@ -52,6 +56,11 @@ class AuxiliaryUIFactory {
52 const std::vector<MenuItem>& items,56 const std::vector<MenuItem>& items,
53 WebContextMenuClient* client) = 0;57 WebContextMenuClient* client) = 0;
5458
59 virtual std::unique_ptr<WebAutofillPopup> CreateWebAutofillPopup(
60 const std::vector<AutofillSuggestion>& suggestions,
61 const QRectF& bounds,
62 WebAutofillPopupClient* client) = 0;
63
55 virtual std::unique_ptr<TouchEditingMenu> CreateTouchEditingMenu(64 virtual std::unique_ptr<TouchEditingMenu> CreateTouchEditingMenu(
56 EditCapabilityFlags edit_flags,65 EditCapabilityFlags edit_flags,
57 TouchEditingMenuClient* client) = 0;66 TouchEditingMenuClient* client) = 0;
diff --git a/qt/core/glue/oxide_qt_web_context_proxy.h b/qt/core/glue/oxide_qt_web_context_proxy.h
index ff13a71..49f0180 100644
--- a/qt/core/glue/oxide_qt_web_context_proxy.h
+++ b/qt/core/glue/oxide_qt_web_context_proxy.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -137,6 +137,9 @@ class OXIDE_QTCORE_EXPORT WebContextProxy : public ProxyBase<WebContext> {
137137
138 virtual bool doNotTrack() const = 0;138 virtual bool doNotTrack() const = 0;
139 virtual void setDoNotTrack(bool dnt) = 0;139 virtual void setDoNotTrack(bool dnt) = 0;
140
141 virtual bool autofillEnabled() const = 0;
142 virtual void setAutofillEnabled(bool enabled) = 0;
140};143};
141144
142} // namespace qt145} // namespace qt
diff --git a/qt/core/glue/web_autofill_popup.h b/qt/core/glue/web_autofill_popup.h
143new file mode 100644146new file mode 100644
index 0000000..c28d561
--- /dev/null
+++ b/qt/core/glue/web_autofill_popup.h
@@ -0,0 +1,43 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_QT_CORE_GLUE_WEB_AUTOFILL_POPUP_H_
19#define _OXIDE_QT_CORE_GLUE_WEB_AUTOFILL_POPUP_H_
20
21#include <vector>
22
23namespace oxide {
24namespace qt {
25
26class AutofillSuggestion;
27
28class WebAutofillPopup {
29 public:
30 virtual ~WebAutofillPopup() = default;
31
32 virtual void Show() = 0;
33
34 virtual void UpdateDataListValues(
35 const std::vector<AutofillSuggestion>& suggestions) = 0;
36
37 virtual void Hide() = 0;
38};
39
40} // namespace qt
41} // namespace oxide
42
43#endif // _OXIDE_QT_CORE_GLUE_WEB_AUTOFILL_POPUP_H_
diff --git a/qt/core/glue/web_autofill_popup_client.h b/qt/core/glue/web_autofill_popup_client.h
0new file mode 10064444new file mode 100644
index 0000000..b31cae4
--- /dev/null
+++ b/qt/core/glue/web_autofill_popup_client.h
@@ -0,0 +1,40 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_QT_CORE_GLUE_WEB_AUTOFILL_POPUP_CLIENT_H_
19#define _OXIDE_QT_CORE_GLUE_WEB_AUTOFILL_POPUP_CLIENT_H_
20
21namespace oxide {
22namespace qt {
23
24struct AutofillSuggestion;
25
26class WebAutofillPopupClient {
27 public:
28 virtual ~WebAutofillPopupClient() {}
29
30 virtual void Close() = 0;
31 virtual void SelectSuggestion(const AutofillSuggestion& suggestion) = 0;
32 virtual void ClearSelection() = 0;
33 virtual void AcceptSuggestion(const AutofillSuggestion& suggestion) = 0;
34 virtual bool RemoveSuggestion(const AutofillSuggestion& suggestion) = 0;
35};
36
37} // namespace qt
38} // namespace oxide
39
40#endif // _OXIDE_QT_CORE_GLUE_WEB_AUTOFILL_POPUP_CLIENT_H_
diff --git a/qt/qmlplugin/oxide.qmltypes b/qt/qmlplugin/oxide.qmltypes
index 8a111b6..ab9848f 100644
--- a/qt/qmlplugin/oxide.qmltypes
+++ b/qt/qmlplugin/oxide.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
4// It is used for QML tooling purposes only.4// It is used for QML tooling purposes only.
5//5//
6// This file was auto-generated by:6// This file was auto-generated by:
7// 'qmlplugindump -v -noinstantiate com.canonical.Oxide 1.19 com/canonical/Oxide'7// 'qmlplugindump -v -noinstantiate com.canonical.Oxide 1.23 com/canonical/Oxide'
88
9Module {9Module {
10 dependencies: []10 dependencies: ["QtQuick 2.0"]
11 Component {11 Component {
12 name: "OxideQCertificateError"12 name: "OxideQCertificateError"
13 prototype: "QObject"13 prototype: "QObject"
@@ -414,11 +414,12 @@ Module {
414 prototype: "QObject"414 prototype: "QObject"
415 exports: [415 exports: [
416 "WebContext 1.0",416 "WebContext 1.0",
417 "WebContext 1.23",
417 "WebContext 1.3",418 "WebContext 1.3",
418 "WebContext 1.6",419 "WebContext 1.6",
419 "WebContext 1.9"420 "WebContext 1.9"
420 ]421 ]
421 exportMetaObjectRevisions: [0, 1, 2, 3]422 exportMetaObjectRevisions: [0, 1, 2, 3, 4]
422 Enum {423 Enum {
423 name: "CookiePolicy"424 name: "CookiePolicy"
424 values: {425 values: {
@@ -475,6 +476,7 @@ Module {
475 Property { name: "defaultVideoCaptureDeviceId"; revision: 3; type: "string" }476 Property { name: "defaultVideoCaptureDeviceId"; revision: 3; type: "string" }
476 Property { name: "userAgentOverrides"; revision: 3; type: "QVariantList" }477 Property { name: "userAgentOverrides"; revision: 3; type: "QVariantList" }
477 Property { name: "doNotTrackEnabled"; revision: 3; type: "bool" }478 Property { name: "doNotTrackEnabled"; revision: 3; type: "bool" }
479 Property { name: "autofillEnabled"; revision: 4; type: "bool" }
478 Signal { name: "devtoolsBindIpChanged" }480 Signal { name: "devtoolsBindIpChanged" }
479 Signal { name: "hostMappingRulesChanged"; revision: 1 }481 Signal { name: "hostMappingRulesChanged"; revision: 1 }
480 Signal { name: "allowedExtraUrlSchemesChanged"; revision: 1 }482 Signal { name: "allowedExtraUrlSchemesChanged"; revision: 1 }
@@ -483,6 +485,7 @@ Module {
483 Signal { name: "defaultVideoCaptureDeviceIdChanged"; revision: 3 }485 Signal { name: "defaultVideoCaptureDeviceIdChanged"; revision: 3 }
484 Signal { name: "userAgentOverridesChanged"; revision: 3 }486 Signal { name: "userAgentOverridesChanged"; revision: 3 }
485 Signal { name: "doNotTrackEnabledChanged"; revision: 3 }487 Signal { name: "doNotTrackEnabledChanged"; revision: 3 }
488 Signal { name: "autofillEnabledChanged"; revision: 4 }
486 Method {489 Method {
487 name: "addUserScript"490 name: "addUserScript"
488 Parameter { name: "script"; type: "OxideQQuickUserScript"; isPointer: true }491 Parameter { name: "script"; type: "OxideQQuickUserScript"; isPointer: true }
@@ -575,7 +578,7 @@ Module {
575 "WebView 1.8",578 "WebView 1.8",
576 "WebView 1.9"579 "WebView 1.9"
577 ]580 ]
578 exportMetaObjectRevisions: [0, 6, 7, 8, 9, 1, 2, 3, 4, 5]581 exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
579 attachedType: "OxideQQuickWebViewAttached"582 attachedType: "OxideQQuickWebViewAttached"
580 Enum {583 Enum {
581 name: "LogMessageSeverityLevel"584 name: "LogMessageSeverityLevel"
@@ -972,423 +975,4 @@ Module {
972 Property { name: "touchEnabled"; type: "bool" }975 Property { name: "touchEnabled"; type: "bool" }
973 Signal { name: "sansSerifFontFamilyChanged" }976 Signal { name: "sansSerifFontFamilyChanged" }
974 }977 }
975 Component {
976 name: "QAbstractItemModel"
977 prototype: "QObject"
978 Enum {
979 name: "LayoutChangeHint"
980 values: {
981 "NoLayoutChangeHint": 0,
982 "VerticalSortHint": 1,
983 "HorizontalSortHint": 2
984 }
985 }
986 Signal {
987 name: "dataChanged"
988 Parameter { name: "topLeft"; type: "QModelIndex" }
989 Parameter { name: "bottomRight"; type: "QModelIndex" }
990 Parameter { name: "roles"; type: "QVector<int>" }
991 }
992 Signal {
993 name: "dataChanged"
994 Parameter { name: "topLeft"; type: "QModelIndex" }
995 Parameter { name: "bottomRight"; type: "QModelIndex" }
996 }
997 Signal {
998 name: "headerDataChanged"
999 Parameter { name: "orientation"; type: "Qt::Orientation" }
1000 Parameter { name: "first"; type: "int" }
1001 Parameter { name: "last"; type: "int" }
1002 }
1003 Signal {
1004 name: "layoutChanged"
1005 Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
1006 Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
1007 }
1008 Signal {
1009 name: "layoutChanged"
1010 Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
1011 }
1012 Signal { name: "layoutChanged" }
1013 Signal {
1014 name: "layoutAboutToBeChanged"
1015 Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
1016 Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
1017 }
1018 Signal {
1019 name: "layoutAboutToBeChanged"
1020 Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
1021 }
1022 Signal { name: "layoutAboutToBeChanged" }
1023 Signal {
1024 name: "rowsAboutToBeInserted"
1025 Parameter { name: "parent"; type: "QModelIndex" }
1026 Parameter { name: "first"; type: "int" }
1027 Parameter { name: "last"; type: "int" }
1028 }
1029 Signal {
1030 name: "rowsInserted"
1031 Parameter { name: "parent"; type: "QModelIndex" }
1032 Parameter { name: "first"; type: "int" }
1033 Parameter { name: "last"; type: "int" }
1034 }
1035 Signal {
1036 name: "rowsAboutToBeRemoved"
1037 Parameter { name: "parent"; type: "QModelIndex" }
1038 Parameter { name: "first"; type: "int" }
1039 Parameter { name: "last"; type: "int" }
1040 }
1041 Signal {
1042 name: "rowsRemoved"
1043 Parameter { name: "parent"; type: "QModelIndex" }
1044 Parameter { name: "first"; type: "int" }
1045 Parameter { name: "last"; type: "int" }
1046 }
1047 Signal {
1048 name: "columnsAboutToBeInserted"
1049 Parameter { name: "parent"; type: "QModelIndex" }
1050 Parameter { name: "first"; type: "int" }
1051 Parameter { name: "last"; type: "int" }
1052 }
1053 Signal {
1054 name: "columnsInserted"
1055 Parameter { name: "parent"; type: "QModelIndex" }
1056 Parameter { name: "first"; type: "int" }
1057 Parameter { name: "last"; type: "int" }
1058 }
1059 Signal {
1060 name: "columnsAboutToBeRemoved"
1061 Parameter { name: "parent"; type: "QModelIndex" }
1062 Parameter { name: "first"; type: "int" }
1063 Parameter { name: "last"; type: "int" }
1064 }
1065 Signal {
1066 name: "columnsRemoved"
1067 Parameter { name: "parent"; type: "QModelIndex" }
1068 Parameter { name: "first"; type: "int" }
1069 Parameter { name: "last"; type: "int" }
1070 }
1071 Signal { name: "modelAboutToBeReset" }
1072 Signal { name: "modelReset" }
1073 Signal {
1074 name: "rowsAboutToBeMoved"
1075 Parameter { name: "sourceParent"; type: "QModelIndex" }
1076 Parameter { name: "sourceStart"; type: "int" }
1077 Parameter { name: "sourceEnd"; type: "int" }
1078 Parameter { name: "destinationParent"; type: "QModelIndex" }
1079 Parameter { name: "destinationRow"; type: "int" }
1080 }
1081 Signal {
1082 name: "rowsMoved"
1083 Parameter { name: "parent"; type: "QModelIndex" }
1084 Parameter { name: "start"; type: "int" }
1085 Parameter { name: "end"; type: "int" }
1086 Parameter { name: "destination"; type: "QModelIndex" }
1087 Parameter { name: "row"; type: "int" }
1088 }
1089 Signal {
1090 name: "columnsAboutToBeMoved"
1091 Parameter { name: "sourceParent"; type: "QModelIndex" }
1092 Parameter { name: "sourceStart"; type: "int" }
1093 Parameter { name: "sourceEnd"; type: "int" }
1094 Parameter { name: "destinationParent"; type: "QModelIndex" }
1095 Parameter { name: "destinationColumn"; type: "int" }
1096 }
1097 Signal {
1098 name: "columnsMoved"
1099 Parameter { name: "parent"; type: "QModelIndex" }
1100 Parameter { name: "start"; type: "int" }
1101 Parameter { name: "end"; type: "int" }
1102 Parameter { name: "destination"; type: "QModelIndex" }
1103 Parameter { name: "column"; type: "int" }
1104 }
1105 Method { name: "submit"; type: "bool" }
1106 Method { name: "revert" }
1107 Method {
1108 name: "hasIndex"
1109 type: "bool"
1110 Parameter { name: "row"; type: "int" }
1111 Parameter { name: "column"; type: "int" }
1112 Parameter { name: "parent"; type: "QModelIndex" }
1113 }
1114 Method {
1115 name: "hasIndex"
1116 type: "bool"
1117 Parameter { name: "row"; type: "int" }
1118 Parameter { name: "column"; type: "int" }
1119 }
1120 Method {
1121 name: "index"
1122 type: "QModelIndex"
1123 Parameter { name: "row"; type: "int" }
1124 Parameter { name: "column"; type: "int" }
1125 Parameter { name: "parent"; type: "QModelIndex" }
1126 }
1127 Method {
1128 name: "index"
1129 type: "QModelIndex"
1130 Parameter { name: "row"; type: "int" }
1131 Parameter { name: "column"; type: "int" }
1132 }
1133 Method {
1134 name: "parent"
1135 type: "QModelIndex"
1136 Parameter { name: "child"; type: "QModelIndex" }
1137 }
1138 Method {
1139 name: "sibling"
1140 type: "QModelIndex"
1141 Parameter { name: "row"; type: "int" }
1142 Parameter { name: "column"; type: "int" }
1143 Parameter { name: "idx"; type: "QModelIndex" }
1144 }
1145 Method {
1146 name: "rowCount"
1147 type: "int"
1148 Parameter { name: "parent"; type: "QModelIndex" }
1149 }
1150 Method { name: "rowCount"; type: "int" }
1151 Method {
1152 name: "columnCount"
1153 type: "int"
1154 Parameter { name: "parent"; type: "QModelIndex" }
1155 }
1156 Method { name: "columnCount"; type: "int" }
1157 Method {
1158 name: "hasChildren"
1159 type: "bool"
1160 Parameter { name: "parent"; type: "QModelIndex" }
1161 }
1162 Method { name: "hasChildren"; type: "bool" }
1163 Method {
1164 name: "data"
1165 type: "QVariant"
1166 Parameter { name: "index"; type: "QModelIndex" }
1167 Parameter { name: "role"; type: "int" }
1168 }
1169 Method {
1170 name: "data"
1171 type: "QVariant"
1172 Parameter { name: "index"; type: "QModelIndex" }
1173 }
1174 Method {
1175 name: "setData"
1176 type: "bool"
1177 Parameter { name: "index"; type: "QModelIndex" }
1178 Parameter { name: "value"; type: "QVariant" }
1179 Parameter { name: "role"; type: "int" }
1180 }
1181 Method {
1182 name: "setData"
1183 type: "bool"
1184 Parameter { name: "index"; type: "QModelIndex" }
1185 Parameter { name: "value"; type: "QVariant" }
1186 }
1187 Method {
1188 name: "headerData"
1189 type: "QVariant"
1190 Parameter { name: "section"; type: "int" }
1191 Parameter { name: "orientation"; type: "Qt::Orientation" }
1192 Parameter { name: "role"; type: "int" }
1193 }
1194 Method {
1195 name: "headerData"
1196 type: "QVariant"
1197 Parameter { name: "section"; type: "int" }
1198 Parameter { name: "orientation"; type: "Qt::Orientation" }
1199 }
1200 Method {
1201 name: "fetchMore"
1202 Parameter { name: "parent"; type: "QModelIndex" }
1203 }
1204 Method {
1205 name: "canFetchMore"
1206 type: "bool"
1207 Parameter { name: "parent"; type: "QModelIndex" }
1208 }
1209 Method {
1210 name: "flags"
1211 type: "Qt::ItemFlags"
1212 Parameter { name: "index"; type: "QModelIndex" }
1213 }
1214 Method {
1215 name: "match"
1216 type: "QModelIndexList"
1217 Parameter { name: "start"; type: "QModelIndex" }
1218 Parameter { name: "role"; type: "int" }
1219 Parameter { name: "value"; type: "QVariant" }
1220 Parameter { name: "hits"; type: "int" }
1221 Parameter { name: "flags"; type: "Qt::MatchFlags" }
1222 }
1223 Method {
1224 name: "match"
1225 type: "QModelIndexList"
1226 Parameter { name: "start"; type: "QModelIndex" }
1227 Parameter { name: "role"; type: "int" }
1228 Parameter { name: "value"; type: "QVariant" }
1229 Parameter { name: "hits"; type: "int" }
1230 }
1231 Method {
1232 name: "match"
1233 type: "QModelIndexList"
1234 Parameter { name: "start"; type: "QModelIndex" }
1235 Parameter { name: "role"; type: "int" }
1236 Parameter { name: "value"; type: "QVariant" }
1237 }
1238 }
1239 Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
1240 Component {
1241 name: "QQuickItem"
1242 defaultProperty: "data"
1243 prototype: "QObject"
1244 Enum {
1245 name: "TransformOrigin"
1246 values: {
1247 "TopLeft": 0,
1248 "Top": 1,
1249 "TopRight": 2,
1250 "Left": 3,
1251 "Center": 4,
1252 "Right": 5,
1253 "BottomLeft": 6,
1254 "Bottom": 7,
1255 "BottomRight": 8
1256 }
1257 }
1258 Property { name: "parent"; type: "QQuickItem"; isPointer: true }
1259 Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
1260 Property { name: "resources"; type: "QObject"; isList: true; isReadonly: true }
1261 Property { name: "children"; type: "QQuickItem"; isList: true; isReadonly: true }
1262 Property { name: "x"; type: "double" }
1263 Property { name: "y"; type: "double" }
1264 Property { name: "z"; type: "double" }
1265 Property { name: "width"; type: "double" }
1266 Property { name: "height"; type: "double" }
1267 Property { name: "opacity"; type: "double" }
1268 Property { name: "enabled"; type: "bool" }
1269 Property { name: "visible"; type: "bool" }
1270 Property { name: "visibleChildren"; type: "QQuickItem"; isList: true; isReadonly: true }
1271 Property { name: "states"; type: "QQuickState"; isList: true; isReadonly: true }
1272 Property { name: "transitions"; type: "QQuickTransition"; isList: true; isReadonly: true }
1273 Property { name: "state"; type: "string" }
1274 Property { name: "childrenRect"; type: "QRectF"; isReadonly: true }
1275 Property { name: "anchors"; type: "QQuickAnchors"; isReadonly: true; isPointer: true }
1276 Property { name: "left"; type: "QQuickAnchorLine"; isReadonly: true }
1277 Property { name: "right"; type: "QQuickAnchorLine"; isReadonly: true }
1278 Property { name: "horizontalCenter"; type: "QQuickAnchorLine"; isReadonly: true }
1279 Property { name: "top"; type: "QQuickAnchorLine"; isReadonly: true }
1280 Property { name: "bottom"; type: "QQuickAnchorLine"; isReadonly: true }
1281 Property { name: "verticalCenter"; type: "QQuickAnchorLine"; isReadonly: true }
1282 Property { name: "baseline"; type: "QQuickAnchorLine"; isReadonly: true }
1283 Property { name: "baselineOffset"; type: "double" }
1284 Property { name: "clip"; type: "bool" }
1285 Property { name: "focus"; type: "bool" }
1286 Property { name: "activeFocus"; type: "bool"; isReadonly: true }
1287 Property { name: "activeFocusOnTab"; revision: 1; type: "bool" }
1288 Property { name: "rotation"; type: "double" }
1289 Property { name: "scale"; type: "double" }
1290 Property { name: "transformOrigin"; type: "TransformOrigin" }
1291 Property { name: "transformOriginPoint"; type: "QPointF"; isReadonly: true }
1292 Property { name: "transform"; type: "QQuickTransform"; isList: true; isReadonly: true }
1293 Property { name: "smooth"; type: "bool" }
1294 Property { name: "antialiasing"; type: "bool" }
1295 Property { name: "implicitWidth"; type: "double" }
1296 Property { name: "implicitHeight"; type: "double" }
1297 Property { name: "layer"; type: "QQuickItemLayer"; isReadonly: true; isPointer: true }
1298 Signal {
1299 name: "childrenRectChanged"
1300 Parameter { type: "QRectF" }
1301 }
1302 Signal {
1303 name: "baselineOffsetChanged"
1304 Parameter { type: "double" }
1305 }
1306 Signal {
1307 name: "stateChanged"
1308 Parameter { type: "string" }
1309 }
1310 Signal {
1311 name: "focusChanged"
1312 Parameter { type: "bool" }
1313 }
1314 Signal {
1315 name: "activeFocusChanged"
1316 Parameter { type: "bool" }
1317 }
1318 Signal {
1319 name: "activeFocusOnTabChanged"
1320 revision: 1
1321 Parameter { type: "bool" }
1322 }
1323 Signal {
1324 name: "parentChanged"
1325 Parameter { type: "QQuickItem"; isPointer: true }
1326 }
1327 Signal {
1328 name: "transformOriginChanged"
1329 Parameter { type: "TransformOrigin" }
1330 }
1331 Signal {
1332 name: "smoothChanged"
1333 Parameter { type: "bool" }
1334 }
1335 Signal {
1336 name: "antialiasingChanged"
1337 Parameter { type: "bool" }
1338 }
1339 Signal {
1340 name: "clipChanged"
1341 Parameter { type: "bool" }
1342 }
1343 Signal {
1344 name: "windowChanged"
1345 revision: 1
1346 Parameter { name: "window"; type: "QQuickWindow"; isPointer: true }
1347 }
1348 Method { name: "update" }
1349 Method {
1350 name: "grabToImage"
1351 revision: 2
1352 type: "bool"
1353 Parameter { name: "callback"; type: "QJSValue" }
1354 Parameter { name: "targetSize"; type: "QSize" }
1355 }
1356 Method {
1357 name: "grabToImage"
1358 revision: 2
1359 type: "bool"
1360 Parameter { name: "callback"; type: "QJSValue" }
1361 }
1362 Method {
1363 name: "contains"
1364 type: "bool"
1365 Parameter { name: "point"; type: "QPointF" }
1366 }
1367 Method {
1368 name: "mapFromItem"
1369 Parameter { type: "QQmlV4Function"; isPointer: true }
1370 }
1371 Method {
1372 name: "mapToItem"
1373 Parameter { type: "QQmlV4Function"; isPointer: true }
1374 }
1375 Method { name: "forceActiveFocus" }
1376 Method {
1377 name: "forceActiveFocus"
1378 Parameter { name: "reason"; type: "Qt::FocusReason" }
1379 }
1380 Method {
1381 name: "nextItemInFocusChain"
1382 revision: 1
1383 type: "QQuickItem*"
1384 Parameter { name: "forward"; type: "bool" }
1385 }
1386 Method { name: "nextItemInFocusChain"; revision: 1; type: "QQuickItem*" }
1387 Method {
1388 name: "childAt"
1389 type: "QQuickItem*"
1390 Parameter { name: "x"; type: "double" }
1391 Parameter { name: "y"; type: "double" }
1392 }
1393 }
1394}978}
diff --git a/qt/qmlplugin/oxide_qml_plugin.cc b/qt/qmlplugin/oxide_qml_plugin.cc
index 1597b5d..b56fb51 100644
--- a/qt/qmlplugin/oxide_qml_plugin.cc
+++ b/qt/qmlplugin/oxide_qml_plugin.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -215,6 +215,8 @@ class OxideQmlPlugin : public QQmlExtensionPlugin {
215 qmlRegisterUncreatableType<OxideQQuickNavigationHistory, 1>(215 qmlRegisterUncreatableType<OxideQQuickNavigationHistory, 1>(
216 uri, 1, 19, "NavigationHistory",216 uri, 1, 19, "NavigationHistory",
217 "NavigationHistory is accessed via WebView.navigationHistory");217 "NavigationHistory is accessed via WebView.navigationHistory");
218
219 qmlRegisterType<OxideQQuickWebContext, 4>(uri, 1, 23, "WebContext");
218 }220 }
219};221};
220222
diff --git a/qt/quick/api/oxideqquickwebcontext.cc b/qt/quick/api/oxideqquickwebcontext.cc
index 6fe1ef7..1946af0 100644
--- a/qt/quick/api/oxideqquickwebcontext.cc
+++ b/qt/quick/api/oxideqquickwebcontext.cc
@@ -1561,4 +1561,35 @@ void OxideQQuickWebContext::setDoNotTrack(bool dnt) {
1561 emit doNotTrackEnabledChanged();1561 emit doNotTrackEnabledChanged();
1562}1562}
15631563
1564/*!
1565\qmlproperty bool WebContext::autofillEnabled
1566\since OxideQt 1.22
1567
1568Whether to enable autofill. The default is false.
1569
1570Autofill is most probably neither useful nor desirable outside of the browser
1571use case, and as such is disabled by default.
1572
1573The base Oxide WebView does not know how to display autofill suggestions,
1574use the WebView from the Oxide.Ubuntu module if you need them.
1575*/
1576
1577bool OxideQQuickWebContext::autofillEnabled() const {
1578 Q_D(const OxideQQuickWebContext);
1579
1580 return d->proxy_->autofillEnabled();
1581}
1582
1583void OxideQQuickWebContext::setAutofillEnabled(bool enabled) {
1584 Q_D(OxideQQuickWebContext);
1585
1586 if (autofillEnabled() == enabled) {
1587 return;
1588 }
1589
1590 d->proxy_->setAutofillEnabled(enabled);
1591
1592 emit autofillEnabledChanged();
1593}
1594
1564#include "moc_oxideqquickwebcontext.cpp"1595#include "moc_oxideqquickwebcontext.cpp"
diff --git a/qt/quick/api/oxideqquickwebcontext.h b/qt/quick/api/oxideqquickwebcontext.h
index 99de73a..f8ca6fa 100644
--- a/qt/quick/api/oxideqquickwebcontext.h
+++ b/qt/quick/api/oxideqquickwebcontext.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2015 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -77,6 +77,8 @@ class OXIDE_QTQUICK_EXPORT OxideQQuickWebContext : public QObject,
7777
78 Q_PROPERTY(bool doNotTrackEnabled READ doNotTrack WRITE setDoNotTrack NOTIFY doNotTrackEnabledChanged REVISION 3)78 Q_PROPERTY(bool doNotTrackEnabled READ doNotTrack WRITE setDoNotTrack NOTIFY doNotTrackEnabledChanged REVISION 3)
7979
80 Q_PROPERTY(bool autofillEnabled READ autofillEnabled WRITE setAutofillEnabled NOTIFY autofillEnabledChanged REVISION 4)
81
80 Q_ENUMS(CookiePolicy)82 Q_ENUMS(CookiePolicy)
81 Q_ENUMS(SessionCookieMode)83 Q_ENUMS(SessionCookieMode)
8284
@@ -173,6 +175,9 @@ class OXIDE_QTQUICK_EXPORT OxideQQuickWebContext : public QObject,
173 bool doNotTrack() const;175 bool doNotTrack() const;
174 void setDoNotTrack(bool dnt);176 void setDoNotTrack(bool dnt);
175177
178 bool autofillEnabled() const;
179 void setAutofillEnabled(bool enabled);
180
176 Q_SIGNALS:181 Q_SIGNALS:
177 void productChanged();182 void productChanged();
178 void userAgentChanged();183 void userAgentChanged();
@@ -196,6 +201,7 @@ class OXIDE_QTQUICK_EXPORT OxideQQuickWebContext : public QObject,
196 Q_REVISION(3) void defaultVideoCaptureDeviceIdChanged();201 Q_REVISION(3) void defaultVideoCaptureDeviceIdChanged();
197 Q_REVISION(3) void userAgentOverridesChanged();202 Q_REVISION(3) void userAgentOverridesChanged();
198 Q_REVISION(3) void doNotTrackEnabledChanged();203 Q_REVISION(3) void doNotTrackEnabledChanged();
204 Q_REVISION(4) void autofillEnabledChanged();
199205
200 protected:206 protected:
201 // QQmlParserStatus implementation207 // QQmlParserStatus implementation
diff --git a/qt/quick/qquick_legacy_auxiliary_ui_factory.cc b/qt/quick/qquick_legacy_auxiliary_ui_factory.cc
index c0084c2..e50b6c3 100644
--- a/qt/quick/qquick_legacy_auxiliary_ui_factory.cc
+++ b/qt/quick/qquick_legacy_auxiliary_ui_factory.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016 Canonical Ltd.2// Copyright (C) 2016-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -21,6 +21,7 @@
2121
22#include "qt/core/glue/javascript_dialog_type.h"22#include "qt/core/glue/javascript_dialog_type.h"
23#include "qt/core/glue/touch_editing_menu.h"23#include "qt/core/glue/touch_editing_menu.h"
24#include "qt/core/glue/web_autofill_popup.h"
2425
25#include "qquick_legacy_alert_dialog.h"26#include "qquick_legacy_alert_dialog.h"
26#include "qquick_legacy_before_unload_dialog.h"27#include "qquick_legacy_before_unload_dialog.h"
@@ -31,11 +32,13 @@
31namespace oxide {32namespace oxide {
32namespace qquick {33namespace qquick {
3334
35using qt::AutofillSuggestion;
34using qt::EditCapabilityFlags;36using qt::EditCapabilityFlags;
35using qt::JavaScriptDialogClient;37using qt::JavaScriptDialogClient;
36using qt::JavaScriptDialogType;38using qt::JavaScriptDialogType;
37using qt::MenuItem;39using qt::MenuItem;
38using qt::TouchEditingMenuClient;40using qt::TouchEditingMenuClient;
41using qt::WebAutofillPopupClient;
39using qt::WebContextMenuClient;42using qt::WebContextMenuClient;
40using qt::WebContextMenuParams;43using qt::WebContextMenuParams;
4144
@@ -52,6 +55,15 @@ LegacyAuxiliaryUIFactory::CreateWebContextMenu(
52 new LegacyWebContextMenu(item_, context_menu_, params, client));55 new LegacyWebContextMenu(item_, context_menu_, params, client));
53}56}
5457
58std::unique_ptr<qt::WebAutofillPopup>
59LegacyAuxiliaryUIFactory::CreateWebAutofillPopup(
60 const std::vector<AutofillSuggestion>& suggestions,
61 const QRectF& bounds,
62 WebAutofillPopupClient* client) {
63 Q_ASSERT(0);
64 return nullptr;
65}
66
55std::unique_ptr<qt::TouchEditingMenu>67std::unique_ptr<qt::TouchEditingMenu>
56LegacyAuxiliaryUIFactory::CreateTouchEditingMenu(68LegacyAuxiliaryUIFactory::CreateTouchEditingMenu(
57 EditCapabilityFlags edit_flags,69 EditCapabilityFlags edit_flags,
diff --git a/qt/quick/qquick_legacy_auxiliary_ui_factory.h b/qt/quick/qquick_legacy_auxiliary_ui_factory.h
index a7cec12..e969e6e 100644
--- a/qt/quick/qquick_legacy_auxiliary_ui_factory.h
+++ b/qt/quick/qquick_legacy_auxiliary_ui_factory.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016 Canonical Ltd.2// Copyright (C) 2016-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -59,6 +59,10 @@ class LegacyAuxiliaryUIFactory : public qt::AuxiliaryUIFactory {
59 const qt::WebContextMenuParams& params,59 const qt::WebContextMenuParams& params,
60 const std::vector<qt::MenuItem>& items,60 const std::vector<qt::MenuItem>& items,
61 qt::WebContextMenuClient* client) override;61 qt::WebContextMenuClient* client) override;
62 std::unique_ptr<qt::WebAutofillPopup> CreateWebAutofillPopup(
63 const std::vector<qt::AutofillSuggestion>& suggestions,
64 const QRectF& bounds,
65 qt::WebAutofillPopupClient* client) override;
62 std::unique_ptr<qt::TouchEditingMenu> CreateTouchEditingMenu(66 std::unique_ptr<qt::TouchEditingMenu> CreateTouchEditingMenu(
63 qt::EditCapabilityFlags edit_flags,67 qt::EditCapabilityFlags edit_flags,
64 qt::TouchEditingMenuClient* client) override;68 qt::TouchEditingMenuClient* client) override;
diff --git a/qt/tests/qmltests/api/tst_WebContext_autofillEnabled.qml b/qt/tests/qmltests/api/tst_WebContext_autofillEnabled.qml
65new file mode 10064469new file mode 100644
index 0000000..7350196
--- /dev/null
+++ b/qt/tests/qmltests/api/tst_WebContext_autofillEnabled.qml
@@ -0,0 +1,38 @@
1import QtQuick 2.0
2import QtTest 1.0
3import com.canonical.Oxide 1.22
4import Oxide.testsupport 1.0
5
6TestWebView {
7 id: webView
8
9 SignalSpy {
10 id: spy
11 signalName: "autofillEnabledChanged"
12 }
13
14 TestCase {
15 name: "WebContext_autofillEnabled"
16 when: windowShown
17
18 function test_WebContext_autofillEnabled1_default() {
19 compare(webView.context.autofillEnabled, false,
20 "Autofill should be disabled by default");
21 }
22
23 function test_WebContext_autofillEnabled2_get_set() {
24 spy.target = webView.context;
25
26 verify(!webView.context.autofillEnabled);
27 compare(spy.count, 0);
28
29 webView.context.autofillEnabled = true;
30 compare(spy.count, 1);
31 verify(webView.context.autofillEnabled);
32
33 webView.context.autofillEnabled = false;
34 compare(spy.count, 2);
35 verify(!webView.context.autofillEnabled);
36 }
37 }
38}
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.html b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.html
0new file mode 10064439new file mode 100644
index 0000000..e28755c
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.html
@@ -0,0 +1,23 @@
1<html>
2 <body>
3 <form action="empty.html">
4 <input id="firstname" name="firstname" type="text" required autofocus />
5 <br />
6 <input id="lastname" name="lastname" type="text" required />
7 <br />
8 <input id="email" name="email" type="text" required />
9 <br />
10 <input id="country" name="country" type="text" required />
11 <br />
12 <input id="state" name="state" type="text" />
13 <br />
14 <input id="zipcode" name="zipcode" type="text" required />
15 <br />
16 <input id="city" name="city" type="text" required />
17 <br />
18 <input id="street" name="street" type="text" required />
19 <br />
20 <input type="submit" value="Submit" />
21 </form>
22 </body>
23</html>
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml
0new file mode 10064424new file mode 100644
index 0000000..e65d221
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_autofill_profiles.qml
@@ -0,0 +1,300 @@
1import QtQuick 2.0
2import QtTest 1.0
3import com.canonical.Oxide 1.22
4import Oxide.Ubuntu 1.0
5import Oxide.testsupport 1.0
6import Ubuntu.Components 1.3
7
8FocusScope {
9 width: 800
10 height: 600
11
12 focus: true
13
14 UbuntuTestWebView {
15 id: webView
16 objectName: "webView"
17 anchors.fill: parent
18 visible: false
19 }
20
21 UbuntuTestWebView {
22 id: incognitoWebView
23 objectName: "incognitoWebView"
24 anchors.fill: parent
25 incognito: true
26 visible: false
27 }
28
29 TestCase {
30 name: "WebViewAutofillPopup_autofill_profiles"
31 when: windowShown
32
33 function loadForm(webView) {
34 webView.visible = true;
35 webView.focus = true;
36 webView.context.autofillEnabled = true;
37 webView.url =
38 "http://testsuite/tst_WebViewAutofillPopup_autofill_profiles.html";
39 verify(webView.waitForLoadSucceeded());
40 }
41
42 function verify_field_focused(webView, field) {
43 verify(TestUtils.waitFor(function() {
44 return webView.getTestApi().evaluateCode(
45 "document.activeElement.id") == field; }));
46 }
47
48 function compare_field_value(webView, field, value) {
49 verify(TestUtils.waitFor(function() {
50 return webView.getTestApi().evaluateCode(
51 "document.querySelector('#%1').value".arg(field)) == value; }));
52 }
53
54 function typeStringInField(webView, string, field) {
55 verify_field_focused(webView, field);
56 for (var i = 0; i < string.length; ++i) {
57 keyClick(string[i]);
58 }
59 compare_field_value(webView, field, string);
60 }
61
62 function inputAndValidateProfile(webView, data) {
63 var fields = ["firstname", "lastname", "email", "country", "state",
64 "zipcode", "city", "street"];
65 for (var i = 0; i < fields.length; ++i) {
66 typeStringInField(webView, data[i], fields[i]);
67 keyClick(Qt.Key_Tab);
68 }
69 keyClick(Qt.Key_Enter);
70 verify(webView.waitForLoadSucceeded());
71 loadForm(webView);
72 }
73
74 function initTestCase() {
75 loadForm(webView);
76
77 // Initial population of the autofill profiles database
78 var data = [
79 ["John", "Doe", "john.doe@nospam.org",
80 "US", "New York", "10016", "NYC", "Park Avenue"],
81 ["John", "Lennon", "john@thebeatles.com",
82 "UK", "", "L25 6DA", "Liverpool", "Beaconsfield Road"],
83 ["Bruce", "Lee", "bruce@lee.com",
84 "US", "California", "94108", "San Francisco", "Joice Street"],
85 ];
86 for (var i = 0; i < data.length; ++i) {
87 inputAndValidateProfile(webView, data[i]);
88 }
89 }
90
91 function getAutofillPopup(webView) {
92 return TestSupport.findItemInScene(
93 TestWindow.rootItem, "%1_WebAutofillPopup".arg(webView.objectName));
94 }
95
96 function waitForAutofillPopupToClose(webView) {
97 var popup = getAutofillPopup(webView);
98 if (!popup) {
99 return true;
100 }
101
102 var helper = TestSupport.createQObjectTestHelper(popup);
103
104 return TestUtils.waitFor(function() {
105 return !getAutofillPopup(webView); }) &&
106 TestUtils.waitFor(function() { return helper.destroyed; });
107 }
108
109 function waitForAutofillPopup(webView, timeout) {
110 return TestUtils.waitFor(function() {
111 return !!getAutofillPopup(webView) &&
112 getAutofillPopup(webView).visible; },
113 timeout);
114 }
115
116 function getSuggestion(webView, index) {
117 return TestSupport.findItemInScene(
118 TestWindow.rootItem,
119 "%1_WebAutofillPopup_item%2".arg(webView.objectName).arg(index));
120 }
121
122 function compareBoundsToClientRect(bounds, rect) {
123 compare(bounds.x, rect.x);
124 compare(bounds.y, rect.y);
125 compare(bounds.width, rect.width);
126 compare(bounds.height, rect.height);
127 }
128
129 function init() {
130 loadForm(webView);
131 }
132
133 function get_webviews_data() {
134 var data = [ { webView: webView } ];
135 if (incognitoWebView.incognito) {
136 // When run in single process mode, incognito cannot be set
137 data.push({ webView: incognitoWebView });
138 }
139 return data;
140 }
141
142 function test_initial_state_data() {
143 return get_webviews_data();
144 }
145
146 function test_initial_state(data) {
147 loadForm(data.webView);
148 typeStringInField(data.webView, "jo", "firstname");
149 var popup = getAutofillPopup(data.webView);
150 var r = data.webView.getTestApi()
151 .getBoundingClientRectForSelector("#firstname");
152 compareBoundsToClientRect(popup.elementBounds, r);
153 compare(popup.currentIndex, -1);
154 compare(popup.count, 2);
155 compare(getSuggestion(data.webView, 0).value, "John");
156 compare(getSuggestion(data.webView, 1).value, "John");
157 data.webView.visible = false;
158 }
159
160 function test_toggle_autofillEnabled_data() {
161 return get_webviews_data();
162 }
163
164 function test_toggle_autofillEnabled(data) {
165 loadForm(data.webView);
166 typeStringInField(data.webView, "j", "firstname");
167 verify(waitForAutofillPopup(data.webView));
168 keyClick(Qt.Key_Backspace);
169 verify(waitForAutofillPopupToClose(data.webView));
170
171 data.webView.context.autofillEnabled = false;
172 typeStringInField(data.webView, "j", "firstname");
173 verify(!waitForAutofillPopup(data.webView, 1000));
174 keyClick(Qt.Key_Backspace);
175
176 data.webView.context.autofillEnabled = true;
177 typeStringInField(data.webView, "j", "firstname");
178 verify(waitForAutofillPopup(data.webView));
179 data.webView.visible = false;
180 }
181
182 function test_escape_dismisses_popup_and_resets_field_value_data() {
183 return get_webviews_data();
184 }
185
186 function test_escape_dismisses_popup_and_resets_field_value(data) {
187 loadForm(data.webView);
188 typeStringInField(data.webView, "br", "firstname");
189 verify(waitForAutofillPopup(data.webView));
190 var popup = getAutofillPopup(data.webView);
191 compare(popup.count, 1);
192 compare(getSuggestion(data.webView, 0).value, "Bruce");
193 keyClick(Qt.Key_Down);
194 tryCompare(popup, "currentIndex", 0);
195 keyClick(Qt.Key_Escape);
196 verify(waitForAutofillPopupToClose(data.webView));
197 compare_field_value(data.webView, "firstname", "br");
198 compare_field_value(data.webView, "lastname", "");
199 compare_field_value(data.webView, "email", "");
200 compare_field_value(data.webView, "country", "");
201 compare_field_value(data.webView, "state", "");
202 compare_field_value(data.webView, "zipcode", "");
203 compare_field_value(data.webView, "city", "");
204 compare_field_value(data.webView, "street", "");
205 data.webView.visible = false;
206 }
207
208 function test_validate_suggestion_with_mouse_data() {
209 return get_webviews_data();
210 }
211
212 function test_validate_suggestion_with_mouse(data) {
213 loadForm(data.webView);
214 typeStringInField(data.webView, "br", "firstname");
215 verify(waitForAutofillPopup(data.webView));
216 var popup = getAutofillPopup(data.webView);
217 compare(popup.count, 1);
218 compare(getSuggestion(data.webView, 0).value, "Bruce");
219 var item = getSuggestion(data.webView, 0);
220 mouseClick(item);
221 verify(waitForAutofillPopupToClose(data.webView));
222 verify_field_focused(data.webView, "firstname");
223 compare_field_value(data.webView, "firstname", "Bruce");
224 compare_field_value(data.webView, "lastname", "Lee");
225 compare_field_value(data.webView, "email", "bruce@lee.com");
226 compare_field_value(data.webView, "state", "California");
227 compare_field_value(data.webView, "zipcode", "94108");
228 compare_field_value(data.webView, "city", "San Francisco");
229 compare_field_value(data.webView, "street", "Joice Street");
230 data.webView.visible = false;
231 }
232
233 function test_validate_suggestion_with_keyboard_data() {
234 return [
235 { webView: webView, key: Qt.Key_Enter, focus: "lastname" },
236 { webView: webView, key: Qt.Key_Return, focus: "lastname" },
237 { webView: webView, key: Qt.Key_Tab, focus: "email" },
238 { webView: incognitoWebView, key: Qt.Key_Enter, focus: "lastname" },
239 { webView: incognitoWebView, key: Qt.Key_Return, focus: "lastname" },
240 { webView: incognitoWebView, key: Qt.Key_Tab, focus: "email" },
241 ];
242 }
243
244 function test_validate_suggestion_with_keyboard(data) {
245 loadForm(data.webView);
246 keyClick(Qt.Key_Tab);
247 typeStringInField(data.webView, "len", "lastname");
248 var popup = getAutofillPopup(data.webView);
249 compare(popup.count, 1);
250 compare(getSuggestion(data.webView, 0).value, "Lennon");
251 keyClick(Qt.Key_Down);
252 tryCompare(popup, "currentIndex", 0);
253 keyClick(data.key);
254 verify(waitForAutofillPopupToClose(data.webView));
255 verify_field_focused(data.webView, data.focus);
256 compare_field_value(data.webView, "firstname", "John");
257 compare_field_value(data.webView, "lastname", "Lennon");
258 compare_field_value(data.webView, "email", "john@thebeatles.com");
259 compare_field_value(data.webView, "state", "");
260 compare_field_value(data.webView, "zipcode", "L25 6DA");
261 compare_field_value(data.webView, "city", "Liverpool");
262 compare_field_value(data.webView, "street", "Beaconsfield Road");
263 data.webView.visible = false;
264 }
265
266 function test_shiftdel_deletes_suggestion() {
267 var data = ["Paul", "McCartney", "paul@thebeatles.com",
268 "UK", "", "L18 1DE", "Liverpool", "Penny Lane"];
269 inputAndValidateProfile(webView, data);
270 for (var i = 0; i < 6; ++i) {
271 keyClick(Qt.Key_Tab);
272 }
273 typeStringInField(webView, "Live", "city");
274 verify(waitForAutofillPopup(webView));
275 var popup = getAutofillPopup(webView);
276 compare(popup.count, 2);
277 compare(getSuggestion(webView, 0).label, "Penny Lane");
278 compare(getSuggestion(webView, 1).label, "Beaconsfield Road");
279 keyClick(Qt.Key_Down);
280 tryCompare(popup, "currentIndex", 0);
281 keyClick(Qt.Key_Delete, Qt.ShiftModifier);
282 tryCompare(popup, "currentIndex", -1);
283 tryCompare(popup, "count", 1);
284 compare(getSuggestion(webView, 0).label, "Beaconsfield Road");
285 }
286
287 function test_incognito_profile_not_saved() {
288 if (!incognitoWebView.incognito) {
289 skip("WebView.incognito cannot be set in single process mode");
290 }
291 loadForm(incognitoWebView);
292 var data = ["Paul", "McCartney", "paul@thebeatles.com",
293 "UK", "", "L18 1DE", "Liverpool", "Penny Lane"];
294 inputAndValidateProfile(incognitoWebView, data);
295 typeStringInField(incognitoWebView, "P", "firstname");
296 verify(!waitForAutofillPopup(incognitoWebView, 1000));
297 incognitoWebView.visible = false;
298 }
299 }
300}
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.html b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.html
0new file mode 100644301new file mode 100644
index 0000000..cded135
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.html
@@ -0,0 +1,37 @@
1<html>
2 <body>
3 <form action="tst_WebViewAutofillPopup_datalist.html">
4 <input id="static" name="static" list="staticdatalist" type="text" autofocus />
5 <datalist id="staticdatalist">
6 <option>bar</option>
7 <option>baz</option>
8 <option>qux</option>
9 </datalist>
10 <br />
11 <input id="static2" name="static2" list="staticdatalist" type="text" />
12 <br />
13 <input id="dynamic" name="dynamic" list="dynamicdatalist" type="text" />
14 <datalist id="dynamicdatalist"></datalist>
15 <script>
16 function createDatalist() {
17 var value = document.getElementById("dynamic").value;
18 var list = [];
19 if (value == "f") {
20 list = ["foo", "flip"];
21 } else if (value == "b") {
22 list = ["bar", "beard", "beam"];
23 }
24 var datalist = document.getElementById("dynamicdatalist");
25 datalist.innerHTML = "";
26 for (var i = 0; i < list.length; ++i) {
27 var option = document.createElement('option');
28 option.value = list[i];
29 datalist.appendChild(option);
30 }
31 }
32 document.getElementById("dynamic").addEventListener("input", createDatalist);
33 </script>
34 <input type="submit" value="Submit" />
35 </form>
36 </body>
37</html>
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.qml b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.qml
0new file mode 10064438new file mode 100644
index 0000000..1288857
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_datalist.qml
@@ -0,0 +1,157 @@
1import QtQuick 2.0
2import QtTest 1.0
3import com.canonical.Oxide 1.22
4import Oxide.Ubuntu 1.0
5import Oxide.testsupport 1.0
6import Ubuntu.Components 1.3
7
8UbuntuTestWebView {
9 id: webView
10 objectName: "webView"
11
12 width: 800
13 height: 600
14
15 focus: true
16
17 TestCase {
18 name: "WebViewAutofillPopup_datalist"
19 when: windowShown
20
21 function verify_field_focused(field) {
22 verify(TestUtils.waitFor(function() {
23 return webView.getTestApi().evaluateCode(
24 "document.activeElement.id") == field; }));
25 }
26
27 function compare_field_value(field, value) {
28 verify(TestUtils.waitFor(function() {
29 return webView.getTestApi().evaluateCode(
30 "document.querySelector('#%1').value".arg(field)) == value; }));
31 }
32
33 function typeStringInField(string, field) {
34 verify_field_focused(field);
35 for (var i = 0; i < string.length; ++i) {
36 keyClick(string[i]);
37 }
38 compare_field_value(field, string);
39 }
40
41 function initTestCase() {
42 webView.context.autofillEnabled = true;
43 }
44
45 function getAutofillPopup() {
46 return TestSupport.findItemInScene(TestWindow.rootItem,
47 "webView_WebAutofillPopup");
48 }
49
50 function waitForAutofillPopupToClose() {
51 var popup = getAutofillPopup();
52 if (!popup) {
53 return true;
54 }
55
56 var helper = TestSupport.createQObjectTestHelper(popup);
57
58 return TestUtils.waitFor(function() { return !getAutofillPopup(); }) &&
59 TestUtils.waitFor(function() { return helper.destroyed; });
60 }
61
62 function waitForAutofillPopup() {
63 return TestUtils.waitFor(function() {
64 return !!getAutofillPopup() && getAutofillPopup().visible; });
65 }
66
67 function getSuggestion(index) {
68 return TestSupport.findItemInScene(
69 TestWindow.rootItem, "webView_WebAutofillPopup_item%1".arg(index));
70 }
71
72 function init() {
73 webView.url =
74 "http://testsuite/tst_WebViewAutofillPopup_datalist.html";
75 verify(webView.waitForLoadSucceeded());
76 }
77
78 function test_static_datalist() {
79 typeStringInField("b", "static");
80 verify(waitForAutofillPopup());
81 var popup = getAutofillPopup();
82 compare(popup.count, 2);
83 compare(getSuggestion(0).value, "bar");
84 compare(getSuggestion(1).value, "baz");
85 keyClick("a");
86 compare(popup.count, 2);
87 keyClick("e");
88 verify(waitForAutofillPopupToClose());
89
90 keyClick(Qt.Key_Backspace);
91 verify(waitForAutofillPopup());
92 popup = getAutofillPopup();
93 compare(popup.count, 2);
94 keyClick(Qt.Key_Backspace);
95 keyClick(Qt.Key_Backspace);
96 verify(waitForAutofillPopupToClose());
97
98 typeStringInField("q", "static");
99 verify(waitForAutofillPopup());
100 popup = getAutofillPopup();
101 compare(popup.count, 1);
102 compare(getSuggestion(0).value, "qux");
103 compare(popup.currentIndex, -1);
104 keyClick(Qt.Key_Down);
105 compare(popup.currentIndex, 0);
106 keyClick(Qt.Key_Return);
107 verify(waitForAutofillPopupToClose());
108 compare_field_value("static", "qux");
109 }
110
111 function test_combined_datalist_autofill_suggestions() {
112 keyClick(Qt.Key_Tab);
113 typeStringInField("quantal", "static2");
114 keyClick(Qt.Key_Enter);
115 verify(webView.waitForLoadSucceeded());
116
117 keyClick(Qt.Key_Tab);
118 typeStringInField("q", "static2");
119 verify(waitForAutofillPopup());
120 var popup = getAutofillPopup();
121 compare(popup.count, 2);
122 compare(getSuggestion(0).value, "qux");
123 compare(getSuggestion(1).value, "quantal");
124 }
125
126 function test_dynamic_datalist() {
127 keyClick(Qt.Key_Tab);
128 keyClick(Qt.Key_Tab);
129 typeStringInField("f", "dynamic");
130 verify(waitForAutofillPopup());
131 var popup = getAutofillPopup();
132 compare(popup.count, 2);
133 compare(getSuggestion(0).value, "foo");
134 compare(getSuggestion(1).value, "flip");
135 keyClick("a");
136 verify(waitForAutofillPopupToClose());
137 keyClick(Qt.Key_Backspace);
138 verify(waitForAutofillPopup());
139 keyClick(Qt.Key_Backspace);
140 verify(waitForAutofillPopupToClose());
141 compare_field_value("dynamic", "");
142
143 typeStringInField("b", "dynamic");
144 verify(waitForAutofillPopup());
145 popup = getAutofillPopup();
146 compare(popup.count, 3);
147 compare(getSuggestion(0).value, "bar");
148 compare(getSuggestion(1).value, "beard");
149 compare(getSuggestion(2).value, "beam");
150 keyClick(Qt.Key_Up);
151 compare(popup.currentIndex, 2);
152 keyClick(Qt.Key_Enter);
153 verify(waitForAutofillPopupToClose());
154 compare_field_value("dynamic", "beam");
155 }
156 }
157}
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.html b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.html
0new file mode 100644158new file mode 100644
index 0000000..8a712e6
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.html
@@ -0,0 +1,11 @@
1<html>
2 <body>
3 <form action="empty.html">
4 <input id="username" name="username" type="text" required autofocus />
5 <br />
6 <input id="password" name="password" type="password" required />
7 <br />
8 <input type="submit" value="Submit" />
9 </form>
10 </body>
11</html>
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.qml b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.qml
0new file mode 10064412new file mode 100644
index 0000000..b1aede3
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_passwords.qml
@@ -0,0 +1,105 @@
1import QtQuick 2.0
2import QtTest 1.0
3import com.canonical.Oxide 1.22
4import Oxide.Ubuntu 1.0
5import Oxide.testsupport 1.0
6import Ubuntu.Components 1.3
7
8UbuntuTestWebView {
9 id: webView
10 objectName: "webView"
11
12 width: 800
13 height: 600
14
15 focus: true
16
17 TestCase {
18 name: "WebViewAutofillPopup_passwords"
19 when: windowShown
20
21 function loadForm() {
22 webView.url =
23 "http://testsuite/tst_WebViewAutofillPopup_passwords.html";
24 verify(webView.waitForLoadSucceeded());
25 }
26
27 function verify_field_focused(field) {
28 verify(TestUtils.waitFor(function() {
29 return webView.getTestApi().evaluateCode(
30 "document.activeElement.id") == field; }));
31 }
32
33 function compare_field_value(field, value) {
34 verify(TestUtils.waitFor(function() {
35 return webView.getTestApi().evaluateCode(
36 "document.querySelector('#%1').value".arg(field)) == value; }));
37 }
38
39 function typeStringInField(string, field) {
40 verify_field_focused(field);
41 for (var i = 0; i < string.length; ++i) {
42 keyClick(string[i]);
43 }
44 compare_field_value(field, string);
45 }
46
47 function initTestCase() {
48 webView.context.autofillEnabled = true;
49 }
50
51 function getAutofillPopup() {
52 return TestSupport.findItemInScene(TestWindow.rootItem,
53 "webView_WebAutofillPopup");
54 }
55
56 function waitForAutofillPopupToClose() {
57 var popup = getAutofillPopup();
58 if (!popup) {
59 return true;
60 }
61
62 var helper = TestSupport.createQObjectTestHelper(popup);
63
64 return TestUtils.waitFor(function() { return !getAutofillPopup(); }) &&
65 TestUtils.waitFor(function() { return helper.destroyed; });
66 }
67
68 function waitForAutofillPopup(timeout) {
69 return TestUtils.waitFor(function() {
70 return !!getAutofillPopup() && getAutofillPopup().visible; },
71 timeout);
72 }
73
74 function getSuggestion(index) {
75 return TestSupport.findItemInScene(
76 TestWindow.rootItem, "webView_WebAutofillPopup_item%1".arg(index));
77 }
78
79 function init() {
80 loadForm();
81 }
82
83 // Autofill is not implemented yet for passwords
84 function test_passwords_not_autofilled() {
85 typeStringInField("myuser", "username");
86 keyClick(Qt.Key_Tab);
87 typeStringInField("mypass", "password");
88 keyClick(Qt.Key_Enter);
89 verify(webView.waitForLoadSucceeded());
90
91 loadForm();
92 typeStringInField("my", "username");
93 verify(waitForAutofillPopup());
94 var popup = getAutofillPopup();
95 compare(popup.count, 1);
96 compare(getSuggestion(0).value, "myuser");
97 keyClick(Qt.Key_Down);
98 compare(popup.currentIndex, 0);
99 keyClick(Qt.Key_Enter);
100 verify(waitForAutofillPopupToClose());
101 compare_field_value("username", "myuser");
102 compare_field_value("password", "");
103 }
104 }
105}
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.html b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.html
0new file mode 100644106new file mode 100644
index 0000000..7389fe5
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.html
@@ -0,0 +1,11 @@
1<html>
2 <body>
3 <form action="empty.html">
4 <input id="field1" name="field1" type="text" autofocus />
5 <br />
6 <input id="field2" name="field2" type="text" />
7 <br />
8 <input type="submit" value="Submit" />
9 </form>
10 </body>
11</html>
diff --git a/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.qml b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.qml
0new file mode 10064412new file mode 100644
index 0000000..26a88fb
--- /dev/null
+++ b/qt/tests/qmltests/ubuntu_ui/tst_WebViewAutofillPopup_single_fields.qml
@@ -0,0 +1,359 @@
1import QtQuick 2.0
2import QtTest 1.0
3import com.canonical.Oxide 1.22
4import Oxide.Ubuntu 1.0
5import Oxide.testsupport 1.0
6import Ubuntu.Components 1.3
7
8FocusScope {
9 id: testRoot
10
11 width: 800
12 height: 600
13
14 focus: true
15
16 UbuntuTestWebView {
17 id: webView
18 objectName: "webView"
19 anchors.fill: parent
20 visible: false
21 }
22
23 UbuntuTestWebView {
24 id: incognitoWebView
25 objectName: "incognitoWebView"
26 anchors.fill: parent
27 incognito: true
28 visible: false
29 }
30
31 Component {
32 id: webViewFactory
33 UbuntuTestWebView {
34 objectName: "webView2"
35 anchors.fill: parent
36 }
37 }
38
39 TestCase {
40 name: "WebViewAutofillPopup_single_fields"
41 when: windowShown
42
43 function loadForm(webView) {
44 webView.visible = true;
45 webView.focus = true;
46 webView.context.autofillEnabled = true;
47 webView.url =
48 "http://testsuite/tst_WebViewAutofillPopup_single_fields.html";
49 verify(webView.waitForLoadSucceeded());
50 }
51
52 function verify_field_focused(webView, field) {
53 verify(TestUtils.waitFor(function() {
54 return webView.getTestApi().evaluateCode(
55 "document.activeElement.id") == field; }));
56 }
57
58 function compare_field_value(webView, field, value) {
59 verify(TestUtils.waitFor(function() {
60 return webView.getTestApi().evaluateCode(
61 "document.querySelector('#%1').value".arg(field)) == value; }));
62 }
63
64 function typeStringInField(webView, string, field) {
65 verify_field_focused(webView, field);
66 for (var i = 0; i < string.length; ++i) {
67 keyClick(string[i]);
68 }
69 compare_field_value(webView, field, string);
70 }
71
72 function initTestCase() {
73 loadForm(webView);
74 // Initial population of the autofill database
75 var data = ["foo", "for", "four"];
76 for (var i = 0; i < data.length; ++i) {
77 webView.url =
78 "http://testsuite/tst_WebViewAutofillPopup_single_fields.html";
79 verify(webView.waitForLoadSucceeded());
80 typeStringInField(webView, data[i], "field1");
81 keyClick(Qt.Key_Enter);
82 verify(webView.waitForLoadSucceeded());
83 }
84 }
85
86 function getAutofillPopup(webView) {
87 return TestSupport.findItemInScene(
88 TestWindow.rootItem, "%1_WebAutofillPopup".arg(webView.objectName));
89 }
90
91 function waitForAutofillPopupToClose(webView) {
92 var popup = getAutofillPopup(webView);
93 if (!popup) {
94 return true;
95 }
96
97 var helper = TestSupport.createQObjectTestHelper(popup);
98
99 return TestUtils.waitFor(function() {
100 return !getAutofillPopup(webView); }) &&
101 TestUtils.waitFor(function() { return helper.destroyed; });
102 }
103
104 function waitForAutofillPopup(webView, timeout) {
105 return TestUtils.waitFor(function() {
106 return !!getAutofillPopup(webView) &&
107 getAutofillPopup(webView).visible; },
108 timeout);
109 }
110
111 function getSuggestion(webView, index) {
112 return TestSupport.findItemInScene(
113 TestWindow.rootItem,
114 "%1_WebAutofillPopup_item%2".arg(webView.objectName).arg(index));
115 }
116
117 function compareBoundsToClientRect(bounds, rect) {
118 compare(bounds.x, rect.x);
119 compare(bounds.y, rect.y);
120 compare(bounds.width, rect.width);
121 compare(bounds.height, rect.height);
122 }
123
124 function init() {
125 loadForm(webView);
126 }
127
128 function get_webviews_data() {
129 var data = [ { webView: webView } ];
130 if (incognitoWebView.incognito) {
131 // When run in single process mode, incognito cannot be set
132 data.push({ webView: incognitoWebView });
133 }
134 return data;
135 }
136
137 function test_initial_state_data() {
138 return get_webviews_data();
139 }
140
141 function test_initial_state(data) {
142 loadForm(data.webView);
143 typeStringInField(data.webView, "f", "field1");
144 verify(waitForAutofillPopup(data.webView));
145 var popup = getAutofillPopup(data.webView);
146 var r =
147 data.webView.getTestApi().getBoundingClientRectForSelector("#field1");
148 compareBoundsToClientRect(popup.elementBounds, r);
149 compare(popup.currentIndex, -1);
150 compare(popup.count, 3);
151 compare(getSuggestion(data.webView, 0).value, "foo");
152 compare(getSuggestion(data.webView, 1).value, "for");
153 compare(getSuggestion(data.webView, 2).value, "four");
154 data.webView.visible = false;
155 }
156
157 function test_destroy_on_webview_close() {
158 var webView2 = webViewFactory.createObject(testRoot);
159 loadForm(webView2);
160 typeStringInField(webView2, "f", "field1");
161
162 verify(TestUtils.waitFor(function() {
163 return !!getAutofillPopup(webView2) &&
164 getAutofillPopup(webView2).visible; }));
165 var popup = getAutofillPopup(webView2);
166 var helper = TestSupport.createQObjectTestHelper(popup);
167
168 webView2.destroy();
169 verify(TestUtils.waitFor(function() { return helper.destroyed; }));
170 }
171
172 function test_down_arrow_key_navigation_data() {
173 return get_webviews_data();
174 }
175
176 function test_down_arrow_key_navigation(data) {
177 loadForm(data.webView);
178 typeStringInField(data.webView, "f", "field1");
179 verify(waitForAutofillPopup(data.webView));
180 var popup = getAutofillPopup(data.webView);
181 keyClick(Qt.Key_Down);
182 compare(popup.currentIndex, 0);
183 keyClick(Qt.Key_Down);
184 compare(popup.currentIndex, 1);
185 keyClick(Qt.Key_Down);
186 compare(popup.currentIndex, 2);
187 keyClick(Qt.Key_Down);
188 compare(popup.currentIndex, 0);
189 data.webView.visible = false;
190 }
191
192 function test_up_arrow_key_navigation_data() {
193 return get_webviews_data();
194 }
195
196 function test_up_arrow_key_navigation(data) {
197 loadForm(data.webView);
198 typeStringInField(data.webView, "f", "field1");
199 verify(waitForAutofillPopup(data.webView));
200 var popup = getAutofillPopup(data.webView);
201 keyClick(Qt.Key_Up);
202 compare(popup.currentIndex, 2);
203 keyClick(Qt.Key_Up);
204 compare(popup.currentIndex, 1);
205 keyClick(Qt.Key_Up);
206 compare(popup.currentIndex, 0);
207 keyClick(Qt.Key_Up);
208 compare(popup.currentIndex, 2);
209 data.webView.visible = false;
210 }
211
212 function test_escape_dismisses_popup_data() {
213 return get_webviews_data();
214 }
215
216 function test_escape_dismisses_popup(data) {
217 loadForm(data.webView);
218 typeStringInField(data.webView, "f", "field1");
219 verify(waitForAutofillPopup(data.webView));
220 keyClick(Qt.Key_Escape);
221 verify(waitForAutofillPopupToClose(data.webView));
222 data.webView.visible = false;
223 }
224
225 function test_escape_dismisses_popup_and_resets_field_value_data() {
226 return get_webviews_data();
227 }
228
229 function test_escape_dismisses_popup_and_resets_field_value(data) {
230 loadForm(data.webView);
231 typeStringInField(data.webView, "f", "field1");
232 verify(waitForAutofillPopup(data.webView));
233 var popup = getAutofillPopup(data.webView);
234 keyClick(Qt.Key_Down);
235 compare(popup.currentIndex, 0);
236 keyClick(Qt.Key_Escape);
237 verify(waitForAutofillPopupToClose(data.webView));
238 compare_field_value(data.webView, "field1", "f");
239 data.webView.visible = false;
240 }
241
242 function test_validate_suggestion_with_mouse_data() {
243 return get_webviews_data();
244 }
245
246 function test_validate_suggestion_with_mouse(data) {
247 loadForm(data.webView);
248 typeStringInField(data.webView, "f", "field1");
249 verify(waitForAutofillPopup(data.webView));
250 var popup = getAutofillPopup(data.webView);
251 var item = getSuggestion(data.webView, 1);
252 mouseClick(item);
253 verify(waitForAutofillPopupToClose(data.webView));
254 verify_field_focused(data.webView, "field1");
255 compare_field_value(data.webView, "field1", "for");
256 data.webView.visible = false;
257 }
258
259 function test_validate_suggestion_with_keyboard_data() {
260 return [
261 { webView: webView, key: Qt.Key_Enter, focus: "field1" },
262 { webView: webView, key: Qt.Key_Return, focus: "field1" },
263 { webView: webView, key: Qt.Key_Tab, focus: "field2" },
264 { webView: incognitoWebView, key: Qt.Key_Enter, focus: "field1" },
265 { webView: incognitoWebView, key: Qt.Key_Return, focus: "field1" },
266 { webView: incognitoWebView, key: Qt.Key_Tab, focus: "field2" },
267 ];
268 }
269
270 function test_validate_suggestion_with_keyboard(data) {
271 loadForm(data.webView);
272 typeStringInField(data.webView, "f", "field1");
273 verify(waitForAutofillPopup(data.webView));
274 var popup = getAutofillPopup(data.webView);
275 keyClick(Qt.Key_Down);
276 compare(popup.currentIndex, 0);
277 keyClick(data.key);
278 verify(waitForAutofillPopupToClose(data.webView));
279 verify_field_focused(data.webView, data.focus);
280 compare_field_value(data.webView, "field1", "foo");
281 data.webView.visible = false;
282 }
283
284 function test_shiftdel_deletes_suggestion() {
285 typeStringInField(webView, "f", "field1");
286 verify(waitForAutofillPopup(webView));
287 keyClick("l");
288 verify(waitForAutofillPopupToClose(webView));
289 keyClick("i");
290 keyClick("p");
291 compare_field_value(webView, "field1", "flip");
292 keyClick(Qt.Key_Enter);
293 verify(webView.waitForLoadSucceeded());
294 webView.url =
295 "http://testsuite/tst_WebViewAutofillPopup_single_fields.html";
296 verify(webView.waitForLoadSucceeded());
297 typeStringInField(webView, "f", "field1");
298 verify(waitForAutofillPopup(webView));
299 var popup = getAutofillPopup(webView);
300 compare(popup.count, 4);
301 compare(getSuggestion(webView, 0).value, "flip");
302 keyClick(Qt.Key_Down);
303 compare(popup.currentIndex, 0);
304 keyClick(Qt.Key_Delete, Qt.ShiftModifier);
305 tryCompare(popup, "currentIndex", -1);
306 tryCompare(popup, "count", 3);
307 }
308
309 function test_tab_no_suggestion_data() {
310 return get_webviews_data();
311 }
312
313 function test_tab_no_suggestion(data) {
314 loadForm(data.webView);
315 typeStringInField(data.webView, "f", "field1");
316 verify(waitForAutofillPopup(data.webView));
317 var popup = getAutofillPopup(data.webView);
318 compare(popup.currentIndex, -1);
319 verify_field_focused(data.webView, "field1");
320 keyClick(Qt.Key_Tab);
321 verify(waitForAutofillPopupToClose(data.webView));
322 verify_field_focused(data.webView, "field2");
323 data.webView.visible = false;
324 }
325
326 function test_incognito_data_not_saved() {
327 if (!incognitoWebView.incognito) {
328 skip("WebView.incognito cannot be set in single process mode");
329 }
330 loadForm(incognitoWebView);
331 typeStringInField(incognitoWebView, "bar", "field1");
332 keyClick(Qt.Key_Enter);
333 verify(incognitoWebView.waitForLoadSucceeded());
334 loadForm(incognitoWebView);
335 typeStringInField(incognitoWebView, "b", "field1");
336 verify(!waitForAutofillPopup(incognitoWebView, 1000));
337 incognitoWebView.visible = false;
338 }
339
340 function test_zlast_validate_no_suggestion_data() {
341 return [
342 { key: Qt.Key_Enter },
343 { key: Qt.Key_Return },
344 ];
345 }
346
347 // This test needs to be run last as it adds a suggestion that is
348 // not removed afterwards, thus breaking other tests' assumptions
349 function test_zlast_validate_no_suggestion(data) {
350 typeStringInField(webView, "f", "field1");
351 verify(waitForAutofillPopup(webView));
352 var popup = getAutofillPopup(webView);
353 compare(popup.currentIndex, -1);
354 keyClick(data.key);
355 verify(waitForAutofillPopupToClose(webView));
356 verify(webView.waitForLoadSucceeded());
357 }
358 }
359}
diff --git a/qt/uitk/lib/CMakeLists.txt b/qt/uitk/lib/CMakeLists.txt
index 9e76ebe..8f73100 100644
--- a/qt/uitk/lib/CMakeLists.txt
+++ b/qt/uitk/lib/CMakeLists.txt
@@ -1,6 +1,6 @@
1# vim:expandtab:shiftwidth=2:tabstop=2:1# vim:expandtab:shiftwidth=2:tabstop=2:
22
3# Copyright (C) 2016 Canonical Ltd.3# Copyright (C) 2016-2017 Canonical Ltd.
44
5# This library is free software; you can redistribute it and/or5# This library is free software; you can redistribute it and/or
6# modify it under the terms of the GNU Lesser General Public6# modify it under the terms of the GNU Lesser General Public
@@ -27,6 +27,7 @@ set(OXIDE_UITKLIB_SRCS
27 uitk_javascript_dialog.cc27 uitk_javascript_dialog.cc
28 uitk_touch_editing_menu.cc28 uitk_touch_editing_menu.cc
29 uitk_touch_handle_drawable.cc29 uitk_touch_handle_drawable.cc
30 uitk_web_autofill_popup.cc
30 uitk_web_context_menu.cc31 uitk_web_context_menu.cc
31 uitk_web_popup_menu.cc)32 uitk_web_popup_menu.cc)
3233
diff --git a/qt/uitk/lib/resources.qrc b/qt/uitk/lib/resources.qrc
index f2cf4ba..83f258a 100644
--- a/qt/uitk/lib/resources.qrc
+++ b/qt/uitk/lib/resources.qrc
@@ -6,6 +6,7 @@
6 <file alias="TouchEditingMenu.qml">resources/TouchEditingMenu.qml</file>6 <file alias="TouchEditingMenu.qml">resources/TouchEditingMenu.qml</file>
7 <file alias="TouchHandle@27.png">resources/TouchHandle@27.png</file>7 <file alias="TouchHandle@27.png">resources/TouchHandle@27.png</file>
8 <file alias="TouchHandle.qml">resources/TouchHandle.qml</file>8 <file alias="TouchHandle.qml">resources/TouchHandle.qml</file>
9 <file alias="WebAutofillPopup.qml">resources/WebAutofillPopup.qml</file>
9 <file alias="WebContextMenuMobile.qml">resources/WebContextMenuMobile.qml</file>10 <file alias="WebContextMenuMobile.qml">resources/WebContextMenuMobile.qml</file>
10 <file alias="WebContextMenuDesktop.qml">resources/WebContextMenuDesktop.qml</file>11 <file alias="WebContextMenuDesktop.qml">resources/WebContextMenuDesktop.qml</file>
11 <file alias="WebPopupMenu.qml">resources/WebPopupMenu.qml</file>12 <file alias="WebPopupMenu.qml">resources/WebPopupMenu.qml</file>
diff --git a/qt/uitk/lib/resources/WebAutofillPopup.qml b/qt/uitk/lib/resources/WebAutofillPopup.qml
12new file mode 10064413new file mode 100644
index 0000000..848cf0e
--- /dev/null
+++ b/qt/uitk/lib/resources/WebAutofillPopup.qml
@@ -0,0 +1,139 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18import QtQuick 2.4
19import Ubuntu.Components 1.3
20
21FocusScope {
22 objectName: parent && parent.objectName ? parent.objectName + "_WebAutofillPopup" : ""
23
24 property alias model: listview.model
25 property rect elementBounds
26 readonly property int currentIndex: listview.currentIndex
27 readonly property int count: listview.count
28
29 signal close()
30 signal acceptedSuggestion(int index)
31 signal removeSuggestion(int index)
32
33 focus: true
34 clip: true
35
36 x: elementBounds.x
37 y: elementBounds.y + elementBounds.height
38 width: elementBounds.width
39 readonly property real maxHeight: parent ? parent.height - elementBounds.y - elementBounds.height : 0
40 height: Math.min(maxHeight, listview.count * listview.itemHeight)
41
42 Rectangle {
43 anchors.fill: parent
44 color: theme.palette.normal.overlay
45 function newColorWithAlpha(color, alpha) {
46 return Qt.rgba(color.r, color.g, color.b, alpha);
47 }
48 border {
49 width: units.dp(1)
50 color: newColorWithAlpha(theme.palette.normal.base, 0.4)
51 }
52 }
53
54 MouseArea {
55 anchors.fill: parent
56 hoverEnabled: true
57 onPositionChanged: listview.currentIndex = listview.indexAt(mouse.x, mouse.y)
58 onExited: listview.currentIndex = -1
59 }
60
61 ListView {
62 id: listview
63
64 property real itemHeight: 0
65 anchors.fill: parent
66
67 delegate: ListItem {
68 objectName: "%1_item%2".arg(listview.parent.objectName).arg(index)
69 readonly property string value: model.value
70 readonly property string label: model.label
71 height: units.gu(5)
72 ListItemLayout {
73 anchors.verticalCenter: parent.verticalCenter
74 title {
75 text: model.value
76 textSize: Label.Small
77 }
78 subtitle {
79 text: model.label
80 textSize: Label.XSmall
81 }
82 }
83 color: ListView.isCurrentItem ? theme.palette.normal.focus : "transparent"
84 Component.onCompleted: listview.itemHeight = height
85
86 onClicked: acceptedSuggestion(index)
87
88 property bool removalRequested: false
89 Keys.onDeletePressed: {
90 if (event.modifiers & Qt.ShiftModifier) {
91 removalRequested = true;
92 removeSuggestion(index);
93 } else {
94 event.accepted = false;
95 }
96 }
97 ListView.onRemove: {
98 if (removalRequested) {
99 listview.currentIndex = -1;
100 }
101 }
102 }
103
104 Keys.onEnterPressed: {
105 if (currentItem) {
106 currentItem.clicked();
107 } else {
108 event.accepted = false;
109 }
110 }
111 Keys.onReturnPressed: {
112 if (currentItem) {
113 currentItem.clicked();
114 } else {
115 event.accepted = false;
116 }
117 }
118 Keys.onTabPressed: {
119 event.accepted = false;
120 if (currentItem) {
121 currentItem.clicked();
122 }
123 }
124
125 keyNavigationWraps: true
126 currentIndex: -1
127
128 Component.onCompleted: {
129 // Work around the UITK ListViewProxy extension that forces
130 // activeFocusOnTab, thus breaking tab key propagation. Setting
131 // activeFocusOnTab to false needs to be done before the item is the
132 // active focus item.
133 activeFocusOnTab = false;
134 focus = true;
135 }
136 }
137
138 Keys.onEscapePressed: close()
139}
diff --git a/qt/uitk/lib/uitk_auxiliary_ui_factory.cc b/qt/uitk/lib/uitk_auxiliary_ui_factory.cc
index e6f64fb..48731e0 100644
--- a/qt/uitk/lib/uitk_auxiliary_ui_factory.cc
+++ b/qt/uitk/lib/uitk_auxiliary_ui_factory.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016 Canonical Ltd.2// Copyright (C) 2016-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -38,6 +38,7 @@
38#include "uitk_before_unload_dialog.h"38#include "uitk_before_unload_dialog.h"
39#include "uitk_javascript_dialog.h"39#include "uitk_javascript_dialog.h"
40#include "uitk_touch_editing_menu.h"40#include "uitk_touch_editing_menu.h"
41#include "uitk_web_autofill_popup.h"
41#include "uitk_web_context_menu.h"42#include "uitk_web_context_menu.h"
4243
43static void InitResources() {44static void InitResources() {
@@ -47,11 +48,13 @@ static void InitResources() {
47namespace oxide {48namespace oxide {
48namespace uitk {49namespace uitk {
4950
51using qt::AutofillSuggestion;
50using qt::EditCapabilityFlags;52using qt::EditCapabilityFlags;
51using qt::GetScreenFormFactor;53using qt::GetScreenFormFactor;
52using qt::MenuItem;54using qt::MenuItem;
53using qt::ScreenFormFactor;55using qt::ScreenFormFactor;
54using qt::TouchEditingMenuClient;56using qt::TouchEditingMenuClient;
57using qt::WebAutofillPopupClient;
55using qt::WebContextMenuAction;58using qt::WebContextMenuAction;
56using qt::WebContextMenuClient;59using qt::WebContextMenuClient;
57using qt::WebContextMenuParams;60using qt::WebContextMenuParams;
@@ -230,6 +233,14 @@ std::unique_ptr<qt::WebContextMenu> AuxiliaryUIFactory::CreateWebContextMenu(
230 IsItemOnMobileScreen(item_));233 IsItemOnMobileScreen(item_));
231}234}
232235
236std::unique_ptr<qt::WebAutofillPopup>
237AuxiliaryUIFactory::CreateWebAutofillPopup(
238 const std::vector<AutofillSuggestion>& suggestions,
239 const QRectF& bounds,
240 WebAutofillPopupClient* client) {
241 return WebAutofillPopup::Create(item_, suggestions, bounds, client);
242}
243
233std::unique_ptr<qt::TouchEditingMenu>244std::unique_ptr<qt::TouchEditingMenu>
234AuxiliaryUIFactory::CreateTouchEditingMenu(245AuxiliaryUIFactory::CreateTouchEditingMenu(
235 EditCapabilityFlags edit_flags,246 EditCapabilityFlags edit_flags,
diff --git a/qt/uitk/lib/uitk_auxiliary_ui_factory.h b/qt/uitk/lib/uitk_auxiliary_ui_factory.h
index 3d169e4..d0ae8e7 100644
--- a/qt/uitk/lib/uitk_auxiliary_ui_factory.h
+++ b/qt/uitk/lib/uitk_auxiliary_ui_factory.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016 Canonical Ltd.2// Copyright (C) 2016-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -56,6 +56,10 @@ class AuxiliaryUIFactory : public qt::AuxiliaryUIFactory {
56 const qt::WebContextMenuParams& params,56 const qt::WebContextMenuParams& params,
57 const std::vector<qt::MenuItem>& items,57 const std::vector<qt::MenuItem>& items,
58 qt::WebContextMenuClient* client) override;58 qt::WebContextMenuClient* client) override;
59 std::unique_ptr<qt::WebAutofillPopup> CreateWebAutofillPopup(
60 const std::vector<qt::AutofillSuggestion>& suggestions,
61 const QRectF& bounds,
62 qt::WebAutofillPopupClient* client) override;
59 std::unique_ptr<qt::TouchEditingMenu> CreateTouchEditingMenu(63 std::unique_ptr<qt::TouchEditingMenu> CreateTouchEditingMenu(
60 qt::EditCapabilityFlags edit_flags,64 qt::EditCapabilityFlags edit_flags,
61 qt::TouchEditingMenuClient* client) override;65 qt::TouchEditingMenuClient* client) override;
diff --git a/qt/uitk/lib/uitk_web_autofill_popup.cc b/qt/uitk/lib/uitk_web_autofill_popup.cc
62new file mode 10064466new file mode 100644
index 0000000..4085608
--- /dev/null
+++ b/qt/uitk/lib/uitk_web_autofill_popup.cc
@@ -0,0 +1,297 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#include "uitk_web_autofill_popup.h"
19
20#include <QAbstractListModel>
21#include <QMetaObject>
22#include <QQmlComponent>
23#include <QQmlEngine>
24#include <QQmlError>
25#include <QQmlProperty>
26#include <QQuickItem>
27#include <QtDebug>
28#include <QVariant>
29#include <QVector>
30
31#include "qt/core/glue/autofill_suggestion.h"
32#include "qt/core/glue/web_autofill_popup_client.h"
33
34namespace oxide {
35namespace uitk {
36
37using qt::AutofillSuggestion;
38
39class WebAutofillPopup::Model : public QAbstractListModel {
40 public:
41 Model(const std::vector<AutofillSuggestion>& suggestions);
42 ~Model() override;
43
44 enum Role {
45 RoleType = Qt::UserRole,
46 RoleValue,
47 RoleLabel,
48 RoleIcon
49 };
50
51 // QAbstractItemModel implementation
52 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
53 QVariant data(const QModelIndex& index,
54 int role = Qt::DisplayRole) const override;
55 QHash<int, QByteArray> roleNames() const override;
56
57 protected:
58 friend class WebAutofillPopup;
59 void updateDataListValues(const std::vector<AutofillSuggestion>& suggestions);
60 void removeSuggestion(int index);
61
62 QVector<AutofillSuggestion> suggestions_;
63};
64
65WebAutofillPopup::Model::Model(
66 const std::vector<AutofillSuggestion>& suggestions) {
67 suggestions_ = QVector<AutofillSuggestion>::fromStdVector(suggestions);
68}
69
70WebAutofillPopup::Model::~Model() = default;
71
72int WebAutofillPopup::Model::rowCount(const QModelIndex& parent) const {
73 return suggestions_.size();
74}
75
76QVariant WebAutofillPopup::Model::data(const QModelIndex& index,
77 int role) const {
78 Q_ASSERT(index.isValid());
79 Q_ASSERT(index.row() >= 0 && index.row() < suggestions_.size());
80 Q_ASSERT(index.column() == 0);
81 Q_ASSERT(!index.parent().isValid());
82
83 const AutofillSuggestion& suggestion = suggestions_[index.row()];
84
85 switch (role) {
86 case RoleType: {
87 switch (suggestion.type) {
88 case AutofillSuggestion::Type::ProfileEntry:
89 return QStringLiteral("profile");
90 case AutofillSuggestion::Type::AutoCompleteEntry:
91 return QStringLiteral("autocomplete");
92 case AutofillSuggestion::Type::PasswordEntry:
93 return QStringLiteral("password");
94 case AutofillSuggestion::Type::DataListEntry:
95 return QStringLiteral("datalist");
96 default:
97 Q_UNREACHABLE();
98 }
99 }
100 case RoleValue:
101 return suggestion.value;
102 case RoleLabel:
103 return suggestion.label;
104 case RoleIcon:
105 return suggestion.icon;
106 default:
107 Q_UNREACHABLE();
108 }
109}
110
111QHash<int, QByteArray> WebAutofillPopup::Model::roleNames() const {
112 static QHash<int, QByteArray> roles;
113
114 if (roles.size() > 0) {
115 return roles;
116 }
117
118 roles[RoleType] = "type";
119 roles[RoleValue] = "value";
120 roles[RoleLabel] = "label";
121 roles[RoleIcon] = "icon";
122
123 return roles;
124}
125
126void WebAutofillPopup::Model::updateDataListValues(
127 const std::vector<AutofillSuggestion>& suggestions) {
128 // Remove all the old data list values, which should always be at the top of
129 // the list if they are present.
130 if (!suggestions_.isEmpty()) {
131 int i = suggestions_.size() - 1;
132 while (i >= 0 &&
133 suggestions_[i--].type != AutofillSuggestion::Type::DataListEntry);
134 if (i >= 0) {
135 beginRemoveRows(QModelIndex(), 0, i);
136 suggestions_.remove(0, i + 1);
137 endRemoveRows();
138 }
139 }
140
141 // Prepend the new data list values to the suggestions we already have.
142 beginInsertRows(QModelIndex(), 0, suggestions.size() - 1);
143 suggestions_ =
144 QVector<AutofillSuggestion>::fromStdVector(suggestions) + suggestions_;
145 endInsertRows();
146}
147
148void WebAutofillPopup::Model::removeSuggestion(int index) {
149 beginRemoveRows(QModelIndex(), index, index);
150 suggestions_.remove(index);
151 endRemoveRows();
152}
153
154void WebAutofillPopup::Show() {
155 item_->setVisible(true);
156}
157
158void WebAutofillPopup::UpdateDataListValues(
159 const std::vector<AutofillSuggestion>& suggestions) {
160 model_->updateDataListValues(suggestions);
161}
162
163void WebAutofillPopup::Hide() {
164 item_->setVisible(false);
165}
166
167WebAutofillPopup::WebAutofillPopup(
168 const std::vector<AutofillSuggestion>& suggestions,
169 const QRectF& bounds,
170 qt::WebAutofillPopupClient* client)
171 : model_(new Model(suggestions)),
172 bounds_(bounds),
173 client_(client) {}
174
175bool WebAutofillPopup::Init(QQuickItem* parent) {
176 QQmlEngine* engine = qmlEngine(parent);
177 if (!engine) {
178 qWarning() <<
179 "uitk::WebAutofillPopup: Failed to create autofill popup - "
180 "cannot determine QQmlEngine for parent item";
181 return false;
182 }
183
184 QQmlComponent component(engine);
185 component.loadUrl(QUrl("qrc:///WebAutofillPopup.qml"));
186
187 if (component.isError()) {
188 qCritical() <<
189 "uitk::WebAutofillPopup: Failed to initialize autofill popup component "
190 "because of the following errors: ";
191 for (const auto& error : component.errors()) {
192 qCritical() << error;
193 }
194 return false;
195 }
196
197 Q_ASSERT(component.isReady());
198
199 QObject* popup = component.beginCreate(engine->rootContext());
200 if (!popup) {
201 qCritical() <<
202 "uitk::WebAutofillPopup: Failed to create autofill popup instance";
203 return false;
204 }
205
206 item_.reset(qobject_cast<QQuickItem*>(popup));
207 if (!item_) {
208 qCritical() <<
209 "uitk::WebAutofillPopup: Autofill popup instance is not a QQuickItem";
210 delete popup;
211 return false;
212 }
213
214 item_->setProperty("model", QVariant::fromValue(model_.get()));
215 item_->setProperty("elementBounds", bounds_);
216 item_->setParentItem(parent);
217
218 component.completeCreate();
219
220 connect(item_.get(), SIGNAL(close()), this, SLOT(OnCloseRequested()));
221 connect(item_.get(), SIGNAL(currentIndexChanged()),
222 this, SLOT(OnSuggestionSelected()));
223 connect(item_.get(), SIGNAL(acceptedSuggestion(int)),
224 this, SLOT(OnSuggestionAccepted(int)));
225 connect(item_.get(), SIGNAL(removeSuggestion(int)),
226 this, SLOT(OnSuggestionRemovalRequested(int)));
227
228 return true;
229}
230
231void WebAutofillPopup::OnCloseRequested() {
232 client_->Close();
233}
234
235void WebAutofillPopup::OnSuggestionSelected() {
236 int index =
237 QQmlProperty(item_.get(), QStringLiteral("currentIndex")).read().toInt();
238
239 if (index == -1) {
240 client_->ClearSelection();
241 return;
242 }
243
244 if (index < 0 || index >= model_->rowCount()) {
245 qWarning() << "uitk::WebAutofillPopup: invalid index";
246 return;
247 }
248
249 const AutofillSuggestion& suggestion = model_->suggestions_[index];
250 client_->SelectSuggestion(suggestion);
251}
252
253void WebAutofillPopup::OnSuggestionAccepted(int index) {
254 if (index < 0 || index >= model_->rowCount()) {
255 qWarning() << "uitk::WebAutofillPopup: invalid index";
256 return;
257 }
258
259 const AutofillSuggestion& suggestion = model_->suggestions_[index];
260 client_->AcceptSuggestion(suggestion);
261}
262
263void WebAutofillPopup::OnSuggestionRemovalRequested(int index) {
264 if (index < 0 || index >= model_->rowCount()) {
265 qWarning() << "uitk::WebAutofillPopup: invalid index";
266 return;
267 }
268
269 const AutofillSuggestion& suggestion = model_->suggestions_[index];
270 if (client_->RemoveSuggestion(suggestion)) {
271 model_->removeSuggestion(index);
272 }
273}
274
275// static
276std::unique_ptr<WebAutofillPopup> WebAutofillPopup::Create(
277 QQuickItem* parent,
278 const std::vector<AutofillSuggestion>& suggestions,
279 const QRectF& bounds,
280 qt::WebAutofillPopupClient* client) {
281 if (suggestions.empty()) {
282 return nullptr;
283 }
284
285 std::unique_ptr<WebAutofillPopup> popup(
286 new WebAutofillPopup(suggestions, bounds, client));
287 if (!popup->Init(parent)) {
288 return nullptr;
289 }
290
291 return std::move(popup);
292}
293
294WebAutofillPopup::~WebAutofillPopup() = default;
295
296} // namespace uitk
297} // namespace oxide
diff --git a/qt/uitk/lib/uitk_web_autofill_popup.h b/qt/uitk/lib/uitk_web_autofill_popup.h
0new file mode 100644298new file mode 100644
index 0000000..4dfbf38
--- /dev/null
+++ b/qt/uitk/lib/uitk_web_autofill_popup.h
@@ -0,0 +1,87 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_UITK_LIB_WEB_AUTOFILL_POPUP_H_
19#define _OXIDE_UITK_LIB_WEB_AUTOFILL_POPUP_H_
20
21#include "qt/core/glue/web_autofill_popup.h"
22
23#include <memory>
24#include <vector>
25
26#include <QObject>
27#include <QRectF>
28#include <QtGlobal>
29
30QT_BEGIN_NAMESPACE
31class QQuickItem;
32QT_END_NAMESPACE
33
34namespace oxide {
35
36namespace qt {
37struct AutofillSuggestion;
38class WebAutofillPopupClient;
39}
40
41namespace uitk {
42
43class WebAutofillPopup : public QObject,
44 public qt::WebAutofillPopup {
45 Q_OBJECT
46 Q_DISABLE_COPY(WebAutofillPopup)
47
48 public:
49 static std::unique_ptr<WebAutofillPopup> Create(
50 QQuickItem* parent,
51 const std::vector<qt::AutofillSuggestion>& suggestions,
52 const QRectF& bounds,
53 qt::WebAutofillPopupClient* client);
54 ~WebAutofillPopup() override;
55
56 private Q_SLOTS:
57 void OnCloseRequested();
58 void OnSuggestionSelected();
59 void OnSuggestionAccepted(int index);
60 void OnSuggestionRemovalRequested(int index);
61
62 private:
63 WebAutofillPopup(const std::vector<qt::AutofillSuggestion>& suggestions,
64 const QRectF& bounds,
65 qt::WebAutofillPopupClient* client);
66 bool Init(QQuickItem* parent);
67
68 // qt::WebAutofillPopup implementation
69 void Show() override;
70 void UpdateDataListValues(
71 const std::vector<qt::AutofillSuggestion>& suggestions) override;
72 void Hide() override;
73
74 class Model;
75 std::unique_ptr<Model> model_;
76
77 QRectF bounds_;
78
79 qt::WebAutofillPopupClient* client_;
80
81 std::unique_ptr<QQuickItem> item_;
82};
83
84} // namespace uitk
85} // namespace oxide
86
87#endif // _OXIDE_UITK_LIB_WEB_AUTOFILL_POPUP_H_
diff --git a/shared/BUILD.gn b/shared/BUILD.gn
index 77eaeca..1aaf81d 100644
--- a/shared/BUILD.gn
+++ b/shared/BUILD.gn
@@ -1,6 +1,6 @@
1# vim:expandtab:shiftwidth=2:tabstop=2:1# vim:expandtab:shiftwidth=2:tabstop=2:
22
3# Copyright (C) 2016 Canonical Ltd.3# Copyright (C) 2016-2017 Canonical Ltd.
44
5# This library is free software; you can redistribute it and/or5# This library is free software; you can redistribute it and/or
6# modify it under the terms of the GNU Lesser General Public6# modify it under the terms of the GNU Lesser General Public
@@ -113,6 +113,7 @@ repack_locales("shared_repack_locales") {
113 output_locales = locales113 output_locales = locales
114114
115 source_patterns = [115 source_patterns = [
116 "${root_gen_dir}/components/strings/components_strings_",
116 "${root_gen_dir}/content/app/strings/content_strings_",117 "${root_gen_dir}/content/app/strings/content_strings_",
117 "${root_gen_dir}/ui/strings/app_locale_settings_",118 "${root_gen_dir}/ui/strings/app_locale_settings_",
118 ]119 ]
@@ -120,6 +121,7 @@ repack_locales("shared_repack_locales") {
120 output_dir = "${root_out_dir}/chromium_l10n"121 output_dir = "${root_out_dir}/chromium_l10n"
121122
122 deps = [123 deps = [
124 "//components/strings",
123 "//content/app/strings",125 "//content/app/strings",
124 "//ui/strings:app_locale_settings",126 "//ui/strings:app_locale_settings",
125 ]127 ]
@@ -180,13 +182,23 @@ component("shared") {
180 "//base:i18n",182 "//base:i18n",
181 "//cc",183 "//cc",
182 "//cc/surfaces",184 "//cc/surfaces",
185 "//components/autofill/content/browser",
186 "//components/autofill/content/renderer",
187 "//components/autofill/core/browser",
183 "//components/keyed_service/content",188 "//components/keyed_service/content",
184 "//components/keyed_service/core",189 "//components/keyed_service/core",
190 "//components/password_manager/content/browser",
191 "//components/pref_registry",
192 "//components/prefs",
193 "//components/sync",
194 "//components/user_prefs",
185 "//components/sessions",195 "//components/sessions",
196 "//components/webdata/common",
186 "//content/public/app:both",197 "//content/public/app:both",
187 "//content/public/browser",198 "//content/public/browser",
188 "//content/public/child",199 "//content/public/child",
189 "//content/public/common",200 "//content/public/common",
201 "//content/public/common:service_names",
190 "//content/public/gpu",202 "//content/public/gpu",
191 "//content/public/renderer",203 "//content/public/renderer",
192 "//content/public/utility",204 "//content/public/utility",
@@ -198,6 +210,7 @@ component("shared") {
198 "//device/vibration:mojo_bindings",210 "//device/vibration:mojo_bindings",
199 "//extensions/common",211 "//extensions/common",
200 "//gin",212 "//gin",
213 "//google_apis",
201 "//gpu/command_buffer/client",214 "//gpu/command_buffer/client",
202 "//gpu/command_buffer/common",215 "//gpu/command_buffer/common",
203 "//gpu/command_buffer/service",216 "//gpu/command_buffer/service",
@@ -244,6 +257,12 @@ component("shared") {
244 "app/oxide_main.cc",257 "app/oxide_main.cc",
245 "app/oxide_main.h",258 "app/oxide_main.h",
246 "app/oxide_platform_delegate.h",259 "app/oxide_platform_delegate.h",
260 "browser/autofill/autofill_client.cc",
261 "browser/autofill/autofill_client.h",
262 "browser/autofill/autofill_popup_controller.cc",
263 "browser/autofill/autofill_popup_controller.h",
264 "browser/autofill/web_autofill_popup.h",
265 "browser/autofill/web_autofill_popup_client.h",
247 "browser/browser_object_weak_ptrs.h",266 "browser/browser_object_weak_ptrs.h",
248 "browser/chrome_controller.cc",267 "browser/chrome_controller.cc",
249 "browser/chrome_controller.h",268 "browser/chrome_controller.h",
@@ -299,6 +318,8 @@ component("shared") {
299 "browser/device/power_save_blocker.h",318 "browser/device/power_save_blocker.h",
300 "browser/device/power_save_blocker_linux.cc",319 "browser/device/power_save_blocker_linux.cc",
301 "browser/display_form_factor.h",320 "browser/display_form_factor.h",
321 "browser/filtered_pref_store.cc",
322 "browser/filtered_pref_store.h",
302 "browser/input/input_method_context.h",323 "browser/input/input_method_context.h",
303 "browser/input/input_method_context_client.cc",324 "browser/input/input_method_context_client.cc",
304 "browser/input/input_method_context_client.h",325 "browser/input/input_method_context_client.h",
@@ -454,6 +475,8 @@ component("shared") {
454 "browser/permissions/oxide_permission_request_response.h",475 "browser/permissions/oxide_permission_request_response.h",
455 "browser/permissions/oxide_temporary_saved_permission_context.cc",476 "browser/permissions/oxide_temporary_saved_permission_context.cc",
456 "browser/permissions/oxide_temporary_saved_permission_context.h",477 "browser/permissions/oxide_temporary_saved_permission_context.h",
478 "browser/personal_data_manager_factory.cc",
479 "browser/personal_data_manager_factory.h",
457 "browser/screen.cc",480 "browser/screen.cc",
458 "browser/screen.h",481 "browser/screen.h",
459 "browser/screen_observer.cc",482 "browser/screen_observer.cc",
@@ -487,6 +510,10 @@ component("shared") {
487 "browser/web_contents_data_tracker.h",510 "browser/web_contents_data_tracker.h",
488 "browser/web_contents_helper.cc",511 "browser/web_contents_helper.cc",
489 "browser/web_contents_helper.h",512 "browser/web_contents_helper.h",
513 "browser/web_data_service_factory.cc",
514 "browser/web_data_service_factory.h",
515 "browser/web_data_service_wrapper.cc",
516 "browser/web_data_service_wrapper.h",
490 "browser/web_popup_menu.h",517 "browser/web_popup_menu.h",
491 "browser/web_popup_menu_client.h",518 "browser/web_popup_menu_client.h",
492 "browser/web_popup_menu_host.cc",519 "browser/web_popup_menu_host.cc",
@@ -714,6 +741,7 @@ test_executable("shared_unittests") {
714 "//base",741 "//base",
715 "//base/test:test_support",742 "//base/test:test_support",
716 "//cc",743 "//cc",
744 "//components/prefs:test_support",
717 "//content/public/browser",745 "//content/public/browser",
718 "//content/public/common",746 "//content/public/common",
719 "//content/test:test_support",747 "//content/test:test_support",
@@ -729,6 +757,7 @@ test_executable("shared_unittests") {
729 ]757 ]
730758
731 sources = [759 sources = [
760 "browser/filtered_pref_store_unittest.cc",
732 "browser/javascript_dialogs/javascript_dialog_contents_helper_unittest.cc",761 "browser/javascript_dialogs/javascript_dialog_contents_helper_unittest.cc",
733 "browser/javascript_dialogs/javascript_dialog_host_unittest.cc",762 "browser/javascript_dialogs/javascript_dialog_host_unittest.cc",
734 "browser/javascript_dialogs/javascript_dialog_testing_utils.cc",763 "browser/javascript_dialogs/javascript_dialog_testing_utils.cc",
diff --git a/shared/browser/autofill/autofill_client.cc b/shared/browser/autofill/autofill_client.cc
735new file mode 100644764new file mode 100644
index 0000000..bbf22ee
--- /dev/null
+++ b/shared/browser/autofill/autofill_client.cc
@@ -0,0 +1,272 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016-2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#include "autofill_client.h"
19
20#include "base/logging.h"
21#include "components/autofill/content/browser/content_autofill_driver.h"
22#include "components/autofill/content/browser/content_autofill_driver_factory.h"
23#include "components/autofill/core/common/autofill_pref_names.h"
24#include "components/prefs/pref_service.h"
25#include "content/public/browser/browser_context.h"
26#include "content/public/browser/navigation_entry.h"
27#include "content/public/browser/render_frame_host.h"
28#include "content/public/browser/ssl_status.h"
29#include "google_apis/gaia/identity_provider.h"
30
31#include "shared/browser/oxide_browser_context.h"
32#include "shared/browser/personal_data_manager_factory.h"
33#include "shared/browser/web_data_service_factory.h"
34
35#include "autofill_popup_controller.h"
36
37namespace oxide {
38
39DEFINE_WEB_CONTENTS_USER_DATA_KEY(oxide::AutofillClient);
40
41class DummyIdentityProvider : public IdentityProvider {
42 public:
43 explicit DummyIdentityProvider();
44 ~DummyIdentityProvider() override;
45
46 std::string GetActiveUsername() override;
47 std::string GetActiveAccountId() override;
48 OAuth2TokenService* GetTokenService() override;
49 bool RequestLogin() override;
50
51 private:
52 DISALLOW_COPY_AND_ASSIGN(DummyIdentityProvider);
53};
54
55DummyIdentityProvider::DummyIdentityProvider() {}
56
57DummyIdentityProvider::~DummyIdentityProvider() {}
58
59std::string DummyIdentityProvider::GetActiveUsername() {
60 return std::string();
61}
62
63std::string DummyIdentityProvider::GetActiveAccountId() {
64 return std::string();
65}
66
67OAuth2TokenService* DummyIdentityProvider::GetTokenService() {
68 return nullptr;
69}
70
71bool DummyIdentityProvider::RequestLogin() {
72 return false;
73}
74
75AutofillClient::AutofillClient(content::WebContents* web_contents)
76 : content::WebContentsObserver(web_contents) {
77 DCHECK(web_contents);
78}
79
80AutofillClient::~AutofillClient() {
81 DCHECK(!popup_controller_);
82}
83
84void AutofillClient::DidHideAutofillPopup() {
85 DCHECK(popup_controller_);
86
87 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
88 popup_controller_.release());
89}
90
91autofill::PersonalDataManager* AutofillClient::GetPersonalDataManager() {
92 return PersonalDataManagerFactory::GetForContext(
93 web_contents()->GetBrowserContext());
94}
95
96scoped_refptr<autofill::AutofillWebDataService>
97AutofillClient::GetDatabase() {
98 return WebDataServiceFactory::GetAutofillWebDataForContext(
99 web_contents()->GetBrowserContext());
100}
101
102PrefService* AutofillClient::GetPrefs() {
103 return BrowserContext::FromContent(web_contents()->GetBrowserContext())
104 ->GetPrefs();
105}
106
107syncer::SyncService* AutofillClient::GetSyncService() {
108 return nullptr;
109}
110
111IdentityProvider* AutofillClient::GetIdentityProvider() {
112 if (!identity_provider_) {
113 identity_provider_.reset(new DummyIdentityProvider());
114 }
115
116 return identity_provider_.get();
117}
118
119rappor::RapporServiceImpl* AutofillClient::GetRapporServiceImpl() {
120 return nullptr;
121}
122
123ukm::UkmService* AutofillClient::GetUkmService() {
124 return nullptr;
125}
126
127void AutofillClient::ShowAutofillSettings() {
128 NOTIMPLEMENTED();
129}
130
131void AutofillClient::ShowUnmaskPrompt(
132 const autofill::CreditCard& card,
133 UnmaskCardReason reason,
134 base::WeakPtr<autofill::CardUnmaskDelegate> delegate) {
135 NOTIMPLEMENTED();
136}
137
138void AutofillClient::OnUnmaskVerificationResult(
139 PaymentsRpcResult result) {
140 NOTIMPLEMENTED();
141}
142
143void AutofillClient::ConfirmSaveCreditCardLocally(
144 const autofill::CreditCard& card,
145 const base::Closure& callback) {
146 NOTIMPLEMENTED();
147}
148
149void AutofillClient::ConfirmSaveCreditCardToCloud(
150 const autofill::CreditCard& card,
151 std::unique_ptr<base::DictionaryValue> legal_message,
152 const base::Closure& callback) {
153 NOTIMPLEMENTED();
154}
155
156void AutofillClient::ConfirmCreditCardFillAssist(
157 const autofill::CreditCard& card,
158 const base::Closure& callback) {
159 NOTIMPLEMENTED();
160}
161
162void AutofillClient::LoadRiskData(
163 const base::Callback<void(const std::string&)>& callback) {
164 NOTIMPLEMENTED();
165}
166
167bool AutofillClient::HasCreditCardScanFeature() {
168 return false;
169}
170
171void AutofillClient::ScanCreditCard(
172 const CreditCardScanCallback& callback) {
173 NOTIMPLEMENTED();
174}
175
176void AutofillClient::ShowAutofillPopup(
177 const gfx::RectF& element_bounds,
178 base::i18n::TextDirection text_direction,
179 const std::vector<autofill::Suggestion>& suggestions,
180 base::WeakPtr<autofill::AutofillPopupDelegate> delegate) {
181 // Will delete or reuse the old |popup_controller_|.
182 popup_controller_.reset(
183 AutofillPopupController::GetOrCreate(
184 popup_controller_, delegate, web_contents(), element_bounds,
185 text_direction, base::Bind(&AutofillClient::DidHideAutofillPopup,
186 base::Unretained(this))));
187
188 popup_controller_->Show(suggestions);
189}
190
191void AutofillClient::UpdateAutofillPopupDataListValues(
192 const std::vector<base::string16>& values,
193 const std::vector<base::string16>& labels) {
194 if (popup_controller_.get()) {
195 popup_controller_->UpdateDataListValues(values, labels);
196 }
197}
198
199void AutofillClient::HideAutofillPopup() {
200 if (popup_controller_.get()) {
201 popup_controller_->Hide();
202 }
203}
204
205bool AutofillClient::IsAutocompleteEnabled() {
206 return GetPrefs()->GetBoolean(autofill::prefs::kAutofillEnabled);
207}
208
209void AutofillClient::MainFrameWasResized(bool width_changed) {
210 HideAutofillPopup();
211}
212
213void AutofillClient::WebContentsDestroyed() {
214 HideAutofillPopup();
215}
216
217void AutofillClient::PropagateAutofillPredictions(
218 content::RenderFrameHost* rfh,
219 const std::vector<autofill::FormStructure*>& forms) {
220 NOTIMPLEMENTED();
221}
222
223void AutofillClient::DidFillOrPreviewField(
224 const base::string16& autofilled_value,
225 const base::string16& profile_full_name) {}
226
227void AutofillClient::OnFirstUserGestureObserved() {
228 autofill::ContentAutofillDriverFactory* factory =
229 autofill::ContentAutofillDriverFactory::FromWebContents(web_contents());
230 DCHECK(factory);
231
232 for (content::RenderFrameHost* frame : web_contents()->GetAllFrames()) {
233 if (!frame->IsRenderFrameLive()) {
234 continue;
235 }
236 autofill::ContentAutofillDriver* driver = factory->DriverForFrame(frame);
237 DCHECK(driver);
238 driver->NotifyFirstUserGestureObservedInTab();
239 }
240}
241
242bool AutofillClient::IsContextSecure() {
243 content::SSLStatus ssl_status;
244 content::NavigationEntry* navigation_entry =
245 web_contents()->GetController().GetLastCommittedEntry();
246 if (!navigation_entry) {
247 return false;
248 }
249
250 ssl_status = navigation_entry->GetSSL();
251 return navigation_entry->GetURL().SchemeIsCryptographic() &&
252 ssl_status.certificate &&
253 (!net::IsCertStatusError(ssl_status.cert_status) ||
254 net::IsCertStatusMinorError(ssl_status.cert_status)) &&
255 !(ssl_status.content_status &
256 content::SSLStatus::RAN_INSECURE_CONTENT);
257}
258
259bool AutofillClient::ShouldShowSigninPromo() {
260 NOTIMPLEMENTED();
261 return false;
262}
263
264void AutofillClient::StartSigninFlow() {
265 NOTIMPLEMENTED();
266}
267
268void AutofillClient::ShowHttpNotSecureExplanation() {
269 NOTIMPLEMENTED();
270}
271
272} // namespace oxide
diff --git a/shared/browser/autofill/autofill_client.h b/shared/browser/autofill/autofill_client.h
0new file mode 100644273new file mode 100644
index 0000000..b31fe3c
--- /dev/null
+++ b/shared/browser/autofill/autofill_client.h
@@ -0,0 +1,116 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2016-2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_SHARED_BROWSER_AUTOFILL_AUTOFILL_CLIENT_H_
19#define _OXIDE_SHARED_BROWSER_AUTOFILL_AUTOFILL_CLIENT_H_
20
21#include <memory>
22#include <string>
23#include <vector>
24
25#include "base/callback.h"
26#include "base/compiler_specific.h"
27#include "base/i18n/rtl.h"
28#include "base/macros.h"
29#include "base/memory/weak_ptr.h"
30#include "components/autofill/core/browser/autofill_client.h"
31#include "content/public/browser/web_contents_observer.h"
32#include "content/public/browser/web_contents_user_data.h"
33
34namespace content {
35class WebContents;
36}
37
38namespace oxide {
39
40class AutofillPopupController;
41class DummyIdentityProvider;
42
43class AutofillClient
44 : public autofill::AutofillClient,
45 public content::WebContentsUserData<AutofillClient>,
46 public content::WebContentsObserver {
47 public:
48 ~AutofillClient() override;
49
50 // AutofillClient:
51 autofill::PersonalDataManager* GetPersonalDataManager() override;
52 scoped_refptr<autofill::AutofillWebDataService> GetDatabase() override;
53 PrefService* GetPrefs() override;
54 syncer::SyncService* GetSyncService() override;
55 IdentityProvider* GetIdentityProvider() override;
56 rappor::RapporServiceImpl* GetRapporServiceImpl() override;
57 ukm::UkmService* GetUkmService() override;
58 void ShowAutofillSettings() override;
59 void ShowUnmaskPrompt(
60 const autofill::CreditCard& card,
61 UnmaskCardReason reason,
62 base::WeakPtr<autofill::CardUnmaskDelegate> delegate) override;
63 void OnUnmaskVerificationResult(PaymentsRpcResult result) override;
64 void ConfirmSaveCreditCardLocally(const autofill::CreditCard& card,
65 const base::Closure& callback) override;
66 void ConfirmSaveCreditCardToCloud(
67 const autofill::CreditCard& card,
68 std::unique_ptr<base::DictionaryValue> legal_message,
69 const base::Closure& callback) override;
70 void ConfirmCreditCardFillAssist(const autofill::CreditCard& card,
71 const base::Closure& callback) override;
72 void LoadRiskData(
73 const base::Callback<void(const std::string&)>& callback) override;
74 bool HasCreditCardScanFeature() override;
75 void ScanCreditCard(const CreditCardScanCallback& callback) override;
76 void ShowAutofillPopup(
77 const gfx::RectF& element_bounds,
78 base::i18n::TextDirection text_direction,
79 const std::vector<autofill::Suggestion>& suggestions,
80 base::WeakPtr<autofill::AutofillPopupDelegate> delegate) override;
81 void UpdateAutofillPopupDataListValues(
82 const std::vector<base::string16>& values,
83 const std::vector<base::string16>& labels) override;
84 void HideAutofillPopup() override;
85 bool IsAutocompleteEnabled() override;
86 void PropagateAutofillPredictions(
87 content::RenderFrameHost* rfh,
88 const std::vector<autofill::FormStructure*>& forms) override;
89 void DidFillOrPreviewField(const base::string16& autofilled_value,
90 const base::string16& profile_full_name) override;
91 void OnFirstUserGestureObserved() override;
92 bool IsContextSecure() override;
93 bool ShouldShowSigninPromo() override;
94 void StartSigninFlow() override;
95 void ShowHttpNotSecureExplanation() override;
96
97 // content::WebContentsObserver implementation.
98 void MainFrameWasResized(bool width_changed) override;
99 void WebContentsDestroyed() override;
100
101 private:
102 explicit AutofillClient(content::WebContents* web_contents);
103 friend class content::WebContentsUserData<AutofillClient>;
104
105 void DidHideAutofillPopup();
106
107 std::unique_ptr<AutofillPopupController> popup_controller_;
108
109 std::unique_ptr<DummyIdentityProvider> identity_provider_;
110
111 DISALLOW_COPY_AND_ASSIGN(AutofillClient);
112};
113
114} // namespace oxide
115
116#endif // _OXIDE_SHARED_BROWSER_AUTOFILL_AUTOFILL_CLIENT_H_
diff --git a/shared/browser/autofill/autofill_popup_controller.cc b/shared/browser/autofill/autofill_popup_controller.cc
0new file mode 100644117new file mode 100644
index 0000000..a79fe61
--- /dev/null
+++ b/shared/browser/autofill/autofill_popup_controller.cc
@@ -0,0 +1,163 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#include "autofill_popup_controller.h"
19
20#include "components/autofill/core/browser/autofill_popup_delegate.h"
21#include "components/autofill/core/browser/suggestion.h"
22
23#include "shared/browser/chrome_controller.h"
24#include "shared/browser/oxide_web_contents_view.h"
25#include "shared/browser/oxide_web_contents_view_client.h"
26#include "shared/browser/web_contents_client.h"
27#include "shared/browser/web_contents_helper.h"
28
29#include "web_autofill_popup.h"
30
31namespace oxide {
32
33// static
34AutofillPopupController* AutofillPopupController::GetOrCreate(
35 std::unique_ptr<AutofillPopupController>& previous,
36 base::WeakPtr<autofill::AutofillPopupDelegate> delegate,
37 content::WebContents* web_contents,
38 const gfx::RectF& element_bounds,
39 base::i18n::TextDirection text_direction,
40 const base::Closure& hidden_callback) {
41 if (previous.get() && previous->web_contents_ == web_contents &&
42 previous->delegate_.get() == delegate.get() &&
43 previous->element_bounds_ == element_bounds) {
44 previous->ClearState();
45 return previous.release();
46 }
47
48 if (previous.get()) {
49 previous->Hide();
50 }
51
52 return new AutofillPopupController(
53 delegate, web_contents, element_bounds, text_direction, hidden_callback);
54}
55
56AutofillPopupController::AutofillPopupController(
57 base::WeakPtr<autofill::AutofillPopupDelegate> delegate,
58 content::WebContents* web_contents,
59 const gfx::RectF& element_bounds,
60 base::i18n::TextDirection text_direction,
61 const base::Closure& hidden_callback)
62 : web_contents_(web_contents),
63 element_bounds_(element_bounds),
64 delegate_(delegate),
65 hidden_callback_(hidden_callback) {
66 ClearState();
67}
68
69AutofillPopupController::~AutofillPopupController() {
70 hidden_callback_.Reset();
71}
72
73void AutofillPopupController::Show(
74 const std::vector<autofill::Suggestion>& suggestions) {
75 suggestions_ = suggestions;
76
77 WebContentsHelper* helper =
78 WebContentsHelper::FromWebContents(web_contents_);
79 if (!helper->client()) {
80 return;
81 }
82
83 gfx::Vector2d top_content_offset;
84 ChromeController* chrome_controller =
85 ChromeController::FromWebContents(web_contents_);
86 if (chrome_controller) {
87 top_content_offset =
88 gfx::Vector2d(0, chrome_controller->GetTopContentOffset());
89 }
90
91 popup_ = helper->client()->CreateAutofillPopup(
92 suggestions, element_bounds_ + top_content_offset, this);
93 if (!popup_) {
94 return;
95 }
96
97 popup_->Show();
98
99 delegate_->OnPopupShown();
100}
101
102void AutofillPopupController::UpdateDataListValues(
103 const std::vector<base::string16>& values,
104 const std::vector<base::string16>& labels) {
105 if (popup_) {
106 popup_->UpdateDataListValues(values, labels);
107 }
108}
109
110void AutofillPopupController::Hide() {
111 if (hidden_callback_.is_null()) {
112 return;
113 }
114 base::Closure hidden_callback = std::move(hidden_callback_);
115 hidden_callback_.Reset();
116
117 if (delegate_) {
118 delegate_->OnPopupHidden();
119 }
120
121 if (popup_) {
122 popup_->Hide();
123 }
124
125 hidden_callback.Run();
126}
127
128void AutofillPopupController::Close() {
129 Hide();
130}
131
132void AutofillPopupController::SelectSuggestion(int frontend_id,
133 const base::string16& value) {
134 delegate_->DidSelectSuggestion(value, frontend_id);
135}
136
137void AutofillPopupController::ClearSelection() {
138 delegate_->ClearPreviewedForm();
139}
140
141void AutofillPopupController::AcceptSuggestion(int frontend_id,
142 const base::string16& value) {
143 int position = 0;
144 for (size_t i = 0; i < suggestions_.size(); ++i) {
145 const autofill::Suggestion& suggestion = suggestions_[i];
146 if (suggestion.frontend_id == frontend_id && suggestion.value == value) {
147 position = i;
148 break;
149 }
150 }
151 delegate_->DidAcceptSuggestion(value, frontend_id, position);
152}
153
154bool AutofillPopupController::RemoveSuggestion(int frontend_id,
155 const base::string16& value) {
156 return delegate_->RemoveSuggestion(value, frontend_id);
157}
158
159void AutofillPopupController::ClearState() {
160 suggestions_.clear();
161}
162
163} // namespace oxide
diff --git a/shared/browser/autofill/autofill_popup_controller.h b/shared/browser/autofill/autofill_popup_controller.h
0new file mode 100644164new file mode 100644
index 0000000..e7d9be0
--- /dev/null
+++ b/shared/browser/autofill/autofill_popup_controller.h
@@ -0,0 +1,92 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_SHARED_BROWSER_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_H_
19#define _OXIDE_SHARED_BROWSER_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_H_
20
21#include <vector>
22
23#include "base/callback.h"
24#include "base/i18n/rtl.h"
25#include "base/memory/weak_ptr.h"
26#include "base/strings/string16.h"
27#include "ui/gfx/geometry/rect_f.h"
28#include "ui/gfx/native_widget_types.h"
29
30#include "web_autofill_popup_client.h"
31
32namespace autofill {
33class AutofillPopupDelegate;
34struct Suggestion;
35}
36
37namespace content {
38class WebContents;
39}
40
41namespace oxide {
42
43class WebAutofillPopup;
44
45class AutofillPopupController : public WebAutofillPopupClient {
46 public:
47 ~AutofillPopupController();
48
49 static AutofillPopupController* GetOrCreate(
50 std::unique_ptr<AutofillPopupController>& previous,
51 base::WeakPtr<autofill::AutofillPopupDelegate> delegate,
52 content::WebContents* web_contents,
53 const gfx::RectF& element_bounds,
54 base::i18n::TextDirection text_direction,
55 const base::Closure& hidden_callback);
56
57 void Show(const std::vector<autofill::Suggestion>& suggestions);
58 void UpdateDataListValues(const std::vector<base::string16>& values,
59 const std::vector<base::string16>& labels);
60 void Hide();
61
62 private:
63 AutofillPopupController(
64 base::WeakPtr<autofill::AutofillPopupDelegate> delegate,
65 content::WebContents* web_contents,
66 const gfx::RectF& element_bounds,
67 base::i18n::TextDirection text_direction,
68 const base::Closure& hidden_callback);
69
70 void ClearState();
71
72 // WebAutofillPopupClient implementation
73 void Close() override;
74 void SelectSuggestion(int frontend_id, const base::string16& value) override;
75 void ClearSelection() override;
76 void AcceptSuggestion(int frontend_id, const base::string16& value) override;
77 bool RemoveSuggestion(int frontend_id, const base::string16& value) override;
78
79 content::WebContents* web_contents_;
80 gfx::RectF element_bounds_;
81 base::WeakPtr<autofill::AutofillPopupDelegate> delegate_;
82 base::i18n::TextDirection text_direction_;
83 std::vector<autofill::Suggestion> suggestions_;
84
85 std::unique_ptr<WebAutofillPopup> popup_;
86
87 base::Closure hidden_callback_;
88};
89
90} // namespace oxide
91
92#endif // _OXIDE_SHARED_BROWSER_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_H_
diff --git a/shared/browser/autofill/web_autofill_popup.h b/shared/browser/autofill/web_autofill_popup.h
0new file mode 10064493new file mode 100644
index 0000000..7d58fdc
--- /dev/null
+++ b/shared/browser/autofill/web_autofill_popup.h
@@ -0,0 +1,42 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_SHARED_BROWSER_WEB_AUTOFILL_POPUP_H_
19#define _OXIDE_SHARED_BROWSER_WEB_AUTOFILL_POPUP_H_
20
21#include <vector>
22
23#include "base/strings/string16.h"
24
25namespace oxide {
26
27class WebAutofillPopup {
28 public:
29 virtual ~WebAutofillPopup() {}
30
31 virtual void Show() = 0;
32
33 virtual void UpdateDataListValues(
34 const std::vector<base::string16>& values,
35 const std::vector<base::string16>& labels) = 0;
36
37 virtual void Hide() = 0;
38};
39
40} // namespace oxide
41
42#endif // _OXIDE_SHARED_BROWSER_WEB_AUTOFILL_POPUP_H_
diff --git a/shared/browser/autofill/web_autofill_popup_client.h b/shared/browser/autofill/web_autofill_popup_client.h
0new file mode 10064443new file mode 100644
index 0000000..4eecc06
--- /dev/null
+++ b/shared/browser/autofill/web_autofill_popup_client.h
@@ -0,0 +1,41 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_SHARED_BROWSER_AUTOFILL_WEB_AUTOFILL_POPUP_CLIENT_H_
19#define _OXIDE_SHARED_BROWSER_AUTOFILL_WEB_AUTOFILL_POPUP_CLIENT_H_
20
21#include "base/strings/string16.h"
22
23namespace oxide {
24
25class WebAutofillPopupClient {
26 public:
27 virtual ~WebAutofillPopupClient() {}
28
29 virtual void Close() = 0;
30 virtual void SelectSuggestion(int frontend_id,
31 const base::string16& value) = 0;
32 virtual void ClearSelection() = 0;
33 virtual void AcceptSuggestion(int frontend_id,
34 const base::string16& value) = 0;
35 virtual bool RemoveSuggestion(int frontend_id,
36 const base::string16& value) = 0;
37};
38
39} // namespace oxide
40
41#endif // _OXIDE_SHARED_BROWSER_AUTOFILL_WEB_AUTOFILL_POPUP_CLIENT_H_
diff --git a/shared/browser/filtered_pref_store.cc b/shared/browser/filtered_pref_store.cc
0new file mode 10064442new file mode 100644
index 0000000..bfc7931
--- /dev/null
+++ b/shared/browser/filtered_pref_store.cc
@@ -0,0 +1,181 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#include "filtered_pref_store.h"
19
20#include "base/stl_util.h"
21#include "base/values.h"
22#include "components/prefs/in_memory_pref_store.h"
23#include "components/prefs/json_pref_store.h"
24
25namespace oxide {
26
27FilteredPrefStore::AggregatingObserver::AggregatingObserver(
28 FilteredPrefStore* outer)
29 : outer_(outer) {}
30
31void FilteredPrefStore::AggregatingObserver::OnPrefValueChanged(
32 const std::string& key) {
33 if (!outer_->IsInitializationComplete()) {
34 return;
35 }
36
37 for (auto& observer : outer_->observers_) {
38 observer.OnPrefValueChanged(key);
39 }
40}
41
42void FilteredPrefStore::AggregatingObserver::OnInitializationCompleted(
43 bool succeeded) {
44 // This always comes the persistent pref store. In-memory pref stores don't
45 // notify observers of their initialization status.
46 if (succeeded && outer_->read_error_delegate_) {
47 PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
48 if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
49 outer_->read_error_delegate_->OnError(read_error);
50 }
51
52 for (auto& observer : outer_->observers_) {
53 observer.OnInitializationCompleted(true);
54 }
55}
56
57FilteredPrefStore::FilteredPrefStore(
58 const scoped_refptr<InMemoryPrefStore>& volatile_pref_store,
59 const scoped_refptr<JsonPrefStore>& persistent_pref_store,
60 const std::set<std::string>& persistent_pref_names)
61 : volatile_pref_store_(volatile_pref_store),
62 persistent_pref_store_(persistent_pref_store),
63 persistent_preference_names_(persistent_pref_names),
64 aggregating_observer_(this) {
65 volatile_pref_store_->AddObserver(&aggregating_observer_);
66 persistent_pref_store_->AddObserver(&aggregating_observer_);
67}
68
69void FilteredPrefStore::AddObserver(Observer* observer) {
70 observers_.AddObserver(observer);
71}
72
73void FilteredPrefStore::RemoveObserver(Observer* observer) {
74 observers_.RemoveObserver(observer);
75}
76
77bool FilteredPrefStore::HasObservers() const {
78 return observers_.might_have_observers();
79}
80
81bool FilteredPrefStore::IsInitializationComplete() const {
82 return persistent_pref_store_->IsInitializationComplete();
83}
84
85bool FilteredPrefStore::GetValue(const std::string& key,
86 const base::Value** result) const {
87 return StoreForKey(key)->GetValue(key, result);
88}
89
90std::unique_ptr<base::DictionaryValue> FilteredPrefStore::GetValues() const {
91 auto values = volatile_pref_store_->GetValues();
92 auto persistent_pref_store_values = persistent_pref_store_->GetValues();
93 for (const auto& key : persistent_preference_names_) {
94 const base::Value* value = nullptr;
95 if (persistent_pref_store_values->Get(key, &value)) {
96 values->Set(key, value->CreateDeepCopy());
97 } else {
98 values->Remove(key, nullptr);
99 }
100 }
101 return values;
102}
103
104void FilteredPrefStore::SetValue(const std::string& key,
105 std::unique_ptr<base::Value> value,
106 uint32_t flags) {
107 StoreForKey(key)->SetValue(key, std::move(value), flags);
108}
109
110void FilteredPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
111 StoreForKey(key)->RemoveValue(key, flags);
112}
113
114bool FilteredPrefStore::GetMutableValue(const std::string& key,
115 base::Value** result) {
116 return StoreForKey(key)->GetMutableValue(key, result);
117}
118
119void FilteredPrefStore::ReportValueChanged(const std::string& key,
120 uint32_t flags) {
121 StoreForKey(key)->ReportValueChanged(key, flags);
122}
123
124void FilteredPrefStore::SetValueSilently(const std::string& key,
125 std::unique_ptr<base::Value> value,
126 uint32_t flags) {
127 StoreForKey(key)->SetValueSilently(key, std::move(value), flags);
128}
129
130bool FilteredPrefStore::ReadOnly() const {
131 return persistent_pref_store_->ReadOnly();
132}
133
134PersistentPrefStore::PrefReadError FilteredPrefStore::GetReadError() const {
135 return persistent_pref_store_->GetReadError();
136}
137
138PersistentPrefStore::PrefReadError FilteredPrefStore::ReadPrefs() {
139 return persistent_pref_store_->ReadPrefs();
140}
141
142void FilteredPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
143 read_error_delegate_.reset(error_delegate);
144 persistent_pref_store_->ReadPrefsAsync(nullptr);
145}
146
147void FilteredPrefStore::CommitPendingWrite() {
148 persistent_pref_store_->CommitPendingWrite();
149}
150
151void FilteredPrefStore::SchedulePendingLossyWrites() {
152 persistent_pref_store_->SchedulePendingLossyWrites();
153}
154
155void FilteredPrefStore::ClearMutableValues() {
156 NOTIMPLEMENTED();
157}
158
159FilteredPrefStore::~FilteredPrefStore() {
160 volatile_pref_store_->RemoveObserver(&aggregating_observer_);
161 persistent_pref_store_->RemoveObserver(&aggregating_observer_);
162}
163
164PersistentPrefStore* FilteredPrefStore::StoreForKey(const std::string& key) {
165 if (base::ContainsKey(persistent_preference_names_, key)) {
166 return persistent_pref_store_.get();
167 } else {
168 return volatile_pref_store_.get();
169 }
170}
171
172const PersistentPrefStore* FilteredPrefStore::StoreForKey(
173 const std::string& key) const {
174 if (base::ContainsKey(persistent_preference_names_, key)) {
175 return persistent_pref_store_.get();
176 } else {
177 return volatile_pref_store_.get();
178 }
179}
180
181} // namespace oxide
diff --git a/shared/browser/filtered_pref_store.h b/shared/browser/filtered_pref_store.h
0new file mode 100644182new file mode 100644
index 0000000..07eee99
--- /dev/null
+++ b/shared/browser/filtered_pref_store.h
@@ -0,0 +1,107 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#ifndef _OXIDE_SHARED_BROWSER_FILTERED_PREF_STORE_H_
19#define _OXIDE_SHARED_BROWSER_FILTERED_PREF_STORE_H_
20
21#include <set>
22#include <string>
23
24#include "base/macros.h"
25#include "base/memory/ref_counted.h"
26#include "base/observer_list.h"
27#include "components/prefs/persistent_pref_store.h"
28
29class InMemoryPrefStore;
30class JsonPrefStore;
31
32namespace oxide {
33
34// Inspired by chromium's SegregatedPrefStore: all preferences are stored
35// in memory (and thus not persisted) except for a selected set which are
36// persisted on disk.
37class FilteredPrefStore : public PersistentPrefStore {
38 public:
39 FilteredPrefStore(
40 const scoped_refptr<InMemoryPrefStore>& volatile_pref_store,
41 const scoped_refptr<JsonPrefStore>& persistent_pref_store,
42 const std::set<std::string>& persistent_pref_names);
43
44 // PrefStore:
45 void AddObserver(Observer* observer) override;
46 void RemoveObserver(Observer* observer) override;
47 bool HasObservers() const override;
48 bool IsInitializationComplete() const override;
49 bool GetValue(const std::string& key,
50 const base::Value** result) const override;
51 std::unique_ptr<base::DictionaryValue> GetValues() const override;
52
53 // WriteablePrefStore:
54 void SetValue(const std::string& key,
55 std::unique_ptr<base::Value> value,
56 uint32_t flags) override;
57 void RemoveValue(const std::string& key, uint32_t flags) override;
58
59 // PersistentPrefStore:
60 bool GetMutableValue(const std::string& key, base::Value** result) override;
61 void ReportValueChanged(const std::string& key, uint32_t flags) override;
62 void SetValueSilently(const std::string& key,
63 std::unique_ptr<base::Value> value,
64 uint32_t flags) override;
65 bool ReadOnly() const override;
66 PrefReadError GetReadError() const override;
67 PrefReadError ReadPrefs() override;
68 void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
69 void CommitPendingWrite() override;
70 void SchedulePendingLossyWrites() override;
71
72 void ClearMutableValues() override;
73
74 private:
75 class AggregatingObserver : public PrefStore::Observer {
76 public:
77 explicit AggregatingObserver(FilteredPrefStore* outer);
78
79 // PrefStore::Observer:
80 void OnPrefValueChanged(const std::string& key) override;
81 void OnInitializationCompleted(bool succeeded) override;
82
83 private:
84 FilteredPrefStore* outer_;
85
86 DISALLOW_COPY_AND_ASSIGN(AggregatingObserver);
87 };
88
89 ~FilteredPrefStore() override;
90
91 PersistentPrefStore* StoreForKey(const std::string& key);
92 const PersistentPrefStore* StoreForKey(const std::string& key) const;
93
94 scoped_refptr<InMemoryPrefStore> volatile_pref_store_;
95 scoped_refptr<JsonPrefStore> persistent_pref_store_;
96 std::set<std::string> persistent_preference_names_;
97
98 std::unique_ptr<PersistentPrefStore::ReadErrorDelegate> read_error_delegate_;
99 base::ObserverList<PrefStore::Observer, true> observers_;
100 AggregatingObserver aggregating_observer_;
101
102 DISALLOW_COPY_AND_ASSIGN(FilteredPrefStore);
103};
104
105} // namespace oxide
106
107#endif // _OXIDE_SHARED_BROWSER_FILTERED_PREF_STORE_H_
diff --git a/shared/browser/filtered_pref_store_unittest.cc b/shared/browser/filtered_pref_store_unittest.cc
0new file mode 100644108new file mode 100644
index 0000000..90e67d8
--- /dev/null
+++ b/shared/browser/filtered_pref_store_unittest.cc
@@ -0,0 +1,209 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2017 Canonical Ltd.
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18#include "base/files/file_util.h"
19#include "base/files/scoped_temp_dir.h"
20#include "base/macros.h"
21#include "base/memory/ptr_util.h"
22#include "base/message_loop/message_loop.h"
23#include "base/run_loop.h"
24#include "base/values.h"
25#include "components/prefs/in_memory_pref_store.h"
26#include "components/prefs/json_pref_store.h"
27#include "components/prefs/pref_filter.h"
28#include "components/prefs/pref_store_observer_mock.h"
29#include "testing/gtest/include/gtest/gtest.h"
30
31#include "filtered_pref_store.h"
32
33namespace {
34
35const char kPersistentStoreFileName[] = "store.json";
36const char kEmptyJson[] = "{}";
37const char kInvalidJson[] = "invalid";
38
39const char kPersistentPref[] = "persistent_pref";
40const char kVolatilePref[] = "volatile_pref";
41const char kSharedPref[] = "shared_pref";
42
43} // namespace
44
45namespace oxide {
46
47class FilteredPrefStoreTest : public testing::Test {
48 public:
49 FilteredPrefStoreTest() = default;
50
51 protected:
52 void SetUp() override {
53 volatile_store_ = new InMemoryPrefStore;
54
55 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
56 persistent_store_filepath_ =
57 temp_dir_.GetPath().AppendASCII(kPersistentStoreFileName);
58 persistent_store_ = new JsonPrefStore(persistent_store_filepath_,
59 message_loop_.task_runner(),
60 std::unique_ptr<PrefFilter>());
61 std::set<std::string> persistent_pref_names;
62 persistent_pref_names.insert(kPersistentPref);
63 persistent_pref_names.insert(kSharedPref);
64
65 filtered_store_ = new FilteredPrefStore(volatile_store_, persistent_store_,
66 persistent_pref_names);
67
68 filtered_store_->AddObserver(&observer_);
69 }
70
71 void TearDown() override {
72 filtered_store_->RemoveObserver(&observer_);
73 base::RunLoop().RunUntilIdle();
74 }
75
76 base::ScopedTempDir temp_dir_;
77 base::FilePath persistent_store_filepath_;
78 base::MessageLoop message_loop_;
79
80 PrefStoreObserverMock observer_;
81
82 scoped_refptr<InMemoryPrefStore> volatile_store_;
83 scoped_refptr<JsonPrefStore> persistent_store_;
84 scoped_refptr<FilteredPrefStore> filtered_store_;
85
86 DISALLOW_COPY_AND_ASSIGN(FilteredPrefStoreTest);
87};
88
89TEST_F(FilteredPrefStoreTest, ReadPrefsNoFile) {
90 ASSERT_FALSE(base::PathExists(persistent_store_filepath_));
91 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
92 filtered_store_->ReadPrefs());
93}
94
95TEST_F(FilteredPrefStoreTest, ReadPrefsParseError) {
96 ASSERT_LT(0, base::WriteFile(persistent_store_filepath_,
97 kInvalidJson, arraysize(kInvalidJson) - 1));
98 ASSERT_TRUE(base::PathExists(persistent_store_filepath_));
99 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
100 filtered_store_->ReadPrefs());
101}
102
103TEST_F(FilteredPrefStoreTest, ReadPrefsSuccess) {
104 ASSERT_LT(0, base::WriteFile(persistent_store_filepath_,
105 kEmptyJson, arraysize(kEmptyJson) - 1));
106 ASSERT_TRUE(base::PathExists(persistent_store_filepath_));
107 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
108 filtered_store_->ReadPrefs());
109}
110
111TEST_F(FilteredPrefStoreTest, IsInitializationComplete) {
112 EXPECT_FALSE(filtered_store_->IsInitializationComplete());
113 filtered_store_->ReadPrefs();
114 EXPECT_TRUE(filtered_store_->IsInitializationComplete());
115}
116
117TEST_F(FilteredPrefStoreTest, Observer) {
118 EXPECT_FALSE(observer_.initialized);
119 filtered_store_->ReadPrefs();
120 EXPECT_TRUE(observer_.initialized);
121 EXPECT_TRUE(observer_.initialization_success);
122 EXPECT_TRUE(observer_.changed_keys.empty());
123 filtered_store_->SetValue(kPersistentPref,
124 base::MakeUnique<base::Value>(1),
125 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
126 observer_.VerifyAndResetChangedKey(kPersistentPref);
127 filtered_store_->SetValue(kVolatilePref,
128 base::MakeUnique<base::Value>(2),
129 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
130 observer_.VerifyAndResetChangedKey(kVolatilePref);
131}
132
133TEST_F(FilteredPrefStoreTest, StoreValues) {
134 PrefStoreObserverMock volatile_observer;
135 volatile_store_->AddObserver(&volatile_observer);
136
137 PrefStoreObserverMock persistent_observer;
138 persistent_store_->AddObserver(&persistent_observer);
139
140 filtered_store_->ReadPrefs();
141 EXPECT_TRUE(persistent_observer.initialized);
142 EXPECT_TRUE(persistent_observer.initialization_success);
143
144 filtered_store_->SetValue(kPersistentPref,
145 base::MakeUnique<base::Value>(3),
146 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
147 persistent_observer.VerifyAndResetChangedKey(kPersistentPref);
148 EXPECT_TRUE(persistent_store_->GetValue(kPersistentPref, nullptr));
149 EXPECT_FALSE(volatile_store_->GetValue(kPersistentPref, nullptr));
150 EXPECT_TRUE(filtered_store_->GetValue(kPersistentPref, nullptr));
151
152 filtered_store_->SetValue(kVolatilePref,
153 base::MakeUnique<base::Value>(4),
154 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
155 volatile_observer.VerifyAndResetChangedKey(kVolatilePref);
156 EXPECT_TRUE(volatile_store_->GetValue(kVolatilePref, nullptr));
157 EXPECT_FALSE(persistent_store_->GetValue(kVolatilePref, nullptr));
158 EXPECT_TRUE(filtered_store_->GetValue(kVolatilePref, nullptr));
159}
160
161TEST_F(FilteredPrefStoreTest, ReadValues) {
162 filtered_store_->ReadPrefs();
163 persistent_store_->SetValue(kPersistentPref,
164 base::MakeUnique<base::Value>(5),
165 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
166 volatile_store_->SetValue(kVolatilePref,
167 base::MakeUnique<base::Value>(6),
168 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
169
170 EXPECT_TRUE(persistent_store_->GetValue(kPersistentPref, nullptr));
171 EXPECT_FALSE(persistent_store_->GetValue(kVolatilePref, nullptr));
172
173 EXPECT_TRUE(volatile_store_->GetValue(kVolatilePref, nullptr));
174 EXPECT_FALSE(volatile_store_->GetValue(kPersistentPref, nullptr));
175
176 EXPECT_TRUE(filtered_store_->GetValue(kPersistentPref, nullptr));
177 EXPECT_TRUE(filtered_store_->GetValue(kVolatilePref, nullptr));
178}
179
180TEST_F(FilteredPrefStoreTest, GetValues) {
181 filtered_store_->ReadPrefs();
182 persistent_store_->SetValue(kPersistentPref,
183 base::MakeUnique<base::Value>(7),
184 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
185 volatile_store_->SetValue(kVolatilePref,
186 base::MakeUnique<base::Value>(8),
187 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
188
189 persistent_store_->SetValue(kSharedPref,
190 base::MakeUnique<base::Value>(9),
191 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
192 volatile_store_->SetValue(kSharedPref,
193 base::MakeUnique<base::Value>(10),
194 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
195
196 auto values = filtered_store_->GetValues();
197 const base::Value* value = nullptr;
198
199 EXPECT_TRUE(values->Get(kPersistentPref, &value));
200 EXPECT_TRUE(base::Value(7).Equals(value));
201
202 EXPECT_TRUE(values->Get(kVolatilePref, &value));
203 EXPECT_TRUE(base::Value(8).Equals(value));
204
205 EXPECT_TRUE(values->Get(kSharedPref, &value));
206 EXPECT_TRUE(base::Value(9).Equals(value));
207}
208
209} // namespace oxide
diff --git a/shared/browser/oxide_browser_context.cc b/shared/browser/oxide_browser_context.cc
index 5652924..265efc5 100644
--- a/shared/browser/oxide_browser_context.cc
+++ b/shared/browser/oxide_browser_context.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,16 @@
35#include "base/threading/sequenced_worker_pool.h"35#include "base/threading/sequenced_worker_pool.h"
36#include "base/threading/thread_restrictions.h"36#include "base/threading/thread_restrictions.h"
37#include "base/threading/worker_pool.h"37#include "base/threading/worker_pool.h"
38#include "components/autofill/core/browser/autofill_manager.h"
39#include "components/autofill/core/common/autofill_pref_names.h"
38#include "components/keyed_service/content/browser_context_dependency_manager.h"40#include "components/keyed_service/content/browser_context_dependency_manager.h"
41#include "components/pref_registry/pref_registry_syncable.h"
42#include "components/prefs/in_memory_pref_store.h"
43#include "components/prefs/json_pref_store.h"
44#include "components/prefs/overlay_user_pref_store.h"
45#include "components/prefs/pref_filter.h"
46#include "components/prefs/pref_notifier_impl.h"
47#include "components/prefs/pref_value_store.h"
39#include "content/browser/loader/resource_dispatcher_host_impl.h" // nogncheck48#include "content/browser/loader/resource_dispatcher_host_impl.h" // nogncheck
40#include "content/public/browser/browser_thread.h"49#include "content/public/browser/browser_thread.h"
41#include "content/public/browser/render_process_host.h"50#include "content/public/browser/render_process_host.h"
@@ -67,6 +76,7 @@
67#include "shared/common/oxide_constants.h"76#include "shared/common/oxide_constants.h"
68#include "shared/common/oxide_content_client.h"77#include "shared/common/oxide_content_client.h"
6978
79#include "filtered_pref_store.h"
70#include "oxide_browser_context_delegate.h"80#include "oxide_browser_context_delegate.h"
71#include "oxide_browser_context_destroyer.h"81#include "oxide_browser_context_destroyer.h"
72#include "oxide_browser_process_main.h"82#include "oxide_browser_process_main.h"
@@ -123,6 +133,8 @@ void CleanupOldCacheDir(const base::FilePath& path) {
123 base::DeleteFile(path, true);133 base::DeleteFile(path, true);
124}134}
125135
136void DoNothingHandleReadError(PersistentPrefStore::PrefReadError error) {}
137
126} // namespace138} // namespace
127139
128class MainURLRequestContextGetter : public URLRequestContextGetter {140class MainURLRequestContextGetter : public URLRequestContextGetter {
@@ -527,6 +539,41 @@ net::CookieStore* BrowserContextIOData::GetCookieStore() const {
527 return cookie_store_owner_->store();539 return cookie_store_owner_->store();
528}540}
529541
542ClonablePrefService::ClonablePrefService(
543 PrefNotifierImpl* pref_notifier,
544 PrefValueStore* pref_value_store,
545 PersistentPrefStore* user_prefs,
546 PrefRegistry* pref_registry,
547 base::Callback<void(PersistentPrefStore::PrefReadError)>
548 read_error_callback,
549 bool async)
550 : PrefService(pref_notifier,
551 pref_value_store,
552 user_prefs,
553 pref_registry,
554 read_error_callback,
555 async) {
556}
557
558ClonablePrefService::~ClonablePrefService() {}
559
560ClonablePrefService* ClonablePrefService::CreateIncognitoPrefService() {
561 PrefNotifierImpl* pref_notifier = new PrefNotifierImpl();
562 OverlayUserPrefStore* incognito_pref_store =
563 new OverlayUserPrefStore(user_pref_store_.get());
564 return new ClonablePrefService(
565 pref_notifier,
566 pref_value_store_->CloneAndSpecialize(nullptr,
567 nullptr,
568 nullptr,
569 nullptr,
570 incognito_pref_store,
571 nullptr,
572 pref_registry_->defaults().get(),
573 pref_notifier),
574 incognito_pref_store, pref_registry_.get(), read_error_callback_, false);
575}
576
530class BrowserContextImpl;577class BrowserContextImpl;
531578
532class OTRBrowserContextImpl : public BrowserContext {579class OTRBrowserContextImpl : public BrowserContext {
@@ -578,6 +625,9 @@ OTRBrowserContextImpl::OTRBrowserContextImpl(
578 original_context_(original) {625 original_context_(original) {
579 BrowserContextDependencyManager::GetInstance()626 BrowserContextDependencyManager::GetInstance()
580 ->CreateBrowserContextServices(this);627 ->CreateBrowserContextServices(this);
628
629 prefs_.reset(static_cast<ClonablePrefService*>(original->GetPrefs())
630 ->CreateIncognitoPrefService());
581}631}
582632
583BrowserContext* BrowserContextImpl::GetOffTheRecordContext() {633BrowserContext* BrowserContextImpl::GetOffTheRecordContext() {
@@ -597,8 +647,15 @@ BrowserContextImpl::~BrowserContextImpl() {
597647
598BrowserContextImpl::BrowserContextImpl(const BrowserContext::Params& params)648BrowserContextImpl::BrowserContextImpl(const BrowserContext::Params& params)
599 : BrowserContext(new BrowserContextIODataImpl(params)) {649 : BrowserContext(new BrowserContextIODataImpl(params)) {
600 if (!GetPath().empty()) {650 base::FilePath path = GetPath();
601 base::FilePath gpu_cache = GetPath().Append(FILE_PATH_LITERAL("GPUCache"));651 if (!path.empty()) {
652 if (!base::PathExists(path)) {
653 if (!base::CreateDirectory(path)) {
654 LOG(ERROR) << "Failed to create profile data path: " << path.value();
655 }
656 }
657
658 base::FilePath gpu_cache = path.Append(FILE_PATH_LITERAL("GPUCache"));
602 content::BrowserThread::PostTask(659 content::BrowserThread::PostTask(
603 content::BrowserThread::FILE,660 content::BrowserThread::FILE,
604 FROM_HERE,661 FROM_HERE,
@@ -607,6 +664,44 @@ BrowserContextImpl::BrowserContextImpl(const BrowserContext::Params& params)
607664
608 BrowserContextDependencyManager::GetInstance()665 BrowserContextDependencyManager::GetInstance()
609 ->CreateBrowserContextServices(this);666 ->CreateBrowserContextServices(this);
667
668 autofill::AutofillManager::RegisterProfilePrefs(pref_registry_.get());
669 pref_registry_->SetDefaultPrefValue(
670 autofill::prefs::kAutofillEnabled,
671 new base::Value(false));
672 PrefNotifierImpl* pref_notifier = new PrefNotifierImpl();
673 scoped_refptr<PersistentPrefStore> user_prefs;
674 if (!path.empty()) {
675 base::FilePath pref_store_path =
676 path.Append(FILE_PATH_LITERAL("Preferences"));
677 scoped_refptr<base::SequencedTaskRunner> task_runner =
678 JsonPrefStore::GetTaskRunnerForFile(
679 pref_store_path, content::BrowserThread::GetBlockingPool());
680 // Persist only selected preferences on disk
681 scoped_refptr<InMemoryPrefStore> volatile_pref_store(new InMemoryPrefStore);
682 scoped_refptr<JsonPrefStore> persistent_pref_store(new JsonPrefStore(
683 pref_store_path, task_runner, std::unique_ptr<PrefFilter>()));
684 std::set<std::string> persistent_pref_names;
685 persistent_pref_names.insert(autofill::prefs::kAutofillLastVersionDeduped);
686 user_prefs = make_scoped_refptr(new FilteredPrefStore(
687 volatile_pref_store, persistent_pref_store, persistent_pref_names));
688 } else {
689 user_prefs = make_scoped_refptr(new InMemoryPrefStore);
690 }
691 prefs_.reset(new ClonablePrefService(
692 pref_notifier,
693 new PrefValueStore(nullptr,
694 nullptr,
695 nullptr,
696 nullptr,
697 user_prefs.get(),
698 nullptr,
699 pref_registry_->defaults().get(),
700 pref_notifier),
701 user_prefs.get(),
702 pref_registry_.get(),
703 base::Bind(&DoNothingHandleReadError),
704 true));
610}705}
611706
612void BrowserContext::Deleter::operator()(BrowserContext* context) {707void BrowserContext::Deleter::operator()(BrowserContext* context) {
@@ -702,7 +797,8 @@ BrowserContext::CreateMediaRequestContextForStoragePartition(
702}797}
703798
704BrowserContext::BrowserContext(BrowserContextIOData* io_data)799BrowserContext::BrowserContext(BrowserContextIOData* io_data)
705 : io_data_(io_data) {800 : pref_registry_(new user_prefs::PrefRegistrySyncable),
801 io_data_(io_data) {
706 CHECK(BrowserProcessMain::GetInstance()->IsRunning()) <<802 CHECK(BrowserProcessMain::GetInstance()->IsRunning()) <<
707 "The main browser process components must be started before " <<803 "The main browser process components must be started before " <<
708 "creating a context";804 "creating a context";
diff --git a/shared/browser/oxide_browser_context.h b/shared/browser/oxide_browser_context.h
index e7f30d5..de32778 100644
--- a/shared/browser/oxide_browser_context.h
+++ b/shared/browser/oxide_browser_context.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -25,6 +25,7 @@
25#include "base/memory/ref_counted.h"25#include "base/memory/ref_counted.h"
26#include "base/synchronization/lock.h"26#include "base/synchronization/lock.h"
27#include "base/threading/non_thread_safe.h"27#include "base/threading/non_thread_safe.h"
28#include "components/prefs/pref_service.h"
28#include "content/public/browser/browser_context.h"29#include "content/public/browser/browser_context.h"
29#include "content/public/browser/content_browser_client.h"30#include "content/public/browser/content_browser_client.h"
30#include "content/public/browser/cookie_store_factory.h"31#include "content/public/browser/cookie_store_factory.h"
@@ -49,6 +50,10 @@ class TransportSecurityState;
4950
50}51}
5152
53namespace user_prefs {
54class PrefRegistrySyncable;
55}
56
52namespace oxide {57namespace oxide {
5358
54class BrowserContext;59class BrowserContext;
@@ -58,6 +63,7 @@ class BrowserContextDelegate;
58class BrowserContextImpl;63class BrowserContextImpl;
59class BrowserContextSharedData;64class BrowserContextSharedData;
60class BrowserContextSharedIOData;65class BrowserContextSharedIOData;
66class ClonablePrefService;
61class CookieStoreOwner;67class CookieStoreOwner;
62class CookieStoreProxy;68class CookieStoreProxy;
63class GeolocationPermissionContext;69class GeolocationPermissionContext;
@@ -136,7 +142,20 @@ class BrowserContextIOData {
136 temporary_saved_permission_context_;142 temporary_saved_permission_context_;
137};143};
138144
139class BrowserContext;145class ClonablePrefService : public PrefService {
146 public:
147 ClonablePrefService(
148 PrefNotifierImpl* pref_notifier,
149 PrefValueStore* pref_value_store,
150 PersistentPrefStore* user_prefs,
151 PrefRegistry* pref_registry,
152 base::Callback<void(PersistentPrefStore::PrefReadError)>
153 read_error_callback,
154 bool async);
155 ~ClonablePrefService() override;
156
157 ClonablePrefService* CreateIncognitoPrefService();
158};
140159
141// This class holds the context needed for a browsing session. It lives on160// This class holds the context needed for a browsing session. It lives on
142// and must only be accessed on the UI thread161// and must only be accessed on the UI thread
@@ -230,11 +249,16 @@ class OXIDE_SHARED_EXPORT BrowserContext : public content::BrowserContext,
230249
231 BrowserContextIOData* GetIOData() const;250 BrowserContextIOData* GetIOData() const;
232251
252 PrefService* GetPrefs() { return prefs_.get(); }
253
233 protected:254 protected:
234 BrowserContext(BrowserContextIOData* io_data);255 BrowserContext(BrowserContextIOData* io_data);
235256
236 BrowserContextIOData* io_data() const { return io_data_; }257 BrowserContextIOData* io_data() const { return io_data_; }
237258
259 scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry_;
260 std::unique_ptr<ClonablePrefService> prefs_;
261
238 private:262 private:
239 // content::BrowserContext implementation263 // content::BrowserContext implementation
240 std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(264 std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(
diff --git a/shared/browser/oxide_browser_platform_integration.cc b/shared/browser/oxide_browser_platform_integration.cc
index e30abbe..10340a8 100644
--- a/shared/browser/oxide_browser_platform_integration.cc
+++ b/shared/browser/oxide_browser_platform_integration.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2014-2015 Canonical Ltd.2// Copyright (C) 2014-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -30,6 +30,7 @@ namespace oxide {
30namespace {30namespace {
3131
32const char kDefaultApplicationName[] = "Oxide";32const char kDefaultApplicationName[] = "Oxide";
33const char kDefaultApplicationLocale[] = "C";
3334
34BrowserPlatformIntegration* g_instance;35BrowserPlatformIntegration* g_instance;
3536
@@ -88,6 +89,10 @@ std::string BrowserPlatformIntegration::GetApplicationName() {
88 return kDefaultApplicationName;89 return kDefaultApplicationName;
89}90}
9091
92std::string BrowserPlatformIntegration::GetApplicationLocale() {
93 return kDefaultApplicationLocale;
94}
95
91std::unique_ptr<DragSource> BrowserPlatformIntegration::CreateDragSource(96std::unique_ptr<DragSource> BrowserPlatformIntegration::CreateDragSource(
92 DragSourceClient* client) {97 DragSourceClient* client) {
93 return nullptr;98 return nullptr;
diff --git a/shared/browser/oxide_browser_platform_integration.h b/shared/browser/oxide_browser_platform_integration.h
index 57f8568..18c6f93 100644
--- a/shared/browser/oxide_browser_platform_integration.h
+++ b/shared/browser/oxide_browser_platform_integration.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2014-2015 Canonical Ltd.2// Copyright (C) 2014-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -116,6 +116,9 @@ class OXIDE_SHARED_EXPORT BrowserPlatformIntegration {
116 // Get the application name. Can be called on any thread116 // Get the application name. Can be called on any thread
117 virtual std::string GetApplicationName();117 virtual std::string GetApplicationName();
118118
119 // Get the application locale. Can be called on any thread
120 virtual std::string GetApplicationLocale();
121
119 // Create a new DragSource implementation. Ownership of |client| is not122 // Create a new DragSource implementation. Ownership of |client| is not
120 // transferred, and |client| will outlive the returned DragSource.123 // transferred, and |client| will outlive the returned DragSource.
121 // Called on the UI thread124 // Called on the UI thread
diff --git a/shared/browser/oxide_content_browser_client.cc b/shared/browser/oxide_content_browser_client.cc
index c5b627a..b26fa9e 100644
--- a/shared/browser/oxide_content_browser_client.cc
+++ b/shared/browser/oxide_content_browser_client.cc
@@ -22,9 +22,12 @@
22#include <vector>22#include <vector>
2323
24#include "base/command_line.h"24#include "base/command_line.h"
25#include "base/json/json_reader.h"
25#include "base/logging.h"26#include "base/logging.h"
26#include "base/memory/ptr_util.h"27#include "base/memory/ptr_util.h"
27#include "base/memory/ref_counted.h"28#include "base/memory/ref_counted.h"
29#include "components/autofill/content/browser/content_autofill_driver_factory.h"
30#include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
28#include "content/public/browser/certificate_request_result_type.h"31#include "content/public/browser/certificate_request_result_type.h"
29#include "content/public/browser/interstitial_page.h"32#include "content/public/browser/interstitial_page.h"
30#include "content/public/browser/permission_type.h"33#include "content/public/browser/permission_type.h"
@@ -34,10 +37,12 @@
34#include "content/public/browser/resource_dispatcher_host.h"37#include "content/public/browser/resource_dispatcher_host.h"
35#include "content/public/common/content_switches.h"38#include "content/public/common/content_switches.h"
36#include "content/public/common/service_info.h"39#include "content/public/common/service_info.h"
40#include "content/public/common/service_names.mojom.h"
37#include "content/public/common/web_preferences.h"41#include "content/public/common/web_preferences.h"
38#include "ppapi/features/features.h"42#include "ppapi/features/features.h"
39#include "services/device/public/interfaces/constants.mojom.h"43#include "services/device/public/interfaces/constants.mojom.h"
40#include "services/service_manager/public/cpp/interface_registry.h"44#include "services/service_manager/public/cpp/interface_registry.h"
45#include "ui/base/resource/resource_bundle.h"
41#include "ui/display/display.h"46#include "ui/display/display.h"
42#include "ui/native_theme/native_theme_switches.h"47#include "ui/native_theme/native_theme_switches.h"
4348
@@ -79,6 +84,8 @@
79#include "pepper/oxide_pepper_host_factory_browser.h"84#include "pepper/oxide_pepper_host_factory_browser.h"
80#endif85#endif
8186
87#include "shared/grit/oxide_resources.h"
88
82namespace oxide {89namespace oxide {
8390
84content::BrowserMainParts* ContentBrowserClient::CreateBrowserMainParts(91content::BrowserMainParts* ContentBrowserClient::CreateBrowserMainParts(
@@ -316,6 +323,23 @@ ContentBrowserClient::GetDevToolsManagerDelegate() {
316 return new DevToolsManagerDelegate();323 return new DevToolsManagerDelegate();
317}324}
318325
326void ContentBrowserClient::RegisterRenderFrameMojoInterfaces(
327 service_manager::InterfaceRegistry* registry,
328 content::RenderFrameHost* render_frame_host) {
329 DCHECK(registry);
330 registry->AddInterface(
331 base::Bind(&autofill::ContentAutofillDriverFactory::BindAutofillDriver,
332 render_frame_host));
333 registry->AddInterface(
334 base::Bind(&password_manager::ContentPasswordManagerDriverFactory::
335 BindPasswordManagerDriver,
336 render_frame_host));
337 registry->AddInterface(
338 base::Bind(&password_manager::ContentPasswordManagerDriverFactory::
339 BindSensitiveInputVisibilityService,
340 render_frame_host));
341}
342
319void ContentBrowserClient::RegisterInProcessServices(343void ContentBrowserClient::RegisterInProcessServices(
320 StaticServiceMap* services) {344 StaticServiceMap* services) {
321 content::ServiceInfo device_info;345 content::ServiceInfo device_info;
@@ -330,6 +354,23 @@ void ContentBrowserClient::RegisterInProcessServices(
330 services->insert(std::make_pair(device::mojom::kServiceName, device_info));354 services->insert(std::make_pair(device::mojom::kServiceName, device_info));
331}355}
332356
357std::unique_ptr<base::Value> ContentBrowserClient::GetServiceManifestOverlay(
358 base::StringPiece name) {
359 int id = -1;
360 if (name == content::mojom::kBrowserServiceName) {
361 id = IDR_OXIDE_BROWSER_MANIFEST_OVERLAY;
362 } else if (name == content::mojom::kRendererServiceName) {
363 id = IDR_OXIDE_RENDERER_MANIFEST_OVERLAY;
364 }
365 if (id == -1) {
366 return nullptr;
367 }
368
369 base::StringPiece manifest_contents =
370 ui::ResourceBundle::GetSharedInstance().GetRawDataResource(id);
371 return base::JSONReader::Read(manifest_contents);
372}
373
333void ContentBrowserClient::DidCreatePpapiPlugin(content::BrowserPpapiHost* host) {374void ContentBrowserClient::DidCreatePpapiPlugin(content::BrowserPpapiHost* host) {
334#if BUILDFLAG(ENABLE_PLUGINS)375#if BUILDFLAG(ENABLE_PLUGINS)
335 host->GetPpapiHost()->AddHostFactoryFilter(376 host->GetPpapiHost()->AddHostFactoryFilter(
diff --git a/shared/browser/oxide_content_browser_client.h b/shared/browser/oxide_content_browser_client.h
index a55285a..2a963dc 100644
--- a/shared/browser/oxide_content_browser_client.h
+++ b/shared/browser/oxide_content_browser_client.h
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013 Canonical Ltd.2// Copyright (C) 2013-2016 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,6 @@ class ResourceDispatcherHostDelegate;
35namespace oxide {35namespace oxide {
3636
37class BrowserPlatformIntegration;37class BrowserPlatformIntegration;
38class ContentMainDelegate;
39class ResourceDispatcherHostDelegate;38class ResourceDispatcherHostDelegate;
4039
41class ContentBrowserClient final : public content::ContentBrowserClient {40class ContentBrowserClient final : public content::ContentBrowserClient {
@@ -104,7 +103,12 @@ class ContentBrowserClient final : public content::ContentBrowserClient {
104 void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,103 void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
105 content::WebPreferences* prefs) override;104 content::WebPreferences* prefs) override;
106 content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override;105 content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override;
106 void RegisterRenderFrameMojoInterfaces(
107 service_manager::InterfaceRegistry* registry,
108 content::RenderFrameHost* render_frame_host) override;
107 void RegisterInProcessServices(StaticServiceMap* services) override;109 void RegisterInProcessServices(StaticServiceMap* services) override;
110 std::unique_ptr<base::Value> GetServiceManifestOverlay(
111 base::StringPiece name) override;
108 void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;112 void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
109 gpu::GpuControlList::OsType GetOsTypeOverrideForGpuDataManager(113 gpu::GpuControlList::OsType GetOsTypeOverrideForGpuDataManager(
110 std::string* os_version) override;114 std::string* os_version) override;
diff --git a/shared/browser/oxide_user_agent_settings.cc b/shared/browser/oxide_user_agent_settings.cc
index a1fe391..2a8550f 100644
--- a/shared/browser/oxide_user_agent_settings.cc
+++ b/shared/browser/oxide_user_agent_settings.cc
@@ -1,5 +1,5 @@
1// vim:expandtab:shiftwidth=2:tabstop=2:1// vim:expandtab:shiftwidth=2:tabstop=2:
2// Copyright (C) 2013-2016 Canonical Ltd.2// Copyright (C) 2013-2017 Canonical Ltd.
33
4// This library is free software; you can redistribute it and/or4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public5// modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,7 @@
22#include "base/logging.h"22#include "base/logging.h"
23#include "base/memory/singleton.h"23#include "base/memory/singleton.h"
24#include "base/strings/stringprintf.h"24#include "base/strings/stringprintf.h"
25#include "components/autofill/core/common/autofill_pref_names.h"
25#include "components/keyed_service/content/browser_context_dependency_manager.h"26#include "components/keyed_service/content/browser_context_dependency_manager.h"
26#include "components/keyed_service/content/browser_context_keyed_service_factory.h"27#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
27#include "content/public/browser/browser_thread.h"28#include "content/public/browser/browser_thread.h"
@@ -151,6 +152,10 @@ bool UserAgentSettingsIOData::GetDoNotTrack() const {
151 return do_not_track_;152 return do_not_track_;
152}153}
153154
155struct UserAgentSettings::DelayedPrefs {
156 bool autofill_enabled = false;
157};
158
154UserAgentSettings::UserAgentSettings(BrowserContext* context)159UserAgentSettings::UserAgentSettings(BrowserContext* context)
155 : context_(context),160 : context_(context),
156 product_(base::StringPrintf("Chrome/%s", CHROME_VERSION_STRING)),161 product_(base::StringPrintf("Chrome/%s", CHROME_VERSION_STRING)),
@@ -159,6 +164,13 @@ UserAgentSettings::UserAgentSettings(BrowserContext* context)
159 UserAgentSettingsIOData* io_data =164 UserAgentSettingsIOData* io_data =
160 context_->GetIOData()->GetUserAgentSettings();165 context_->GetIOData()->GetUserAgentSettings();
161 io_data->user_agent_ = content::BuildUserAgentFromProduct(product_);166 io_data->user_agent_ = content::BuildUserAgentFromProduct(product_);
167
168 PrefService* prefs = context->GetPrefs();
169 if (prefs->GetInitializationStatus() ==
170 PrefService::INITIALIZATION_STATUS_WAITING) {
171 prefs->AddPrefInitObserver(
172 base::Bind(&UserAgentSettings::OnPrefsLoaded, base::Unretained(this)));
173 }
162}174}
163175
164UserAgentSettings::~UserAgentSettings() {}176UserAgentSettings::~UserAgentSettings() {}
@@ -207,6 +219,13 @@ void UserAgentSettings::RemoveObserver(UserAgentSettingsObserver* observer) {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches