Merge lp:~osomon/oxide/navigation-api into lp:~oxide-developers/oxide/oxide.trunk
- navigation-api
- Merge into oxide.trunk
Status: | Merged |
---|---|
Merged at revision: | 294 |
Proposed branch: | lp:~osomon/oxide/navigation-api |
Merge into: | lp:~oxide-developers/oxide/oxide.trunk |
Diff against target: |
1014 lines (+672/-3) 19 files modified
qt/core/glue/oxide_qt_web_view_adapter.cc (+28/-0) qt/core/glue/oxide_qt_web_view_adapter.h (+13/-0) qt/core/glue/private/oxide_qt_web_view_adapter_p.cc (+12/-0) qt/core/glue/private/oxide_qt_web_view_adapter_p.h (+4/-0) qt/quick/api/oxideqquicknavigationhistory.cc (+202/-0) qt/quick/api/oxideqquicknavigationhistory_p.h (+67/-0) qt/quick/api/oxideqquicknavigationhistory_p_p.h (+44/-0) qt/quick/api/oxideqquickwebview.cc (+19/-0) qt/quick/api/oxideqquickwebview_p.h (+5/-0) qt/quick/api/oxideqquickwebview_p_p.h (+7/-0) qt/quick/oxide_qml_plugin.cc (+3/-0) qt/quick/qmlplugin.pro (+3/-0) qt/tests/qmltests/data/tst_WebView_navigation1.html (+3/-0) qt/tests/qmltests/data/tst_WebView_navigation2.html (+3/-0) qt/tests/qmltests/data/tst_WebView_navigation3.html (+4/-1) qt/tests/qmltests/data/tst_WebView_navigation4.html (+3/-0) qt/tests/qmltests/data/tst_WebView_navigationHistory.qml (+116/-0) shared/browser/oxide_web_view.cc (+110/-2) shared/browser/oxide_web_view.h (+26/-0) |
To merge this branch: | bzr merge lp:~osomon/oxide/navigation-api |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Coulson | Approve | ||
Review via email: mp+196704@code.launchpad.net |
Commit message
Implement a navigation API for the QML WebView.
Description of the change
- 265. By Olivier Tilloy
-
Leave out virtualUrl and titleForDisplay for now, we don’t need them.
- 266. By Olivier Tilloy
-
#include re-ordering to be more consistent with the style of the existing code.
- 267. By Olivier Tilloy
-
Remove the unneeded "adapter" parameter.
- 268. By Olivier Tilloy
-
Issue a warning when trying to set the current index to an invalid value, and add corresponding tests.
- 269. By Olivier Tilloy
-
Add a bounds check for index.
- 270. By Olivier Tilloy
-
Remove trailing underscores from public members’ names.
- 271. By Olivier Tilloy
-
Move code that is not Qt-specific from qt/core/
glue/private to shared/. - 272. By Olivier Tilloy
-
Embed OxideQQuickNavi
gationHistory in the address space of OxideQQuickWebV iewPrivate. - 273. By Olivier Tilloy
-
Clear the entry cache when resetting the model.
Olivier Tilloy (osomon) wrote : | # |
All remarks/suggestions addressed, but for this one:
> Does this work as expected when NavigationContr
> For example, if there is a new navigation entry but
> NavigationContr
> being out of date?
Not sure whether such a hypothetical case can ever happen, but if it did then as you point out the model would end up outdated.
In fact, onNavigationHis
Does that make sense?
- 274. By Olivier Tilloy
-
Emit fine-grained notifications on oxide::WebView when the navigation history changes.
- 275. By Olivier Tilloy
-
Actually register to notifications.
- 276. By Olivier Tilloy
-
Hook to the navigation notifications on the Qt side.
- 277. By Olivier Tilloy
-
Update the navigation history model when notified that it changed.
- 278. By Olivier Tilloy
-
Discard notifications coming from other navigation controllers.
- 279. By Olivier Tilloy
-
Fix property type.
- 280. By Olivier Tilloy
-
Use tryCompare because the title is changed asynchronously.
- 281. By Olivier Tilloy
-
Implement WebContentsObse
rver::TitleWasS et to react to immediate title changes that are not notified otherwise.
Olivier Tilloy (osomon) wrote : | # |
I just fixed the last remaining issue, this is now ready for review.
- 282. By Olivier Tilloy
-
Merge the latest changes from trunk.
- 283. By Olivier Tilloy
-
Instantiate the NotificationReg
istrar only when initializing the WebView.
Olivier Tilloy (osomon) wrote : | # |
Fixed to work with the latest trunk.
Chris Coulson (chrisccoulson) wrote : | # |
This looks mostly ok now, but I don't understand why you made the change in r283 :)
Olivier Tilloy (osomon) wrote : | # |
> This looks mostly ok now, but I don't understand why you made the change in
> r283 :)
After merging the latest changes from trunk (at revision 282), this code was consistently crashing at startup, because the registrar was instantiated at construction time, before the WebContents was assigned.
Chris Coulson (chrisccoulson) wrote : | # |
Ok, that's fine. This is a result of http://
Could you please change it to use a scoped_ptr though? Once that's done, feel free to merge it in. Thanks!
- 284. By Olivier Tilloy
-
Use a scoped_ptr instead of a plain pointer.
Olivier Tilloy (osomon) wrote : | # |
> Could you please change it to use a scoped_ptr though?
> Once that's done, feel free to merge it in. Thanks!
Done, and merged. Thanks for the review!
Preview Diff
1 | === modified file 'qt/core/glue/oxide_qt_web_view_adapter.cc' |
2 | --- qt/core/glue/oxide_qt_web_view_adapter.cc 2013-12-12 22:54:44 +0000 |
3 | +++ qt/core/glue/oxide_qt_web_view_adapter.cc 2014-01-07 14:38:44 +0000 |
4 | @@ -126,5 +126,33 @@ |
5 | return priv->web_contents() != NULL; |
6 | } |
7 | |
8 | +int WebViewAdapter::getNavigationEntryCount() const { |
9 | + return priv->GetNavigationEntryCount(); |
10 | +} |
11 | + |
12 | +int WebViewAdapter::getNavigationCurrentEntryIndex() const { |
13 | + return priv->GetNavigationCurrentEntryIndex(); |
14 | +} |
15 | + |
16 | +void WebViewAdapter::setNavigationCurrentEntryIndex(int index) { |
17 | + priv->SetNavigationCurrentEntryIndex(index); |
18 | +} |
19 | + |
20 | +int WebViewAdapter::getNavigationEntryUniqueID(int index) const { |
21 | + return priv->GetNavigationEntryUniqueID(index); |
22 | +} |
23 | + |
24 | +QUrl WebViewAdapter::getNavigationEntryUrl(int index) const { |
25 | + return QUrl(QString::fromStdString(priv->GetNavigationEntryUrl(index).spec())); |
26 | +} |
27 | + |
28 | +QString WebViewAdapter::getNavigationEntryTitle(int index) const { |
29 | + return QString::fromStdString(priv->GetNavigationEntryTitle(index)); |
30 | +} |
31 | + |
32 | +QDateTime WebViewAdapter::getNavigationEntryTimestamp(int index) const { |
33 | + return QDateTime::fromMSecsSinceEpoch(priv->GetNavigationEntryTimestamp(index).ToJsTime()); |
34 | +} |
35 | + |
36 | } // namespace qt |
37 | } // namespace oxide |
38 | |
39 | === modified file 'qt/core/glue/oxide_qt_web_view_adapter.h' |
40 | --- qt/core/glue/oxide_qt_web_view_adapter.h 2013-12-16 12:18:07 +0000 |
41 | +++ qt/core/glue/oxide_qt_web_view_adapter.h 2014-01-07 14:38:44 +0000 |
42 | @@ -18,6 +18,7 @@ |
43 | #ifndef _OXIDE_QT_CORE_GLUE_WEB_VIEW_ADAPTER_H_ |
44 | #define _OXIDE_QT_CORE_GLUE_WEB_VIEW_ADAPTER_H_ |
45 | |
46 | +#include <QDateTime> |
47 | #include <QList> |
48 | #include <QRect> |
49 | #include <QScopedPointer> |
50 | @@ -95,6 +96,10 @@ |
51 | const QString& error_description) = 0; |
52 | virtual void LoadSucceeded(const QUrl& url) = 0; |
53 | |
54 | + virtual void NavigationEntryCommitted() = 0; |
55 | + virtual void NavigationListPruned(bool from_front, int count) = 0; |
56 | + virtual void NavigationEntryChanged(int index) = 0; |
57 | + |
58 | virtual WebFrameAdapter* CreateWebFrame() = 0; |
59 | |
60 | virtual QRect GetContainerBounds() = 0; |
61 | @@ -103,6 +108,14 @@ |
62 | |
63 | bool isInitialized(); |
64 | |
65 | + int getNavigationEntryCount() const; |
66 | + int getNavigationCurrentEntryIndex() const; |
67 | + void setNavigationCurrentEntryIndex(int index); |
68 | + int getNavigationEntryUniqueID(int index) const; |
69 | + QUrl getNavigationEntryUrl(int index) const; |
70 | + QString getNavigationEntryTitle(int index) const; |
71 | + QDateTime getNavigationEntryTimestamp(int index) const; |
72 | + |
73 | protected: |
74 | WebViewAdapter(); |
75 | |
76 | |
77 | === modified file 'qt/core/glue/private/oxide_qt_web_view_adapter_p.cc' |
78 | --- qt/core/glue/private/oxide_qt_web_view_adapter_p.cc 2013-12-16 12:18:07 +0000 |
79 | +++ qt/core/glue/private/oxide_qt_web_view_adapter_p.cc 2014-01-07 14:38:44 +0000 |
80 | @@ -77,6 +77,18 @@ |
81 | a->LoadSucceeded(QUrl(QString::fromStdString(validated_url.spec()))); |
82 | } |
83 | |
84 | +void WebViewAdapterPrivate::OnNavigationEntryCommitted() { |
85 | + a->NavigationEntryCommitted(); |
86 | +} |
87 | + |
88 | +void WebViewAdapterPrivate::OnNavigationListPruned(bool from_front, int count) { |
89 | + a->NavigationListPruned(from_front, count); |
90 | +} |
91 | + |
92 | +void WebViewAdapterPrivate::OnNavigationEntryChanged(int index) { |
93 | + a->NavigationEntryChanged(index); |
94 | +} |
95 | + |
96 | oxide::WebFrame* WebViewAdapterPrivate::CreateWebFrame() { |
97 | return new WebFrame(a->CreateWebFrame()); |
98 | } |
99 | |
100 | === modified file 'qt/core/glue/private/oxide_qt_web_view_adapter_p.h' |
101 | --- qt/core/glue/private/oxide_qt_web_view_adapter_p.h 2013-12-16 12:18:07 +0000 |
102 | +++ qt/core/glue/private/oxide_qt_web_view_adapter_p.h 2014-01-07 14:38:44 +0000 |
103 | @@ -61,6 +61,10 @@ |
104 | const std::string& error_description) FINAL; |
105 | void OnLoadSucceeded(const GURL& validated_url) FINAL; |
106 | |
107 | + void OnNavigationEntryCommitted() FINAL; |
108 | + void OnNavigationListPruned(bool from_front, int count) FINAL; |
109 | + void OnNavigationEntryChanged(int index) FINAL; |
110 | + |
111 | oxide::WebFrame* CreateWebFrame() FINAL; |
112 | |
113 | WebViewAdapter* a; |
114 | |
115 | === added file 'qt/quick/api/oxideqquicknavigationhistory.cc' |
116 | --- qt/quick/api/oxideqquicknavigationhistory.cc 1970-01-01 00:00:00 +0000 |
117 | +++ qt/quick/api/oxideqquicknavigationhistory.cc 2014-01-07 14:38:44 +0000 |
118 | @@ -0,0 +1,202 @@ |
119 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
120 | +// Copyright (C) 2013 Canonical Ltd. |
121 | + |
122 | +// This library is free software; you can redistribute it and/or |
123 | +// modify it under the terms of the GNU Lesser General Public |
124 | +// License as published by the Free Software Foundation; either |
125 | +// version 2.1 of the License, or (at your option) any later version. |
126 | + |
127 | +// This library is distributed in the hope that it will be useful, |
128 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
129 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
130 | +// Lesser General Public License for more details. |
131 | + |
132 | +// You should have received a copy of the GNU Lesser General Public |
133 | +// License along with this library; if not, write to the Free Software |
134 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
135 | + |
136 | +#include "oxideqquicknavigationhistory_p.h" |
137 | +#include "oxideqquicknavigationhistory_p_p.h" |
138 | + |
139 | +#include <QDateTime> |
140 | +#include <QDebug> |
141 | +#include <QSet> |
142 | +#include <QString> |
143 | +#include <QtAlgorithms> |
144 | +#include <QUrl> |
145 | + |
146 | +#include "oxideqquickwebview_p.h" |
147 | +#include "oxideqquickwebview_p_p.h" |
148 | + |
149 | +struct NavigationEntry { |
150 | + QUrl url; |
151 | + QString title; |
152 | + QDateTime timestamp; |
153 | +}; |
154 | + |
155 | +OxideQQuickNavigationHistory::OxideQQuickNavigationHistory( |
156 | + OxideQQuickWebView* webview) : |
157 | + QAbstractListModel(webview), |
158 | + d_ptr(new OxideQQuickNavigationHistoryPrivate) { |
159 | + Q_D(OxideQQuickNavigationHistory); |
160 | + d->q_ptr = this; |
161 | + d->webview = webview; |
162 | + d->entry_count = 0; |
163 | + d->current_index = -1; |
164 | +} |
165 | + |
166 | +OxideQQuickNavigationHistory::~OxideQQuickNavigationHistory() { |
167 | + Q_D(OxideQQuickNavigationHistory); |
168 | + qDeleteAll(d->entry_cache); |
169 | + d->entry_cache.clear(); |
170 | +} |
171 | + |
172 | +void OxideQQuickNavigationHistory::onNavigationEntryCommitted() { |
173 | + Q_D(OxideQQuickNavigationHistory); |
174 | + |
175 | + OxideQQuickWebViewPrivate* adapter = OxideQQuickWebViewPrivate::get(d->webview); |
176 | + int newCount = adapter->getNavigationEntryCount(); |
177 | + int index = adapter->getNavigationCurrentEntryIndex(); |
178 | + if (newCount > d->entry_count) { |
179 | + beginInsertRows(QModelIndex(), index, index); |
180 | + d->entry_count = newCount; |
181 | + int id = adapter->getNavigationEntryUniqueID(index); |
182 | + if (!d->entry_cache.contains(id)) { |
183 | + NavigationEntry* entry = new NavigationEntry; |
184 | + d->entry_cache.insert(id, entry); |
185 | + entry->url = adapter->getNavigationEntryUrl(index); |
186 | + entry->title = adapter->getNavigationEntryTitle(index); |
187 | + entry->timestamp = adapter->getNavigationEntryTimestamp(index); |
188 | + } |
189 | + endInsertRows(); |
190 | + } |
191 | + |
192 | + if (index != d->current_index) { |
193 | + d->current_index = index; |
194 | + Q_EMIT currentIndexChanged(); |
195 | + } |
196 | +} |
197 | + |
198 | +void OxideQQuickNavigationHistory::onNavigationListPruned(bool from_front, int count) { |
199 | + Q_D(OxideQQuickNavigationHistory); |
200 | + |
201 | + int first; |
202 | + if (from_front) { |
203 | + first = 0; |
204 | + } else { |
205 | + first = d->entry_count - count; |
206 | + } |
207 | + int last = first + count - 1; |
208 | + beginRemoveRows(QModelIndex(), first, last); |
209 | + d->entry_count -= count; |
210 | + endRemoveRows(); |
211 | + |
212 | + OxideQQuickWebViewPrivate* adapter = OxideQQuickWebViewPrivate::get(d->webview); |
213 | + QSet<int> ids; |
214 | + for (int i = 0; i < d->entry_count; ++i) { |
215 | + ids.insert(adapter->getNavigationEntryUniqueID(i)); |
216 | + } |
217 | + Q_FOREACH(int id, d->entry_cache.keys()) { |
218 | + if (!ids.contains(id)) { |
219 | + delete d->entry_cache.take(id); |
220 | + } |
221 | + } |
222 | +} |
223 | + |
224 | +void OxideQQuickNavigationHistory::onNavigationEntryChanged(int index) { |
225 | + Q_D(OxideQQuickNavigationHistory); |
226 | + |
227 | + OxideQQuickWebViewPrivate* adapter = OxideQQuickWebViewPrivate::get(d->webview); |
228 | + int id = adapter->getNavigationEntryUniqueID(index); |
229 | + NavigationEntry* entry; |
230 | + if (d->entry_cache.contains(id)) { |
231 | + entry = d->entry_cache.value(id); |
232 | + } else { |
233 | + entry = new NavigationEntry; |
234 | + d->entry_cache.insert(id, entry); |
235 | + } |
236 | + QVector<int> roles; |
237 | + QUrl url = adapter->getNavigationEntryUrl(index); |
238 | + if (url != entry->url) { |
239 | + entry->url = url; |
240 | + roles.append(OxideQQuickNavigationHistoryPrivate::Url); |
241 | + } |
242 | + QString title = adapter->getNavigationEntryTitle(index); |
243 | + if (title != entry->title) { |
244 | + entry->title = title; |
245 | + roles.append(OxideQQuickNavigationHistoryPrivate::Title); |
246 | + } |
247 | + QDateTime timestamp = adapter->getNavigationEntryTimestamp(index); |
248 | + if (timestamp != entry->timestamp) { |
249 | + entry->timestamp = timestamp; |
250 | + roles.append(OxideQQuickNavigationHistoryPrivate::Timestamp); |
251 | + } |
252 | + if (!roles.isEmpty()) { |
253 | + QModelIndex modelIndex = this->index(index, 0); |
254 | + Q_EMIT dataChanged(modelIndex, modelIndex, roles); |
255 | + } |
256 | +} |
257 | + |
258 | +int OxideQQuickNavigationHistory::currentIndex() const { |
259 | + Q_D(const OxideQQuickNavigationHistory); |
260 | + return d->current_index; |
261 | +} |
262 | + |
263 | +void OxideQQuickNavigationHistory::setCurrentIndex(int index) { |
264 | + Q_D(OxideQQuickNavigationHistory); |
265 | + if ((index < 0) || (index >= d->entry_count)) { |
266 | + qWarning() << "Invalid index:" << index; |
267 | + return; |
268 | + } |
269 | + if (index != d->current_index) { |
270 | + d->current_index = index; |
271 | + OxideQQuickWebViewPrivate* adapter = OxideQQuickWebViewPrivate::get(d->webview); |
272 | + adapter->setNavigationCurrentEntryIndex(index); |
273 | + Q_EMIT currentIndexChanged(); |
274 | + } |
275 | +} |
276 | + |
277 | +QHash<int, QByteArray> OxideQQuickNavigationHistory::roleNames() const { |
278 | + static QHash<int, QByteArray> roles; |
279 | + if (roles.isEmpty()) { |
280 | + roles[OxideQQuickNavigationHistoryPrivate::Url] = "url"; |
281 | + roles[OxideQQuickNavigationHistoryPrivate::Title] = "title"; |
282 | + roles[OxideQQuickNavigationHistoryPrivate::Timestamp] = "timestamp"; |
283 | + } |
284 | + return roles; |
285 | +} |
286 | + |
287 | +int OxideQQuickNavigationHistory::rowCount(const QModelIndex& parent) const { |
288 | + Q_UNUSED(parent); |
289 | + Q_D(const OxideQQuickNavigationHistory); |
290 | + return d->entry_count; |
291 | +} |
292 | + |
293 | +QVariant OxideQQuickNavigationHistory::data(const QModelIndex& index, int role) const { |
294 | + Q_D(const OxideQQuickNavigationHistory); |
295 | + if (!index.isValid()) { |
296 | + return QVariant(); |
297 | + } |
298 | + int row = index.row(); |
299 | + if ((row < 0) || (row >= d->entry_count)) { |
300 | + return QVariant(); |
301 | + } |
302 | + OxideQQuickWebViewPrivate* adapter = OxideQQuickWebViewPrivate::get(d->webview); |
303 | + int id = adapter->getNavigationEntryUniqueID(row); |
304 | + NavigationEntry* entry; |
305 | + if (d->entry_cache.contains(id)) { |
306 | + entry = d->entry_cache.value(id); |
307 | + } else { |
308 | + return QVariant(); |
309 | + } |
310 | + switch (role) { |
311 | + case OxideQQuickNavigationHistoryPrivate::Url: |
312 | + return entry->url; |
313 | + case OxideQQuickNavigationHistoryPrivate::Title: |
314 | + return entry->title; |
315 | + case OxideQQuickNavigationHistoryPrivate::Timestamp: |
316 | + return entry->timestamp; |
317 | + default: |
318 | + return QVariant(); |
319 | + } |
320 | +} |
321 | |
322 | === added file 'qt/quick/api/oxideqquicknavigationhistory_p.h' |
323 | --- qt/quick/api/oxideqquicknavigationhistory_p.h 1970-01-01 00:00:00 +0000 |
324 | +++ qt/quick/api/oxideqquicknavigationhistory_p.h 2014-01-07 14:38:44 +0000 |
325 | @@ -0,0 +1,67 @@ |
326 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
327 | +// Copyright (C) 2013 Canonical Ltd. |
328 | + |
329 | +// This library is free software; you can redistribute it and/or |
330 | +// modify it under the terms of the GNU Lesser General Public |
331 | +// License as published by the Free Software Foundation; either |
332 | +// version 2.1 of the License, or (at your option) any later version. |
333 | + |
334 | +// This library is distributed in the hope that it will be useful, |
335 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
336 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
337 | +// Lesser General Public License for more details. |
338 | + |
339 | +// You should have received a copy of the GNU Lesser General Public |
340 | +// License along with this library; if not, write to the Free Software |
341 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
342 | + |
343 | +#ifndef _OXIDE_QT_QUICK_API_NAVIGATION_HISTORY_P_H_ |
344 | +#define _OXIDE_QT_QUICK_API_NAVIGATION_HISTORY_P_H_ |
345 | + |
346 | +#include <QAbstractListModel> |
347 | +#include <QScopedPointer> |
348 | +#include <QtQml> |
349 | + |
350 | +namespace oxide { |
351 | +namespace qt { |
352 | +class WebViewAdapter; |
353 | +} |
354 | +} |
355 | + |
356 | +class OxideQQuickNavigationHistoryPrivate; |
357 | +class OxideQQuickWebView; |
358 | + |
359 | +class OxideQQuickNavigationHistory : public QAbstractListModel { |
360 | + Q_OBJECT |
361 | + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) |
362 | + |
363 | + public: |
364 | + OxideQQuickNavigationHistory(OxideQQuickWebView* webview); |
365 | + ~OxideQQuickNavigationHistory(); |
366 | + |
367 | + // reimplemented from QAbstractListModel |
368 | + QHash<int, QByteArray> roleNames() const; |
369 | + int rowCount(const QModelIndex& parent = QModelIndex()) const; |
370 | + QVariant data(const QModelIndex& index, int role) const; |
371 | + |
372 | + int currentIndex() const; |
373 | + void setCurrentIndex(int index); |
374 | + |
375 | +Q_SIGNALS: |
376 | + void currentIndexChanged(); |
377 | + |
378 | +private Q_SLOTS: |
379 | + friend class OxideQQuickWebViewPrivate; |
380 | + void onNavigationEntryCommitted(); |
381 | + void onNavigationListPruned(bool from_front, int count); |
382 | + void onNavigationEntryChanged(int index); |
383 | + |
384 | +private: |
385 | + Q_DISABLE_COPY(OxideQQuickNavigationHistory) |
386 | + QScopedPointer<OxideQQuickNavigationHistoryPrivate> d_ptr; |
387 | + Q_DECLARE_PRIVATE(OxideQQuickNavigationHistory) |
388 | +}; |
389 | + |
390 | +QML_DECLARE_TYPE(OxideQQuickNavigationHistory) |
391 | + |
392 | +#endif // _OXIDE_QT_QUICK_API_NAVIGATION_HISTORY_P_H_ |
393 | |
394 | === added file 'qt/quick/api/oxideqquicknavigationhistory_p_p.h' |
395 | --- qt/quick/api/oxideqquicknavigationhistory_p_p.h 1970-01-01 00:00:00 +0000 |
396 | +++ qt/quick/api/oxideqquicknavigationhistory_p_p.h 2014-01-07 14:38:44 +0000 |
397 | @@ -0,0 +1,44 @@ |
398 | +// vim:expandtab:shiftwidth=2:tabstop=2: |
399 | +// Copyright (C) 2013 Canonical Ltd. |
400 | + |
401 | +// This library is free software; you can redistribute it and/or |
402 | +// modify it under the terms of the GNU Lesser General Public |
403 | +// License as published by the Free Software Foundation; either |
404 | +// version 2.1 of the License, or (at your option) any later version. |
405 | + |
406 | +// This library is distributed in the hope that it will be useful, |
407 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
408 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
409 | +// Lesser General Public License for more details. |
410 | + |
411 | +// You should have received a copy of the GNU Lesser General Public |
412 | +// License along with this library; if not, write to the Free Software |
413 | +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
414 | + |
415 | +#ifndef _OXIDE_QT_QUICK_API_NAVIGATION_HISTORY_P_P_H_ |
416 | +#define _OXIDE_QT_QUICK_API_NAVIGATION_HISTORY_P_P_H_ |
417 | + |
418 | +#include <QMap> |
419 | + |
420 | +class OxideQQuickNavigationHistory; |
421 | +class OxideQQuickWebView; |
422 | + |
423 | +struct NavigationEntry; |
424 | + |
425 | +class OxideQQuickNavigationHistoryPrivate { |
426 | + Q_DECLARE_PUBLIC(OxideQQuickNavigationHistory) |
427 | + |
428 | + enum Roles { |
429 | + Url = Qt::UserRole + 1, |
430 | + Title, |
431 | + Timestamp |
432 | + }; |
433 | + |
434 | + OxideQQuickNavigationHistory* q_ptr; |
435 | + OxideQQuickWebView* webview; |
436 | + int entry_count; |
437 | + int current_index; |
438 | + QMap<int, NavigationEntry*> entry_cache; |
439 | +}; |
440 | + |
441 | +#endif // _OXIDE_QT_QUICK_API_NAVIGATION_HISTORY_P_P_H_ |
442 | |
443 | === modified file 'qt/quick/api/oxideqquickwebview.cc' |
444 | --- qt/quick/api/oxideqquickwebview.cc 2013-12-19 12:37:21 +0000 |
445 | +++ qt/quick/api/oxideqquickwebview.cc 2014-01-07 14:38:44 +0000 |
446 | @@ -57,6 +57,7 @@ |
447 | OxideQQuickWebViewPrivate::OxideQQuickWebViewPrivate( |
448 | OxideQQuickWebView* view) : |
449 | context(NULL), |
450 | + navigationHistory(view), |
451 | popup_menu(NULL), |
452 | init_props_(new InitData()), |
453 | load_progress_(0), |
454 | @@ -148,6 +149,18 @@ |
455 | emit q->loadingChanged(&event); |
456 | } |
457 | |
458 | +void OxideQQuickWebViewPrivate::NavigationEntryCommitted() { |
459 | + navigationHistory.onNavigationEntryCommitted(); |
460 | +} |
461 | + |
462 | +void OxideQQuickWebViewPrivate::NavigationListPruned(bool from_front, int count) { |
463 | + navigationHistory.onNavigationListPruned(from_front, count); |
464 | +} |
465 | + |
466 | +void OxideQQuickWebViewPrivate::NavigationEntryChanged(int index) { |
467 | + navigationHistory.onNavigationEntryChanged(index); |
468 | +} |
469 | + |
470 | oxide::qt::WebFrameAdapter* OxideQQuickWebViewPrivate::CreateWebFrame() { |
471 | return OxideQQuickWebFramePrivate::get(new OxideQQuickWebFrame()); |
472 | } |
473 | @@ -466,6 +479,12 @@ |
474 | d->context = context; |
475 | } |
476 | |
477 | +OxideQQuickNavigationHistory* OxideQQuickWebView::navigationHistory() { |
478 | + Q_D(OxideQQuickWebView); |
479 | + |
480 | + return &d->navigationHistory; |
481 | +} |
482 | + |
483 | // static |
484 | OxideQQuickWebViewAttached* OxideQQuickWebView::qmlAttachedProperties( |
485 | QObject* object) { |
486 | |
487 | === modified file 'qt/quick/api/oxideqquickwebview_p.h' |
488 | --- qt/quick/api/oxideqquickwebview_p.h 2013-12-16 12:18:07 +0000 |
489 | +++ qt/quick/api/oxideqquickwebview_p.h 2014-01-07 14:38:44 +0000 |
490 | @@ -33,6 +33,7 @@ |
491 | |
492 | class OxideQLoadEvent; |
493 | class OxideQQuickMessageHandler; |
494 | +class OxideQQuickNavigationHistory; |
495 | class OxideQQuickWebContext; |
496 | class OxideQQuickWebFrame; |
497 | class OxideQQuickWebView; |
498 | @@ -69,6 +70,8 @@ |
499 | |
500 | Q_PROPERTY(OxideQQuickWebContext* context READ context WRITE setContext) |
501 | |
502 | + Q_PROPERTY(OxideQQuickNavigationHistory* navigationHistory READ navigationHistory CONSTANT) |
503 | + |
504 | Q_DECLARE_PRIVATE(OxideQQuickWebView) |
505 | |
506 | public: |
507 | @@ -104,6 +107,8 @@ |
508 | OxideQQuickWebContext* context() const; |
509 | void setContext(OxideQQuickWebContext* context); |
510 | |
511 | + OxideQQuickNavigationHistory* navigationHistory(); |
512 | + |
513 | static OxideQQuickWebViewAttached* qmlAttachedProperties(QObject* object); |
514 | |
515 | public Q_SLOTS: |
516 | |
517 | === modified file 'qt/quick/api/oxideqquickwebview_p_p.h' |
518 | --- qt/quick/api/oxideqquickwebview_p_p.h 2013-12-16 12:18:07 +0000 |
519 | +++ qt/quick/api/oxideqquickwebview_p_p.h 2014-01-07 14:38:44 +0000 |
520 | @@ -25,6 +25,8 @@ |
521 | |
522 | #include "qt/core/glue/oxide_qt_web_view_adapter.h" |
523 | |
524 | +#include "oxideqquicknavigationhistory_p.h" |
525 | + |
526 | class OxideQQuickMessageHandler; |
527 | class OxideQQuickWebContext; |
528 | class OxideQQuickWebView; |
529 | @@ -68,6 +70,10 @@ |
530 | const QString& error_description) Q_DECL_FINAL; |
531 | void LoadSucceeded(const QUrl& url) Q_DECL_FINAL; |
532 | |
533 | + void NavigationEntryCommitted() Q_DECL_FINAL; |
534 | + void NavigationListPruned(bool from_front, int count) Q_DECL_FINAL; |
535 | + void NavigationEntryChanged(int index) Q_DECL_FINAL; |
536 | + |
537 | oxide::qt::WebFrameAdapter* CreateWebFrame() Q_DECL_FINAL; |
538 | |
539 | QRect GetContainerBounds() Q_DECL_FINAL; |
540 | @@ -92,6 +98,7 @@ |
541 | InitData* init_props() { return init_props_.data(); } |
542 | |
543 | OxideQQuickWebContext* context; |
544 | + OxideQQuickNavigationHistory navigationHistory; |
545 | QQmlComponent* popup_menu; |
546 | |
547 | private: |
548 | |
549 | === modified file 'qt/quick/oxide_qml_plugin.cc' |
550 | --- qt/quick/oxide_qml_plugin.cc 2013-10-31 03:16:28 +0000 |
551 | +++ qt/quick/oxide_qml_plugin.cc 2014-01-07 14:38:44 +0000 |
552 | @@ -26,6 +26,7 @@ |
553 | #include "qt/core/api/oxideqincomingmessage.h" |
554 | #include "qt/core/api/oxideqloadevent.h" |
555 | #include "qt/quick/api/oxideqquickmessagehandler_p.h" |
556 | +#include "qt/quick/api/oxideqquicknavigationhistory_p.h" |
557 | #include "qt/quick/api/oxideqquickoutgoingmessagerequest_p.h" |
558 | #include "qt/quick/api/oxideqquickuserscript_p.h" |
559 | #include "qt/quick/api/oxideqquickwebcontext_p.h" |
560 | @@ -212,6 +213,8 @@ |
561 | qmlRegisterUncreatableType<OxideQQuickWebFrame>(uri, 0, 1, "WebFrame", |
562 | "Frames are created automatically by Oxide to represent frames in the renderer"); |
563 | qmlRegisterType<OxideQQuickWebContext>(uri, 0, 1, "WebContext"); |
564 | + qmlRegisterUncreatableType<OxideQQuickNavigationHistory>(uri, 0, 1, "NavigationHistory", |
565 | + "Each WebView has a NavigationHistory automatically instantiated by Oxide"); |
566 | qmlRegisterType<OxideQQuickWebView>(uri, 0, 1, "WebView"); |
567 | } |
568 | }; |
569 | |
570 | === modified file 'qt/quick/qmlplugin.pro' |
571 | --- qt/quick/qmlplugin.pro 2013-12-05 18:24:51 +0000 |
572 | +++ qt/quick/qmlplugin.pro 2014-01-07 14:38:44 +0000 |
573 | @@ -12,6 +12,7 @@ |
574 | |
575 | SOURCES += \ |
576 | api/oxideqquickmessagehandler.cc \ |
577 | + api/oxideqquicknavigationhistory.cc \ |
578 | api/oxideqquickoutgoingmessagerequest.cc \ |
579 | api/oxideqquickuserscript.cc \ |
580 | api/oxideqquickwebcontext.cc \ |
581 | @@ -26,6 +27,8 @@ |
582 | HEADERS += \ |
583 | api/oxideqquickmessagehandler_p.h \ |
584 | api/oxideqquickmessagehandler_p_p.h \ |
585 | + api/oxideqquicknavigationhistory_p.h \ |
586 | + api/oxideqquicknavigationhistory_p_p.h \ |
587 | api/oxideqquickoutgoingmessagerequest_p.h \ |
588 | api/oxideqquickoutgoingmessagerequest_p_p.h \ |
589 | api/oxideqquickuserscript_p.h \ |
590 | |
591 | === modified file 'qt/tests/qmltests/data/tst_WebView_navigation1.html' |
592 | --- qt/tests/qmltests/data/tst_WebView_navigation1.html 2013-09-24 21:30:30 +0000 |
593 | +++ qt/tests/qmltests/data/tst_WebView_navigation1.html 2014-01-07 14:38:44 +0000 |
594 | @@ -1,4 +1,7 @@ |
595 | <html> |
596 | +<head> |
597 | + <title>Navigation test 1</title> |
598 | +</head> |
599 | <body> |
600 | <h1>Navigation test 1</h1> |
601 | </body> |
602 | |
603 | === modified file 'qt/tests/qmltests/data/tst_WebView_navigation2.html' |
604 | --- qt/tests/qmltests/data/tst_WebView_navigation2.html 2013-09-24 21:30:30 +0000 |
605 | +++ qt/tests/qmltests/data/tst_WebView_navigation2.html 2014-01-07 14:38:44 +0000 |
606 | @@ -1,4 +1,7 @@ |
607 | <html> |
608 | +<head> |
609 | + <title>Navigation test 2</title> |
610 | +</head> |
611 | <body> |
612 | <h1>Navigation test 2</h1> |
613 | </body> |
614 | |
615 | === modified file 'qt/tests/qmltests/data/tst_WebView_navigation3.html' |
616 | --- qt/tests/qmltests/data/tst_WebView_navigation3.html 2013-09-24 21:30:30 +0000 |
617 | +++ qt/tests/qmltests/data/tst_WebView_navigation3.html 2014-01-07 14:38:44 +0000 |
618 | @@ -1,5 +1,8 @@ |
619 | <html> |
620 | +<head> |
621 | + <title>Navigation test 3</title> |
622 | +</head> |
623 | <body> |
624 | - <h1>Navigation test 2</h1> |
625 | + <h1>Navigation test 3</h1> |
626 | </body> |
627 | </html> |
628 | |
629 | === modified file 'qt/tests/qmltests/data/tst_WebView_navigation4.html' |
630 | --- qt/tests/qmltests/data/tst_WebView_navigation4.html 2013-09-24 21:30:30 +0000 |
631 | +++ qt/tests/qmltests/data/tst_WebView_navigation4.html 2014-01-07 14:38:44 +0000 |
632 | @@ -1,4 +1,7 @@ |
633 | <html> |
634 | +<head> |
635 | + <title>Navigation test 4</title> |
636 | +</head> |
637 | <body> |
638 | <h1>Navigation test 4</h1> |
639 | </body> |
640 | |
641 | === added file 'qt/tests/qmltests/data/tst_WebView_navigationHistory.qml' |
642 | --- qt/tests/qmltests/data/tst_WebView_navigationHistory.qml 1970-01-01 00:00:00 +0000 |
643 | +++ qt/tests/qmltests/data/tst_WebView_navigationHistory.qml 2014-01-07 14:38:44 +0000 |
644 | @@ -0,0 +1,116 @@ |
645 | +import QtQuick 2.0 |
646 | +import QtTest 1.0 |
647 | +import com.canonical.Oxide 0.1 |
648 | +import com.canonical.Oxide.Testing 0.1 |
649 | + |
650 | +TestWebView { |
651 | + id: webView |
652 | + focus: true |
653 | + width: 200 |
654 | + height: 200 |
655 | + |
656 | + ListView { |
657 | + id: navigationView |
658 | + model: webView.navigationHistory |
659 | + currentIndex: model.currentIndex |
660 | + readonly property url currentUrl: currentItem ? currentItem.url : "" |
661 | + readonly property string currentTitle: currentItem ? currentItem.title : "" |
662 | + delegate: Item { |
663 | + readonly property url url: model.url |
664 | + readonly property string title: model.title |
665 | + } |
666 | + } |
667 | + |
668 | + TestCase { |
669 | + id: test |
670 | + name: "WebView_navigationHistory" |
671 | + when: windowShown |
672 | + |
673 | + readonly property alias count: navigationView.count |
674 | + readonly property alias currentIndex: navigationView.currentIndex |
675 | + readonly property alias currentUrl: navigationView.currentUrl |
676 | + readonly property alias currentTitle: navigationView.currentTitle |
677 | + |
678 | + function verifyLoadSucceeded() { |
679 | + verify(webView.waitForLoadSucceeded(), |
680 | + "Timed out waiting for a successful load"); |
681 | + } |
682 | + |
683 | + function loadUrl(url) { |
684 | + webView.url = url; |
685 | + verifyLoadSucceeded(); |
686 | + } |
687 | + |
688 | + function compareAttributes(rCount, rCurrentIndex, rCurrentUrl, |
689 | + rCurrentTitle, message) { |
690 | + compare(count, rCount, message); |
691 | + compare(currentIndex, rCurrentIndex, message); |
692 | + compare(currentUrl, rCurrentUrl, message); |
693 | + tryCompare(test, "currentTitle", rCurrentTitle); |
694 | + } |
695 | + |
696 | + function test_WebView_navigationHistory() { |
697 | + compareAttributes(0, -1, "", "", |
698 | + "Navigation history should be initially empty"); |
699 | + |
700 | + webView.navigationHistory.currentIndex = 0; |
701 | + compare(currentIndex, -1, |
702 | + "Cannot set the current index when the history is empty"); |
703 | + |
704 | + var url1 = "http://localhost:8080/tst_WebView_navigation1.html"; |
705 | + var title1 = "Navigation test 1"; |
706 | + loadUrl(url1); |
707 | + compareAttributes(1, 0, url1, title1, |
708 | + "One entry / current is the first one"); |
709 | + |
710 | + webView.navigationHistory.currentIndex = -1; |
711 | + compare(currentIndex, 0, |
712 | + "Cannot set the current index to an invalid value"); |
713 | + |
714 | + var url2 = "http://localhost:8080/tst_WebView_navigation2.html"; |
715 | + var title2 = "Navigation test 2"; |
716 | + loadUrl(url2); |
717 | + compareAttributes(2, 1, url2, title2, |
718 | + "Two entries / current entry is the last one"); |
719 | + |
720 | + webView.navigationHistory.currentIndex = 3; |
721 | + compare(currentIndex, 1, |
722 | + "Cannot set the current index to an invalid value"); |
723 | + |
724 | + webView.goBack(); |
725 | + verifyLoadSucceeded(); |
726 | + compareAttributes(2, 0, url1, title1, |
727 | + "No new entries / current is the first one"); |
728 | + |
729 | + webView.goForward(); |
730 | + verifyLoadSucceeded(); |
731 | + compareAttributes(2, 1, url2, title2, |
732 | + "No new entries / current is the last one"); |
733 | + |
734 | + webView.navigationHistory.currentIndex = 0; |
735 | + verifyLoadSucceeded(); |
736 | + compareAttributes(2, 0, url1, title1, |
737 | + "No new entries / current is the first one"); |
738 | + |
739 | + var url3 = "http://localhost:8080/tst_WebView_navigation3.html"; |
740 | + var title3 = "Navigation test 3"; |
741 | + loadUrl(url3); |
742 | + compareAttributes(2, 1, url3, title3, "Two entries / last one updated"); |
743 | + |
744 | + loadUrl(url1); |
745 | + compareAttributes(3, 2, url1, title1, |
746 | + "Three entries / current is the last one"); |
747 | + |
748 | + webView.navigationHistory.currentIndex = 0; |
749 | + verifyLoadSucceeded(); |
750 | + compareAttributes(3, 0, url1, title1, |
751 | + "No new entries / current is the first one"); |
752 | + |
753 | + var url4 = "http://localhost:8080/tst_WebView_navigation4.html"; |
754 | + var title4 = "Navigation test 4"; |
755 | + loadUrl(url4); |
756 | + compareAttributes(2, 1, url4, title4, |
757 | + "Entry count updated / current is the last one"); |
758 | + } |
759 | + } |
760 | +} |
761 | |
762 | === modified file 'shared/browser/oxide_web_view.cc' |
763 | --- shared/browser/oxide_web_view.cc 2013-12-16 12:18:07 +0000 |
764 | +++ shared/browser/oxide_web_view.cc 2014-01-07 14:38:44 +0000 |
765 | @@ -25,6 +25,13 @@ |
766 | #include "content/public/browser/invalidate_type.h" |
767 | #include "content/public/browser/browser_context.h" |
768 | #include "content/public/browser/navigation_controller.h" |
769 | +#include "content/public/browser/navigation_details.h" |
770 | +#include "content/public/browser/navigation_entry.h" |
771 | +#include "content/public/browser/notification_details.h" |
772 | +#include "content/public/browser/notification_registrar.h" |
773 | +#include "content/public/browser/notification_service.h" |
774 | +#include "content/public/browser/notification_source.h" |
775 | +#include "content/public/browser/notification_types.h" |
776 | #include "content/public/browser/web_contents.h" |
777 | #include "content/public/browser/web_contents_view.h" |
778 | #include "net/base/net_errors.h" |
779 | @@ -205,6 +212,10 @@ |
780 | const std::string& error_description) {} |
781 | void WebView::OnLoadSucceeded(const GURL& validated_url) {} |
782 | |
783 | +void WebView::OnNavigationEntryCommitted() {} |
784 | +void WebView::OnNavigationListPruned(bool from_front, int count) {} |
785 | +void WebView::OnNavigationEntryChanged(int index) {} |
786 | + |
787 | WebView::WebView() : |
788 | root_frame_(NULL) {} |
789 | |
790 | @@ -240,7 +251,13 @@ |
791 | } |
792 | |
793 | web_contents_->SetDelegate(this); |
794 | - Observe(web_contents_.get()); |
795 | + WebContentsObserver::Observe(web_contents_.get()); |
796 | + |
797 | + registrar_.reset(new content::NotificationRegistrar); |
798 | + registrar_->Add(this, content::NOTIFICATION_NAV_LIST_PRUNED, |
799 | + content::NotificationService::AllBrowserContextsAndSources()); |
800 | + registrar_->Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED, |
801 | + content::NotificationService::AllBrowserContextsAndSources()); |
802 | |
803 | return true; |
804 | } |
805 | @@ -251,7 +268,9 @@ |
806 | return; |
807 | } |
808 | |
809 | - Observe(NULL); |
810 | + registrar_.reset(); |
811 | + |
812 | + WebContentsObserver::Observe(NULL); |
813 | |
814 | if (root_frame_) { |
815 | root_frame_->DestroyFrame(); |
816 | @@ -363,6 +382,62 @@ |
817 | return BrowserContext::FromContent(web_contents_->GetBrowserContext()); |
818 | } |
819 | |
820 | +int WebView::GetNavigationEntryCount() const { |
821 | + if (!web_contents_) { |
822 | + return 0; |
823 | + } |
824 | + return web_contents_->GetController().GetEntryCount(); |
825 | +} |
826 | + |
827 | +int WebView::GetNavigationCurrentEntryIndex() const { |
828 | + if (!web_contents_) { |
829 | + return -1; |
830 | + } |
831 | + return web_contents_->GetController().GetCurrentEntryIndex(); |
832 | +} |
833 | + |
834 | +void WebView::SetNavigationCurrentEntryIndex(int index) { |
835 | + if (web_contents_) { |
836 | + web_contents_->GetController().GoToIndex(index); |
837 | + } |
838 | +} |
839 | + |
840 | +int WebView::GetNavigationEntryUniqueID(int index) const { |
841 | + if (!web_contents_) { |
842 | + return 0; |
843 | + } |
844 | + const content::NavigationController& controller = web_contents_->GetController(); |
845 | + content::NavigationEntry* entry = controller.GetEntryAtIndex(index); |
846 | + return entry->GetUniqueID(); |
847 | +} |
848 | + |
849 | +const GURL& WebView::GetNavigationEntryUrl(int index) const { |
850 | + if (!web_contents_) { |
851 | + return GURL::EmptyGURL(); |
852 | + } |
853 | + const content::NavigationController& controller = web_contents_->GetController(); |
854 | + content::NavigationEntry* entry = controller.GetEntryAtIndex(index); |
855 | + return entry->GetURL(); |
856 | +} |
857 | + |
858 | +std::string WebView::GetNavigationEntryTitle(int index) const { |
859 | + if (!web_contents_) { |
860 | + return std::string(); |
861 | + } |
862 | + const content::NavigationController& controller = web_contents_->GetController(); |
863 | + content::NavigationEntry* entry = controller.GetEntryAtIndex(index); |
864 | + return base::UTF16ToUTF8(entry->GetTitle()); |
865 | +} |
866 | + |
867 | +base::Time WebView::GetNavigationEntryTimestamp(int index) const { |
868 | + if (!web_contents_) { |
869 | + return base::Time(); |
870 | + } |
871 | + const content::NavigationController& controller = web_contents_->GetController(); |
872 | + content::NavigationEntry* entry = controller.GetEntryAtIndex(index); |
873 | + return entry->GetTimestamp(); |
874 | +} |
875 | + |
876 | WebFrame* WebView::GetRootFrame() const { |
877 | return root_frame_; |
878 | } |
879 | @@ -389,6 +464,21 @@ |
880 | return NULL; |
881 | } |
882 | |
883 | +void WebView::Observe(int type, |
884 | + const content::NotificationSource& source, |
885 | + const content::NotificationDetails& details) { |
886 | + if (content::Source<content::NavigationController>(source).ptr() != &web_contents()->GetController()) { |
887 | + return; |
888 | + } |
889 | + if (type == content::NOTIFICATION_NAV_LIST_PRUNED) { |
890 | + content::PrunedDetails* pruned_details = content::Details<content::PrunedDetails>(details).ptr(); |
891 | + OnNavigationListPruned(pruned_details->from_front, pruned_details->count); |
892 | + } else if (type == content::NOTIFICATION_NAV_ENTRY_CHANGED) { |
893 | + int index = content::Details<content::EntryChangedDetails>(details).ptr()->index; |
894 | + OnNavigationEntryChanged(index); |
895 | + } |
896 | +} |
897 | + |
898 | void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, |
899 | content::RenderViewHost* new_host) { |
900 | // Make sure the new RWHV gets the correct size |
901 | @@ -480,6 +570,10 @@ |
902 | DispatchLoadFailed(validated_url, error_code, error_description); |
903 | } |
904 | |
905 | +void WebView::NavigationEntryCommitted( |
906 | + const content::LoadCommittedDetails& load_details) { |
907 | + OnNavigationEntryCommitted(); |
908 | +} |
909 | |
910 | void WebView::FrameDetached(content::RenderViewHost* rvh, |
911 | int64 frame_id) { |
912 | @@ -491,6 +585,20 @@ |
913 | frame->DestroyFrame(); |
914 | } |
915 | |
916 | +void WebView::TitleWasSet(content::NavigationEntry* entry, bool explicit_set) { |
917 | + if (!web_contents_) { |
918 | + return; |
919 | + } |
920 | + const content::NavigationController& controller = web_contents_->GetController(); |
921 | + int count = controller.GetEntryCount(); |
922 | + for (int i = 0; i < count; ++i) { |
923 | + if (controller.GetEntryAtIndex(i) == entry) { |
924 | + OnNavigationEntryChanged(i); |
925 | + return; |
926 | + } |
927 | + } |
928 | +} |
929 | + |
930 | bool WebView::OnMessageReceived(const IPC::Message& message) { |
931 | bool handled = true; |
932 | IPC_BEGIN_MESSAGE_MAP(WebView, message) |
933 | |
934 | === modified file 'shared/browser/oxide_web_view.h' |
935 | --- shared/browser/oxide_web_view.h 2013-12-16 12:18:07 +0000 |
936 | +++ shared/browser/oxide_web_view.h 2014-01-07 14:38:44 +0000 |
937 | @@ -24,6 +24,7 @@ |
938 | #include "base/basictypes.h" |
939 | #include "base/compiler_specific.h" |
940 | #include "base/memory/scoped_ptr.h" |
941 | +#include "content/public/browser/notification_observer.h" |
942 | #include "content/public/browser/web_contents_delegate.h" |
943 | #include "content/public/browser/web_contents_observer.h" |
944 | #include "ui/gfx/rect.h" |
945 | @@ -41,6 +42,7 @@ |
946 | |
947 | namespace content { |
948 | |
949 | +class NotificationRegistrar; |
950 | struct OpenURLParams; |
951 | class RenderWidgetHost; |
952 | class RenderWidgetHostView; |
953 | @@ -58,6 +60,7 @@ |
954 | // this. Note that this class will hold the main browser process |
955 | // components alive |
956 | class WebView : public MessageTarget, |
957 | + public content::NotificationObserver, |
958 | public content::WebContentsDelegate, |
959 | public content::WebContentsObserver { |
960 | public: |
961 | @@ -94,9 +97,21 @@ |
962 | |
963 | BrowserContext* GetBrowserContext() const; |
964 | |
965 | + int GetNavigationEntryCount() const; |
966 | + int GetNavigationCurrentEntryIndex() const; |
967 | + void SetNavigationCurrentEntryIndex(int index); |
968 | + int GetNavigationEntryUniqueID(int index) const; |
969 | + const GURL& GetNavigationEntryUrl(int index) const; |
970 | + std::string GetNavigationEntryTitle(int index) const; |
971 | + base::Time GetNavigationEntryTimestamp(int index) const; |
972 | + |
973 | WebFrame* GetRootFrame() const; |
974 | WebFrame* FindFrameWithID(int64 frame_id) const; |
975 | |
976 | + void Observe(int type, |
977 | + const content::NotificationSource& source, |
978 | + const content::NotificationDetails& details) FINAL; |
979 | + |
980 | void RenderViewHostChanged(content::RenderViewHost* old_host, |
981 | content::RenderViewHost* new_host) FINAL; |
982 | |
983 | @@ -137,9 +152,14 @@ |
984 | const base::string16& error_description, |
985 | content::RenderViewHost* render_view_host) FINAL; |
986 | |
987 | + void NavigationEntryCommitted( |
988 | + const content::LoadCommittedDetails& load_details) FINAL; |
989 | + |
990 | void FrameDetached(content::RenderViewHost* rvh, |
991 | int64 frame_id) FINAL; |
992 | |
993 | + void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) FINAL; |
994 | + |
995 | bool OnMessageReceived(const IPC::Message& message) FINAL; |
996 | |
997 | virtual size_t GetMessageHandlerCount() const OVERRIDE; |
998 | @@ -200,11 +220,17 @@ |
999 | const std::string& error_description); |
1000 | virtual void OnLoadSucceeded(const GURL& validated_url); |
1001 | |
1002 | + virtual void OnNavigationEntryCommitted(); |
1003 | + virtual void OnNavigationListPruned(bool from_front, int count); |
1004 | + virtual void OnNavigationEntryChanged(int index); |
1005 | + |
1006 | virtual WebFrame* CreateWebFrame() = 0; |
1007 | |
1008 | scoped_ptr<content::WebContents> web_contents_; |
1009 | WebFrame* root_frame_; |
1010 | |
1011 | + scoped_ptr<content::NotificationRegistrar> registrar_; |
1012 | + |
1013 | DISALLOW_COPY_AND_ASSIGN(WebView); |
1014 | }; |
1015 |
Thanks for working on this - it's looking good! I've just got a few initial comments:
- Do we need virtualUrl and titleForDisplay for anything? I'd be tempted to leave those out for now unless we've got a use-case for them.
- Technically, the code in the additional functions added to WebViewAdapterP rivate could all live in WebViewAdapter. The classes in qt/core/ glue/private are only there so that we don't leak Chromium API's / types across a public interface, and also to provide a way of constructing objects from other parts of Oxide (see the text in qt/core/api/README, which is applicable here too). However, I've not been that disciplined in making it obvious where code should live, so it's ok as it is for now. I'll probably push some cleanup patches later on for everything in qt/core/glue.
Saying that, as those functions aren't Qt-specific, they could probably just go in oxide::WebView instead...
**************
+ igationhistory_ p.h" igationhistory_ p_p.h" view_p. h" glue/oxide_ qt_web_ view_adapter. h"
+#include "oxideqquicknav
+#include "oxideqquicknav
+#include "oxideqquickweb
+
+#include <QDateTime>
+#include <QString>
+#include <QtAlgorithms>
+#include <QUrl>
+
+#include "qt/core/
+
+struct NavigationEntry {
Just a nit, but generally I've tried to follow the Google style guide when ordering headers (http:// google- styleguide. googlecode. com/svn/ trunk/cppguide. xml#Names_ and_Order_ of_Includes), with the additional requirements of putting headers from shared/ before those in qt/ and listing headers from the same folder as the current object at the end. So I would order these like this:
#include "oxideqquicknav igationhistory_ p.h" igationhistory_ p_p.h"
#include "oxideqquicknav
#include <QDateTime>
#include <QString>
#include <QtAlgorithms>
#include <QUrl>
#include "qt/core/ glue/oxide_ qt_web_ view_adapter. h"
#include "oxideqquickweb view_p. h"
I should write this down somewhere :)
**************
+OxideQQuickNav igationHistory: :OxideQQuickNav igationHistory( qt::WebViewAdap ter* adapter, OxideQQuickWebView* webview) : del(webview) , gationHistoryPr ivate) { NavigationHisto ry);
+ oxide::
+ QAbstractListMo
+ d_ptr(new OxideQQuickNavi
+ Q_D(OxideQQuick
+ d->q_ptr = this;
The "adapter" parameter in the constructor is not needed here, as there is a helper for getting this already from the public webview instance (OxideQQuickWeb ViewPrivate: :get()) .
**************
+void OxideQQuickNavi gationHistory: :onNavigationHi storyChanged( ) { NavigationHisto ry); d->webview_ adapter_ != NULL); adapter_ ->getNavigation EntryCount( ); adapter_ ->getNavigation EntryUniqueID( i); cache_. contains( id)) { cache_. value(id) ; cache_. insert( id, entry); adapter_ ->getNavigation EntryUrl( i); adapter_ ->getNavigation EntryVirtualUrl (i);
+ Q_D(OxideQQuick
+ Q_ASSERT(
+
+ int newCount = d->webview_
+ if (newCount != d->entry_count_) {
+ beginResetModel();
+ d->entry_count_ = newCount;
+ for (int i = 0; i < newCount; ++i) {
+ int id = d->webview_
+ NavigationEntry* entry;
+ if (d->entry_
+ entry = d->entry_
+ } else {
+ entry = new NavigationEntry;
+ d->entry_
+ }
+ entry->url = d->webview_
+ entry->virtualUrl = d->webview_
+ ...