Merge lp:~uriboni/oxide/find-in-page into lp:~oxide-developers/oxide/oxide.trunk
- find-in-page
- Merge into oxide.trunk
Status: | Merged |
---|---|
Merged at revision: | 1088 |
Proposed branch: | lp:~uriboni/oxide/find-in-page |
Merge into: | lp:~oxide-developers/oxide/oxide.trunk |
Diff against target: |
863 lines (+587/-1) 15 files modified
qt/core/api/oxideqfindcontroller.cc (+97/-0) qt/core/api/oxideqfindcontroller.h (+71/-0) qt/core/api/oxideqfindcontroller_p.h (+46/-0) qt/core/browser/oxide_qt_web_view.cc (+16/-1) qt/core/browser/oxide_qt_web_view.h (+7/-0) qt/core/core.gyp (+9/-0) qt/core/glue/oxide_qt_web_view_proxy.h (+11/-0) qt/qmlplugin/oxide_qml_plugin.cc (+5/-0) qt/quick/api/oxideqquickwebview.cc (+7/-0) qt/quick/api/oxideqquickwebview_p.h (+10/-0) qt/tests/qmltests/api/tst_WebView_findController.html (+13/-0) qt/tests/qmltests/api/tst_WebView_findController.qml (+152/-0) qt/tests/qmltests/api/tst_WebView_findControllerManyResults.html (+9/-0) shared/browser/oxide_web_view.cc (+102/-0) shared/browser/oxide_web_view.h (+32/-0) |
To merge this branch: | bzr merge lp:~uriboni/oxide/find-in-page |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Coulson | Approve | ||
Review via email:
|
Commit message
Description of the change
Adds a new API to allow searching text within a page.
- 1063. By Ugo Riboni
-
Remove unrelated changes to cmake file
- 1064. By Ugo Riboni
-
Minor code style fixes
- 1065. By Ugo Riboni
-
Make findInPage group property constant to prevent non-notifyable property warnings
- 1066. By Ugo Riboni
-
Merge changes from trunk
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Olivier Tilloy (osomon) wrote : | # |
- 1067. By Ugo Riboni
-
Fix code style (braces, indentation)
- 1068. By Ugo Riboni
-
Improve some tests
- 1069. By Ugo Riboni
-
Remove useless initialization
- 1070. By Ugo Riboni
-
Add explanatory comment and fix indentation
- 1071. By Ugo Riboni
-
Merge changes from trunk
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Coulson (chrisccoulson) wrote : | # |
Thanks for working on this. I have some general comments:
- I think I'd prefer WebView.
- The implementation doesn't need to live in qt/quick/api - it should go in qt/core/api as OxideQFindContr
- As we want to open up the C++ API in the future, the data members on the public class should be in a private class.
I've also left some comments inline.
- 1072. By Ugo Riboni
-
Refactor all the logic into an OxideQFindContr
oller class owned by oxide::qt::WebView. The QML API merely exposes it through the renamed findController property. Address other minor issues from code review. - 1073. By Ugo Riboni
-
Merge changes from trunk
- 1074. By Ugo Riboni
-
Move all non-QT code to oxide::WebView
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ugo Riboni (uriboni) wrote : | # |
I think all your comments should be addressed at this point, except some to which I replied inline.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Coulson (chrisccoulson) wrote : | # |
Thanks. There's a few stylistic nits (eg, 4-space indents in some places) and some other things (eg, the constructor for OxideQFindContr
I'm going to approve this though, as I'm currently working on re-architecting oxide::WebView which is probably going to be quite disruptive to this branch - I've already created some merge conflicts with http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ugo Riboni (uriboni) wrote : | # |
> Thanks. There's a few stylistic nits (eg, 4-space indents in some places) and
> some other things (eg, the constructor for OxideQFindContr
> exported). The API looks like it's fine now.
>
> I'm going to approve this though, as I'm currently working on re-architecting
> oxide::WebView which is probably going to be quite disruptive to this branch -
> I've already created some merge conflicts with http://
> /~oxide-
Thanks Chris.
Just to be clear, is there any further action needed from me on this branch ?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chris Coulson (chrisccoulson) wrote : | # |
There isn't - I'm going to clean up the merge conflicts I've created and then merge it in for you.
Thanks!
Preview Diff
1 | === added file 'qt/core/api/oxideqfindcontroller.cc' |
2 | --- qt/core/api/oxideqfindcontroller.cc 1970-01-01 00:00:00 +0000 |
3 | +++ qt/core/api/oxideqfindcontroller.cc 2015-05-20 22:10:39 +0000 |
4 | @@ -0,0 +1,97 @@ |
5 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
6 | +// Copyright (C) 2015 Canonical Ltd. |
7 | + |
8 | +// This library is free software; you can redistribute it and/or |
9 | +// modify it under the terms of the GNU Lesser General Public |
10 | +// License as published by the Free Software Foundation; either |
11 | +// version 2.1 of the License, or (at your option) any later version. |
12 | + |
13 | +// This library is distributed in the hope that it will be useful, |
14 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | +// Lesser General Public License for more details. |
17 | + |
18 | +// You should have received a copy of the GNU Lesser General Public |
19 | +// License along with this library; if not, write to the Free Software |
20 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | + |
22 | +#include "oxideqfindcontroller.h" |
23 | +#include "oxideqfindcontroller_p.h" |
24 | + |
25 | +#include "content/browser/web_contents/web_contents_impl.h" |
26 | +#include "qt/core/browser/oxide_qt_web_view.h" |
27 | +#include "shared/browser/oxide_web_view.h" |
28 | + |
29 | +OxideQFindControllerPrivate::OxideQFindControllerPrivate(oxide::WebView* webview) : |
30 | + case_sensitive_(false), |
31 | + count_(0), |
32 | + current_(0), |
33 | + request_id_(0), |
34 | + webview_(webview) {} |
35 | + |
36 | +OxideQFindControllerPrivate::~OxideQFindControllerPrivate() {} |
37 | + |
38 | +OxideQFindController::OxideQFindController(oxide::WebView* webview) : |
39 | + QObject(nullptr), |
40 | + d_ptr(new OxideQFindControllerPrivate(webview)) { |
41 | +} |
42 | + |
43 | +OxideQFindController::~OxideQFindController() {} |
44 | + |
45 | +QString OxideQFindController::text() const { |
46 | + Q_D(const OxideQFindController); |
47 | + |
48 | + return QString::fromStdString(d->webview_->GetFindInPageText()); |
49 | +} |
50 | + |
51 | +void OxideQFindController::setText(const QString& newText) { |
52 | + Q_D(OxideQFindController); |
53 | + |
54 | + if (newText == text()) { |
55 | + return; |
56 | + } |
57 | + |
58 | + d->webview_->SetFindInPageText(newText.toStdString()); |
59 | + emit textChanged(); |
60 | +} |
61 | + |
62 | +bool OxideQFindController::caseSensitive() const { |
63 | + Q_D(const OxideQFindController); |
64 | + |
65 | + return d->webview_->GetFindInPageCaseSensitive(); |
66 | +} |
67 | + |
68 | +void OxideQFindController::setCaseSensitive(bool newCaseSensitive) { |
69 | + Q_D(OxideQFindController); |
70 | + |
71 | + if (newCaseSensitive == caseSensitive()) { |
72 | + return; |
73 | + } |
74 | + |
75 | + d->webview_->SetFindInPageCaseSensitive(newCaseSensitive); |
76 | + emit caseSensitiveChanged(); |
77 | +} |
78 | + |
79 | +int OxideQFindController::count() const { |
80 | + Q_D(const OxideQFindController); |
81 | + |
82 | + return d->webview_->GetFindInPageCount(); |
83 | +} |
84 | + |
85 | +int OxideQFindController::current() const { |
86 | + Q_D(const OxideQFindController); |
87 | + |
88 | + return d->webview_->GetFindInPageCurrent(); |
89 | +} |
90 | + |
91 | +void OxideQFindController::next() { |
92 | + Q_D(OxideQFindController); |
93 | + |
94 | + d->webview_->FindInPageNext(); |
95 | +} |
96 | + |
97 | +void OxideQFindController::previous() { |
98 | + Q_D(OxideQFindController); |
99 | + |
100 | + d->webview_->FindInPagePrevious(); |
101 | +} |
102 | |
103 | === added file 'qt/core/api/oxideqfindcontroller.h' |
104 | --- qt/core/api/oxideqfindcontroller.h 1970-01-01 00:00:00 +0000 |
105 | +++ qt/core/api/oxideqfindcontroller.h 2015-05-20 22:10:39 +0000 |
106 | @@ -0,0 +1,71 @@ |
107 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
108 | +// Copyright (C) 2015 Canonical Ltd. |
109 | + |
110 | +// This library is free software; you can redistribute it and/or |
111 | +// modify it under the terms of the GNU Lesser General Public |
112 | +// License as published by the Free Software Foundation; either |
113 | +// version 2.1 of the License, or (at your option) any later version. |
114 | + |
115 | +// This library is distributed in the hope that it will be useful, |
116 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
117 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
118 | +// Lesser General Public License for more details. |
119 | + |
120 | +// You should have received a copy of the GNU Lesser General Public |
121 | +// License along with this library; if not, write to the Free Software |
122 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
123 | + |
124 | +#ifndef OXIDE_Q_FIND_CONTROLLER |
125 | +#define OXIDE_Q_FIND_CONTROLLER |
126 | + |
127 | +#include <QObject> |
128 | +#include <QScopedPointer> |
129 | +#include <QString> |
130 | +#include <QtGlobal> |
131 | + |
132 | +class OxideQFindControllerPrivate; |
133 | + |
134 | +namespace oxide { |
135 | + class WebView; |
136 | + namespace qt { |
137 | + class WebView; |
138 | + } |
139 | +} |
140 | + |
141 | +class Q_DECL_EXPORT OxideQFindController : public QObject { |
142 | + Q_OBJECT |
143 | + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) |
144 | + Q_PROPERTY(bool caseSensitive READ caseSensitive WRITE setCaseSensitive NOTIFY caseSensitiveChanged) |
145 | + Q_PROPERTY(int count READ count NOTIFY countChanged) |
146 | + Q_PROPERTY(int current READ current NOTIFY currentChanged) |
147 | + |
148 | + Q_DECLARE_PRIVATE(OxideQFindController) |
149 | + Q_DISABLE_COPY(OxideQFindController) |
150 | + |
151 | + public: |
152 | + OxideQFindController(oxide::WebView* webview); |
153 | + ~OxideQFindController(); |
154 | + |
155 | + QString text() const; |
156 | + void setText(const QString& text); |
157 | + bool caseSensitive() const; |
158 | + void setCaseSensitive(bool caseSensitive); |
159 | + int count() const; |
160 | + int current() const; |
161 | + |
162 | + Q_INVOKABLE void next(); |
163 | + Q_INVOKABLE void previous(); |
164 | + |
165 | + Q_SIGNALS: |
166 | + void textChanged() const; |
167 | + void caseSensitiveChanged() const; |
168 | + void countChanged() const; |
169 | + void currentChanged() const; |
170 | + |
171 | + private: |
172 | + QScopedPointer<OxideQFindControllerPrivate> d_ptr; |
173 | + |
174 | + friend class oxide::qt::WebView; |
175 | +}; |
176 | + |
177 | +#endif // OXIDE_Q_FIND_CONTROLLER |
178 | |
179 | === added file 'qt/core/api/oxideqfindcontroller_p.h' |
180 | --- qt/core/api/oxideqfindcontroller_p.h 1970-01-01 00:00:00 +0000 |
181 | +++ qt/core/api/oxideqfindcontroller_p.h 2015-05-20 22:10:39 +0000 |
182 | @@ -0,0 +1,46 @@ |
183 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
184 | +// Copyright (C) 2015 Canonical Ltd. |
185 | + |
186 | +// This library is free software; you can redistribute it and/or |
187 | +// modify it under the terms of the GNU Lesser General Public |
188 | +// License as published by the Free Software Foundation; either |
189 | +// version 2.1 of the License, or (at your option) any later version. |
190 | + |
191 | +// This library is distributed in the hope that it will be useful, |
192 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
193 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
194 | +// Lesser General Public License for more details. |
195 | + |
196 | +// You should have received a copy of the GNU Lesser General Public |
197 | +// License along with this library; if not, write to the Free Software |
198 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
199 | + |
200 | +#ifndef _OXIDE_QT_CORE_API_FIND_CONTROLLER_P_H_ |
201 | +#define _OXIDE_QT_CORE_API_FIND_CONTROLLER_P_H_ |
202 | + |
203 | +#include <QtGlobal> |
204 | +#include <QString> |
205 | + |
206 | +namespace oxide { |
207 | + class WebView; |
208 | +} |
209 | + |
210 | +class OxideQFindControllerPrivate { |
211 | + public: |
212 | + virtual ~OxideQFindControllerPrivate(); |
213 | + |
214 | + private: |
215 | + OxideQFindControllerPrivate(oxide::WebView* webview); |
216 | + |
217 | + QString text_; |
218 | + bool case_sensitive_; |
219 | + int count_; |
220 | + int current_; |
221 | + int request_id_; |
222 | + oxide::WebView* webview_; |
223 | + |
224 | + friend class OxideQFindController; |
225 | +}; |
226 | + |
227 | +#endif // _OXIDE_QT_CORE_API_FIND_CONTROLLER_P_H_ |
228 | + |
229 | |
230 | === modified file 'qt/core/browser/oxide_qt_web_view.cc' |
231 | --- qt/core/browser/oxide_qt_web_view.cc 2015-05-11 21:23:12 +0000 |
232 | +++ qt/core/browser/oxide_qt_web_view.cc 2015-05-20 22:10:39 +0000 |
233 | @@ -67,6 +67,8 @@ |
234 | #include "qt/core/api/oxideqcertificateerror_p.h" |
235 | #include "qt/core/api/oxideqsecuritystatus.h" |
236 | #include "qt/core/api/oxideqsecuritystatus_p.h" |
237 | +#include "qt/core/api/oxideqfindcontroller.h" |
238 | +#include "qt/core/api/oxideqfindcontroller_p.h" |
239 | #include "qt/core/api/oxideqwebpreferences.h" |
240 | #include "qt/core/api/oxideqwebpreferences_p.h" |
241 | #include "qt/core/common/oxide_qt_screen_utils.h" |
242 | @@ -1280,6 +1282,18 @@ |
243 | Reload(); |
244 | } |
245 | |
246 | +OxideQFindController* WebView::findInPage() { |
247 | + return find_in_page_controller_.get(); |
248 | +} |
249 | + |
250 | +void WebView::OnFindInPageCountChanged() { |
251 | + Q_EMIT find_in_page_controller_->countChanged(); |
252 | +} |
253 | + |
254 | +void WebView::OnFindInPageCurrentChanged() { |
255 | + Q_EMIT find_in_page_controller_->currentChanged(); |
256 | +} |
257 | + |
258 | void WebView::loadHtml(const QString& html, const QUrl& base_url) { |
259 | QByteArray encoded_data = html.toUtf8().toPercentEncoding(); |
260 | LoadData(std::string(encoded_data.constData(), encoded_data.length()), |
261 | @@ -1511,7 +1525,8 @@ |
262 | client_(client), |
263 | has_input_method_state_(false), |
264 | qsecurity_status_( |
265 | - OxideQSecurityStatusPrivate::Create(this)) { |
266 | + OxideQSecurityStatusPrivate::Create(this)), |
267 | + find_in_page_controller_(new OxideQFindController(this)) { |
268 | QInputMethod* im = QGuiApplication::inputMethod(); |
269 | if (im) { |
270 | connect(im, SIGNAL(visibleChanged()), |
271 | |
272 | === modified file 'qt/core/browser/oxide_qt_web_view.h' |
273 | --- qt/core/browser/oxide_qt_web_view.h 2015-05-11 21:23:12 +0000 |
274 | +++ qt/core/browser/oxide_qt_web_view.h 2015-05-20 22:10:39 +0000 |
275 | @@ -41,6 +41,7 @@ |
276 | class QWheelEvent; |
277 | QT_END_NAMESPACE |
278 | |
279 | +class OxideQFindController; |
280 | class OxideQSecurityStatus; |
281 | |
282 | namespace oxide { |
283 | @@ -156,6 +157,9 @@ |
284 | const std::string& cookies, |
285 | const std::string& referrer) override; |
286 | |
287 | + void OnFindInPageCountChanged() override; |
288 | + void OnFindInPageCurrentChanged() override; |
289 | + |
290 | bool ShouldHandleNavigation(const GURL& url, |
291 | WindowOpenDisposition disposition, |
292 | bool user_gesture) override; |
293 | @@ -231,6 +235,8 @@ |
294 | void stop() override; |
295 | void reload() override; |
296 | |
297 | + OxideQFindController* findInPage() override; |
298 | + |
299 | void loadHtml(const QString& html, const QUrl& base_url) override; |
300 | |
301 | QList<ScriptMessageHandlerProxyHandle*>& messageHandlers() override; |
302 | @@ -291,6 +297,7 @@ |
303 | UITouchEventFactory touch_event_factory_; |
304 | |
305 | QSharedPointer<CompositorFrameHandle> compositor_frame_; |
306 | + scoped_ptr<OxideQFindController> find_in_page_controller_; |
307 | |
308 | DISALLOW_IMPLICIT_CONSTRUCTORS(WebView); |
309 | }; |
310 | |
311 | === modified file 'qt/core/core.gyp' |
312 | --- qt/core/core.gyp 2015-05-06 21:13:13 +0000 |
313 | +++ qt/core/core.gyp 2015-05-20 22:10:39 +0000 |
314 | @@ -201,6 +201,7 @@ |
315 | '<(INTERMEDIATE_DIR)/moc_oxideqnavigationrequest.cc', |
316 | '<(INTERMEDIATE_DIR)/moc_oxideqnewviewrequest.cc', |
317 | '<(INTERMEDIATE_DIR)/moc_oxideqpermissionrequest.cc', |
318 | + '<(INTERMEDIATE_DIR)/moc_oxideqfindcontroller.cc', |
319 | '<(INTERMEDIATE_DIR)/moc_oxideqsecuritystatus.cc', |
320 | '<(INTERMEDIATE_DIR)/moc_oxideqsslcertificate.cc', |
321 | '<(INTERMEDIATE_DIR)/moc_oxideqstoragepermissionrequest.cc', |
322 | @@ -229,6 +230,9 @@ |
323 | 'api/oxideqpermissionrequest.cc', |
324 | 'api/oxideqpermissionrequest.h', |
325 | 'api/oxideqpermissionrequest_p.h', |
326 | + 'api/oxideqfindcontroller.cc', |
327 | + 'api/oxideqfindcontroller.h', |
328 | + 'api/oxideqfindcontroller_p.h', |
329 | 'api/oxideqsecuritystatus.cc', |
330 | 'api/oxideqsecuritystatus.h', |
331 | 'api/oxideqsecuritystatus_p.h', |
332 | @@ -279,6 +283,11 @@ |
333 | 'includes': [ 'moc.gypi' ], |
334 | }, |
335 | { |
336 | + 'action_name': 'moc_oxideqfindcontroller.cc', |
337 | + 'moc_input': 'api/oxideqfindcontroller.h', |
338 | + 'includes': [ 'moc.gypi' ], |
339 | + }, |
340 | + { |
341 | 'action_name': 'moc_oxideqsecuritystatus.cc', |
342 | 'moc_input': 'api/oxideqsecuritystatus.h', |
343 | 'includes': [ 'moc.gypi' ], |
344 | |
345 | === modified file 'qt/core/glue/oxide_qt_web_view_proxy.h' |
346 | --- qt/core/glue/oxide_qt_web_view_proxy.h 2015-05-06 15:05:53 +0000 |
347 | +++ qt/core/glue/oxide_qt_web_view_proxy.h 2015-05-20 22:10:39 +0000 |
348 | @@ -45,6 +45,7 @@ |
349 | class QWheelEvent; |
350 | QT_END_NAMESPACE |
351 | |
352 | +class OxideQFindController; |
353 | class OxideQNewViewRequest; |
354 | class OxideQSecurityStatus; |
355 | class OxideQWebPreferences; |
356 | @@ -101,6 +102,14 @@ |
357 | virtual EGLImageKHR GetImageFrame() = 0; |
358 | }; |
359 | |
360 | +struct FindInPageState { |
361 | + int request_id; |
362 | + QString text; |
363 | + bool case_sensitive; |
364 | + int current; |
365 | + int count; |
366 | +}; |
367 | + |
368 | OXIDE_Q_DECL_PROXY_HANDLE(ScriptMessageHandlerProxy); |
369 | OXIDE_Q_DECL_PROXY_HANDLE(WebContextProxy); |
370 | OXIDE_Q_DECL_PROXY_HANDLE(WebFrameProxy); |
371 | @@ -155,6 +164,8 @@ |
372 | virtual void stop() = 0; |
373 | virtual void reload() = 0; |
374 | |
375 | + virtual OxideQFindController* findInPage() = 0; |
376 | + |
377 | virtual void loadHtml(const QString& html, const QUrl& base_url) = 0; |
378 | |
379 | virtual QList<ScriptMessageHandlerProxyHandle*>& messageHandlers() = 0; |
380 | |
381 | === modified file 'qt/qmlplugin/oxide_qml_plugin.cc' |
382 | --- qt/qmlplugin/oxide_qml_plugin.cc 2015-05-11 21:23:12 +0000 |
383 | +++ qt/qmlplugin/oxide_qml_plugin.cc 2015-05-20 22:10:39 +0000 |
384 | @@ -24,6 +24,7 @@ |
385 | |
386 | #include "qt/core/api/oxideqcertificateerror.h" |
387 | #include "qt/core/api/oxideqdownloadrequest.h" |
388 | +#include "qt/core/api/oxideqfindcontroller.h" |
389 | #include "qt/core/api/oxideqloadevent.h" |
390 | #include "qt/core/api/oxideqnavigationrequest.h" |
391 | #include "qt/core/api/oxideqnewviewrequest.h" |
392 | @@ -128,8 +129,12 @@ |
393 | qmlRegisterUncreatableType<OxideQQuickLocationBarController, 1>(uri, 1, 7, "LocationBarController", |
394 | "LocationBarController is accessed via WebView.locationBarController"); |
395 | |
396 | + qmlRegisterUncreatableType<OxideQFindController>(uri, 1, 8, "FindController", |
397 | + "FindInPage is accessed via WebView.findController"); |
398 | + |
399 | qmlRegisterUncreatableType<OxideQLoadEvent, 2>(uri, 1, 8, "LoadEvent", |
400 | "LoadEvent is delivered by WebView.loadEvent"); |
401 | + |
402 | qmlRegisterType<OxideQQuickWebView, 4>(uri, 1, 8, "WebView"); |
403 | } |
404 | }; |
405 | |
406 | === modified file 'qt/quick/api/oxideqquickwebview.cc' |
407 | --- qt/quick/api/oxideqquickwebview.cc 2015-05-11 15:32:11 +0000 |
408 | +++ qt/quick/api/oxideqquickwebview.cc 2015-05-20 22:10:39 +0000 |
409 | @@ -41,6 +41,7 @@ |
410 | #include <Qt> |
411 | |
412 | #include "qt/core/api/oxideqcertificateerror.h" |
413 | +#include "qt/core/api/oxideqfindcontroller.h" |
414 | #include "qt/core/api/oxideqglobal.h" |
415 | #include "qt/core/api/oxideqloadevent.h" |
416 | #include "qt/core/api/oxideqnewviewrequest.h" |
417 | @@ -1744,4 +1745,10 @@ |
418 | d->proxy()->prepareToClose(); |
419 | } |
420 | |
421 | +OxideQFindController* OxideQQuickWebView::findController() const { |
422 | + Q_D(const OxideQQuickWebView); |
423 | + |
424 | + return d->proxy()->findInPage(); |
425 | +} |
426 | + |
427 | #include "moc_oxideqquickwebview_p.cpp" |
428 | |
429 | === modified file 'qt/quick/api/oxideqquickwebview_p.h' |
430 | --- qt/quick/api/oxideqquickwebview_p.h 2015-05-11 15:32:11 +0000 |
431 | +++ qt/quick/api/oxideqquickwebview_p.h 2015-05-20 22:10:39 +0000 |
432 | @@ -32,6 +32,7 @@ |
433 | |
434 | QT_USE_NAMESPACE |
435 | |
436 | +class OxideQFindController; |
437 | class OxideQLoadEvent; |
438 | class OxideQNavigationRequest; |
439 | class OxideQNewViewRequest; |
440 | @@ -45,6 +46,11 @@ |
441 | class OxideQQuickWebViewPrivate; |
442 | class OxideQDownloadRequest; |
443 | class OxideQSecurityStatus; |
444 | +namespace oxide { |
445 | + namespace qt { |
446 | + class WebViewProxy; |
447 | + } |
448 | +} |
449 | |
450 | class OxideQQuickWebViewAttached : public QObject { |
451 | Q_OBJECT |
452 | @@ -107,6 +113,8 @@ |
453 | |
454 | Q_PROPERTY(OxideQNewViewRequest* request READ request WRITE setRequest) |
455 | |
456 | + Q_PROPERTY(OxideQFindController* findController READ findController CONSTANT REVISION 4) |
457 | + |
458 | // Set at construction time only |
459 | Q_PROPERTY(QString restoreState READ restoreState WRITE setRestoreState REVISION 2) |
460 | Q_PROPERTY(RestoreType restoreType READ restoreType WRITE setRestoreType REVISION 2) |
461 | @@ -234,6 +242,8 @@ |
462 | |
463 | static OxideQQuickWebViewAttached* qmlAttachedProperties(QObject* object); |
464 | |
465 | + OxideQFindController* findController() const; |
466 | + |
467 | public Q_SLOTS: |
468 | void goBack(); |
469 | void goForward(); |
470 | |
471 | === added file 'qt/tests/qmltests/api/tst_WebView_findController.html' |
472 | --- qt/tests/qmltests/api/tst_WebView_findController.html 1970-01-01 00:00:00 +0000 |
473 | +++ qt/tests/qmltests/api/tst_WebView_findController.html 2015-05-20 22:10:39 +0000 |
474 | @@ -0,0 +1,13 @@ |
475 | +<html> |
476 | + <head> |
477 | + <meta charset="UTF-8"> |
478 | + </head> |
479 | + <body> |
480 | + Lorem ipsum dolor sit Amet, consectetur adipiscing elit. |
481 | + Nam eu venenatis velit. |
482 | + Suspendisse vitae libero rutrum Amet, congue velit quis, fringilla eros. |
483 | + Nulla at semper purus, id scelerisque est. |
484 | + Fusce rhoncus placerat erat ñec ultricies amet. |
485 | + Curabitur mauris. Dolor, facilisis eu tellus vitae, semper iaculis tortor. |
486 | + </body> |
487 | +</html> |
488 | |
489 | === added file 'qt/tests/qmltests/api/tst_WebView_findController.qml' |
490 | --- qt/tests/qmltests/api/tst_WebView_findController.qml 1970-01-01 00:00:00 +0000 |
491 | +++ qt/tests/qmltests/api/tst_WebView_findController.qml 2015-05-20 22:10:39 +0000 |
492 | @@ -0,0 +1,152 @@ |
493 | +import QtQuick 2.0 |
494 | +import QtTest 1.0 |
495 | +import com.canonical.Oxide 1.8 |
496 | +import com.canonical.Oxide.Testing 1.0 |
497 | + |
498 | +TestWebView { |
499 | + id: webView |
500 | + focus: true |
501 | + width: 200 |
502 | + height: 200 |
503 | + |
504 | + TestCase { |
505 | + name: "findController" |
506 | + when: windowShown |
507 | + |
508 | + function init() { |
509 | + webView.findController.text = ""; |
510 | + webView.findController.caseSensitive = false; |
511 | + |
512 | + // load the page that will be used by most tests |
513 | + webView.url = "http://testsuite/tst_WebView_findController.html"; |
514 | + verify(webView.waitForLoadSucceeded(), |
515 | + "Timed out waiting for successful load"); |
516 | + } |
517 | + |
518 | + function test_case_insensitive() { |
519 | + webView.findController.text = "suspendisse"; |
520 | + tryCompare(webView.findController, "count", 1); |
521 | + |
522 | + webView.findController.text = "aMet"; |
523 | + tryCompare(webView.findController, "count", 3); |
524 | + } |
525 | + |
526 | + function test_case_sensitive() { |
527 | + webView.findController.caseSensitive = true; |
528 | + |
529 | + webView.findController.text = "Suspendisse"; |
530 | + tryCompare(webView.findController, "count", 1); |
531 | + |
532 | + webView.findController.text = "suspendisse"; |
533 | + tryCompare(webView.findController, "count", 0); |
534 | + } |
535 | + |
536 | + function test_change_case_sensitivity() { |
537 | + webView.findController.caseSensitive = true; |
538 | + |
539 | + webView.findController.text = "Dolor"; |
540 | + tryCompare(webView.findController, "count", 1); |
541 | + |
542 | + webView.findController.caseSensitive = false; |
543 | + tryCompare(webView.findController, "count", 2); |
544 | + } |
545 | + |
546 | + function test_movement() { |
547 | + webView.findController.text = "dolor"; |
548 | + tryCompare(webView.findController, "count", 2); |
549 | + tryCompare(webView.findController, "current", 1); |
550 | + |
551 | + webView.findController.next(); |
552 | + tryCompare(webView.findController, "count", 2); |
553 | + tryCompare(webView.findController, "current", 2); |
554 | + |
555 | + webView.findController.previous(); |
556 | + tryCompare(webView.findController, "count", 2); |
557 | + tryCompare(webView.findController, "current", 1); |
558 | + } |
559 | + |
560 | + function test_movement_wraps() { |
561 | + webView.findController.text = "dolor"; |
562 | + tryCompare(webView.findController, "count", 2); |
563 | + tryCompare(webView.findController, "current", 1); |
564 | + |
565 | + webView.findController.next(); |
566 | + webView.findController.next(); |
567 | + tryCompare(webView.findController, "current", 1); |
568 | + |
569 | + webView.findController.previous(); |
570 | + webView.findController.previous(); |
571 | + tryCompare(webView.findController, "current", 1); |
572 | + } |
573 | + |
574 | + function test_clear() { |
575 | + webView.findController.text = "dolor"; |
576 | + tryCompare(webView.findController, "count", 2); |
577 | + |
578 | + webView.findController.text = ""; |
579 | + tryCompare(webView.findController, "count", 0); |
580 | + tryCompare(webView.findController, "current", 0); |
581 | + } |
582 | + |
583 | + function test_new_text_resets_count() { |
584 | + webView.findController.text = "dolor"; |
585 | + tryCompare(webView.findController, "count", 2); |
586 | + webView.findController.next(); |
587 | + tryCompare(webView.findController, "current", 2); |
588 | + |
589 | + webView.findController.text = "suspendisse"; |
590 | + tryCompare(webView.findController, "count", 1); |
591 | + tryCompare(webView.findController, "current", 1); |
592 | + } |
593 | + |
594 | + function test_not_found_resets_count() { |
595 | + webView.findController.text = "dolor"; |
596 | + tryCompare(webView.findController, "count", 2); |
597 | + |
598 | + webView.findController.text = "i_am_not_there"; |
599 | + tryCompare(webView.findController, "count", 0); |
600 | + tryCompare(webView.findController, "current", 0); |
601 | + } |
602 | + |
603 | + function test_find_non_latin() { |
604 | + webView.findController.text = "ñec"; |
605 | + tryCompare(webView.findController, "count", 1); |
606 | + } |
607 | + |
608 | + function test_find_on_invalid_page() { |
609 | + webView.url = "http://testsuite/tst_invalid_page.html"; |
610 | + // verify successful load because the server returns a 404 page apparently |
611 | + // and that does not count as a failure |
612 | + verify(webView.waitForLoadSucceeded(), |
613 | + "Timed out waiting for successful load"); |
614 | + |
615 | + webView.findController.text = "hello"; |
616 | + tryCompare(webView.findController, "count", 0); |
617 | + tryCompare(webView.findController, "current", 0); |
618 | + } |
619 | + |
620 | + function test_navigation_does_not_reset() { |
621 | + webView.findController.text = "dolor"; |
622 | + tryCompare(webView.findController, "count", 2); |
623 | + webView.findController.next(); |
624 | + tryCompare(webView.findController, "current", 2); |
625 | + |
626 | + // Verify that when navigating to another page the search does not |
627 | + // reset, it is the user responsibility to cancel it and restart it |
628 | + webView.url = "http://testsuite/tst_WebView_findControllerManyResults.html"; |
629 | + verify(webView.waitForLoadSucceeded(), |
630 | + "Timed out waiting for successful load"); |
631 | + compare(webView.findController.text, "dolor"); |
632 | + tryCompare(webView.findController, "count", 2); |
633 | + tryCompare(webView.findController, "current", 2); |
634 | + |
635 | + webView.findController.text = ""; |
636 | + tryCompare(webView.findController, "count", 0); |
637 | + tryCompare(webView.findController, "current", 0); |
638 | + |
639 | + webView.findController.text = "dolor"; |
640 | + tryCompare(webView.findController, "count", 20); |
641 | + tryCompare(webView.findController, "current", 1); |
642 | + } |
643 | + } |
644 | +} |
645 | |
646 | === added file 'qt/tests/qmltests/api/tst_WebView_findControllerManyResults.html' |
647 | --- qt/tests/qmltests/api/tst_WebView_findControllerManyResults.html 1970-01-01 00:00:00 +0000 |
648 | +++ qt/tests/qmltests/api/tst_WebView_findControllerManyResults.html 2015-05-20 22:10:39 +0000 |
649 | @@ -0,0 +1,9 @@ |
650 | +<html> |
651 | + <head> |
652 | + <meta charset="UTF-8"> |
653 | + </head> |
654 | + <body> |
655 | + Lorem ipsum dolor dolor dolor dolor dolor dolor dolor dolor dolor dolor |
656 | + dolor dolor dolor dolor dolor dolor dolor dolor dolor dolor sit amet. |
657 | + </body> |
658 | +</html> |
659 | |
660 | === modified file 'shared/browser/oxide_web_view.cc' |
661 | --- shared/browser/oxide_web_view.cc 2015-05-15 14:49:32 +0000 |
662 | +++ shared/browser/oxide_web_view.cc 2015-05-20 22:10:39 +0000 |
663 | @@ -76,6 +76,8 @@ |
664 | #include "shared/common/oxide_event_utils.h" |
665 | #include "shared/common/oxide_messages.h" |
666 | |
667 | +#include "third_party/WebKit/public/web/WebFindOptions.h" |
668 | + |
669 | #include "oxide_browser_context.h" |
670 | #include "oxide_browser_process_main.h" |
671 | #include "oxide_content_browser_client.h" |
672 | @@ -753,6 +755,25 @@ |
673 | return IsFullscreen(); |
674 | } |
675 | |
676 | +void WebView::FindReply(content::WebContents* web_contents, |
677 | + int request_id, |
678 | + int number_of_matches, |
679 | + const gfx::Rect& selection_rect, |
680 | + int active_match_ordinal, |
681 | + bool final_update) { |
682 | + if (active_match_ordinal != -1 && |
683 | + find_in_page_.current != active_match_ordinal) { |
684 | + find_in_page_.current = active_match_ordinal; |
685 | + OnFindInPageCurrentChanged(); |
686 | + } |
687 | + |
688 | + if (number_of_matches != -1 && |
689 | + find_in_page_.count != number_of_matches) { |
690 | + find_in_page_.count = number_of_matches; |
691 | + OnFindInPageCountChanged(); |
692 | + } |
693 | +} |
694 | + |
695 | void WebView::RequestMediaAccessPermission( |
696 | content::WebContents* source, |
697 | const content::MediaStreamRequest& request, |
698 | @@ -1222,6 +1243,9 @@ |
699 | void WebView::OnPrepareToCloseResponse(bool proceed) {} |
700 | void WebView::OnCloseRequested() {} |
701 | |
702 | +void WebView::OnFindInPageCountChanged() {} |
703 | +void WebView::OnFindInPageCurrentChanged() {} |
704 | + |
705 | WebView::WebView() |
706 | : text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
707 | show_ime_if_needed_(false), |
708 | @@ -1636,6 +1660,84 @@ |
709 | rvh->OnWebkitPreferencesChanged(); |
710 | } |
711 | |
712 | +int WebView::GetFindInPageCount() const { |
713 | + return find_in_page_.count; |
714 | +} |
715 | + |
716 | +int WebView::GetFindInPageCurrent() const { |
717 | + return find_in_page_.current; |
718 | +} |
719 | + |
720 | +std::string WebView::GetFindInPageText() const { |
721 | + return find_in_page_.text; |
722 | +} |
723 | + |
724 | +bool WebView::GetFindInPageCaseSensitive() const { |
725 | + return find_in_page_.case_sensitive; |
726 | +} |
727 | + |
728 | +void WebView::SetFindInPageText(const std::string& text) { |
729 | + find_in_page_.text = text; |
730 | + RestartFindInPage(); |
731 | +} |
732 | + |
733 | +void WebView::SetFindInPageCaseSensitive(bool case_sensitive) { |
734 | + find_in_page_.case_sensitive = case_sensitive; |
735 | + RestartFindInPage(); |
736 | +} |
737 | + |
738 | +void WebView::RestartFindInPage() { |
739 | + if (!web_contents_) { |
740 | + return; |
741 | + } |
742 | + |
743 | + web_contents_->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION); |
744 | + |
745 | + find_in_page_.current = 0; |
746 | + OnFindInPageCurrentChanged(); |
747 | + find_in_page_.count = 0; |
748 | + OnFindInPageCountChanged(); |
749 | + |
750 | + if (!find_in_page_.text.empty()) { |
751 | + find_in_page_.request_id++; |
752 | + |
753 | + blink::WebFindOptions options; |
754 | + options.forward = true; |
755 | + options.findNext = false; |
756 | + options.matchCase = find_in_page_.case_sensitive; |
757 | + |
758 | + web_contents_->Find(find_in_page_.request_id, |
759 | + base::UTF8ToUTF16(find_in_page_.text), |
760 | + options); |
761 | + } |
762 | +} |
763 | + |
764 | +void WebView::FindInPageNext() { |
765 | + if (!web_contents_) { |
766 | + return; |
767 | + } |
768 | + |
769 | + blink::WebFindOptions options; |
770 | + options.forward = true; |
771 | + options.findNext = true; |
772 | + |
773 | + web_contents_->Find(find_in_page_.request_id, |
774 | + base::UTF8ToUTF16(find_in_page_.text), options); |
775 | +} |
776 | + |
777 | +void WebView::FindInPagePrevious() { |
778 | + if (!web_contents_) { |
779 | + return; |
780 | + } |
781 | + |
782 | + blink::WebFindOptions options; |
783 | + options.forward = false; |
784 | + options.findNext = true; |
785 | + |
786 | + web_contents_->Find(find_in_page_.request_id, |
787 | + base::UTF8ToUTF16(find_in_page_.text), options); |
788 | +} |
789 | + |
790 | BrowserContext* WebView::GetBrowserContext() const { |
791 | return BrowserContext::FromContent(web_contents_->GetBrowserContext()); |
792 | } |
793 | |
794 | === modified file 'shared/browser/oxide_web_view.h' |
795 | --- shared/browser/oxide_web_view.h 2015-05-15 14:49:32 +0000 |
796 | +++ shared/browser/oxide_web_view.h 2015-05-20 22:10:39 +0000 |
797 | @@ -201,6 +201,15 @@ |
798 | void InputPanelVisibilityChanged(); |
799 | void UpdateWebPreferences(); |
800 | |
801 | + int GetFindInPageCount() const; |
802 | + int GetFindInPageCurrent() const; |
803 | + std::string GetFindInPageText() const; |
804 | + void SetFindInPageText(const std::string& text); |
805 | + bool GetFindInPageCaseSensitive() const; |
806 | + void SetFindInPageCaseSensitive(bool case_sensitive); |
807 | + void FindInPageNext(); |
808 | + void FindInPagePrevious(); |
809 | + |
810 | BrowserContext* GetBrowserContext() const; |
811 | content::WebContents* GetWebContents() const; |
812 | |
813 | @@ -355,6 +364,8 @@ |
814 | void InitializeTopControlsForHost(content::RenderViewHost* rvh, |
815 | bool initial_host); |
816 | |
817 | + void RestartFindInPage(); |
818 | + |
819 | // ScriptMessageTarget implementation |
820 | virtual size_t GetScriptMessageHandlerCount() const override; |
821 | virtual const ScriptMessageHandler* GetScriptMessageHandlerAt( |
822 | @@ -440,6 +451,13 @@ |
823 | const content::MediaStreamRequest& request, |
824 | const content::MediaResponseCallback& callback) final; |
825 | |
826 | + void FindReply(content::WebContents* web_contents, |
827 | + int request_id, |
828 | + int number_of_matches, |
829 | + const gfx::Rect& selection_rect, |
830 | + int active_match_ordinal, |
831 | + bool final_update) final; |
832 | + |
833 | // content::WebContentsObserver implementation |
834 | void RenderFrameCreated(content::RenderFrameHost* render_frame_host) final; |
835 | void RenderViewReady() final; |
836 | @@ -577,6 +595,9 @@ |
837 | virtual void OnPrepareToCloseResponse(bool proceed); |
838 | virtual void OnCloseRequested(); |
839 | |
840 | + virtual void OnFindInPageCurrentChanged(); |
841 | + virtual void OnFindInPageCountChanged(); |
842 | + |
843 | struct WebContentsDeleter { |
844 | void operator()(content::WebContents* contents); |
845 | }; |
846 | @@ -623,6 +644,17 @@ |
847 | |
848 | SecurityStatus security_status_; |
849 | |
850 | + struct FindInPageState { |
851 | + int request_id; |
852 | + int current; |
853 | + int count; |
854 | + bool case_sensitive; |
855 | + std::string text; |
856 | + FindInPageState() : request_id(0), current(0), count(0), |
857 | + case_sensitive(false) {} |
858 | + }; |
859 | + FindInPageState find_in_page_; |
860 | + |
861 | int location_bar_height_pix_; |
862 | blink::WebTopControlsState location_bar_constraints_; |
863 | bool location_bar_animated_; |
The API looks good to me (I’ll let Chris comment on the actual implementation). Here are a few comments, most of them on the unit tests:
- In test_case_ insensitive( ), the second test should be on a different string, otherwise the count might not have been updated yet.
- In test_new_ text_resets_ count() and in test_navigation _does_not_ reset() , next() should be called after verifying that the count is 2.
- In test_find_ on_invalid_ page(), waiting for a successful load doesn’t look right. Shouldn’t you use webView. waitForLoadFail ed() ?
- In test_navigation _does_not_ reset() , the comparison of text to "dolor" doesn’t need a tryCompare(), it should be a simple compare().
- In OxideQQuickWebV iewFindInPage’ s constructor, the explicit initialization of text_ is useless.
- In the implementation of WebView: :findInPage( ) and other methods, please avoid the use of a return statement on the same line as the condition, and always use curly braces, even for one-liner if blocks.