|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 /* This test checks that bookmarks service is correctly forwarding async |
|
5 * events like visit or favicon additions. */ |
|
6 |
|
7 const NOW = Date.now() * 1000; |
|
8 |
|
9 let observer = { |
|
10 bookmarks: [], |
|
11 observedBookmarks: 0, |
|
12 observedVisitId: 0, |
|
13 deferred: null, |
|
14 |
|
15 /** |
|
16 * Returns a promise that is resolved when the observer determines that the |
|
17 * test can continue. This is required rather than calling run_next_test |
|
18 * directly in the observer because there are cases where we must wait for |
|
19 * other asynchronous events to be completed in addition to this. |
|
20 */ |
|
21 setupCompletionPromise: function () |
|
22 { |
|
23 this.observedBookmarks = 0; |
|
24 this.deferred = Promise.defer(); |
|
25 return this.deferred.promise; |
|
26 }, |
|
27 |
|
28 onBeginUpdateBatch: function () {}, |
|
29 onEndUpdateBatch: function () {}, |
|
30 onItemAdded: function () {}, |
|
31 onItemRemoved: function () {}, |
|
32 onItemMoved: function () {}, |
|
33 onItemChanged: function(aItemId, aProperty, aIsAnnotation, aNewValue, |
|
34 aLastModified, aItemType) |
|
35 { |
|
36 do_log_info("Check that we got the correct change information."); |
|
37 do_check_neq(this.bookmarks.indexOf(aItemId), -1); |
|
38 if (aProperty == "favicon") { |
|
39 do_check_false(aIsAnnotation); |
|
40 do_check_eq(aNewValue, SMALLPNG_DATA_URI.spec); |
|
41 do_check_eq(aLastModified, 0); |
|
42 do_check_eq(aItemType, PlacesUtils.bookmarks.TYPE_BOOKMARK); |
|
43 } |
|
44 else if (aProperty == "cleartime") { |
|
45 do_check_false(aIsAnnotation); |
|
46 do_check_eq(aNewValue, ""); |
|
47 do_check_eq(aLastModified, 0); |
|
48 do_check_eq(aItemType, PlacesUtils.bookmarks.TYPE_BOOKMARK); |
|
49 } |
|
50 else { |
|
51 do_throw("Unexpected property change " + aProperty); |
|
52 } |
|
53 |
|
54 if (++this.observedBookmarks == this.bookmarks.length) { |
|
55 this.deferred.resolve(); |
|
56 } |
|
57 }, |
|
58 onItemVisited: function(aItemId, aVisitId, aTime) |
|
59 { |
|
60 do_log_info("Check that we got the correct visit information."); |
|
61 do_check_neq(this.bookmarks.indexOf(aItemId), -1); |
|
62 this.observedVisitId = aVisitId; |
|
63 do_check_eq(aTime, NOW); |
|
64 if (++this.observedBookmarks == this.bookmarks.length) { |
|
65 this.deferred.resolve(); |
|
66 } |
|
67 }, |
|
68 |
|
69 QueryInterface: XPCOMUtils.generateQI([ |
|
70 Ci.nsINavBookmarkObserver, |
|
71 ]) |
|
72 }; |
|
73 PlacesUtils.bookmarks.addObserver(observer, false); |
|
74 |
|
75 add_task(function test_add_visit() |
|
76 { |
|
77 let observerPromise = observer.setupCompletionPromise(); |
|
78 |
|
79 // Add a visit to the bookmark and wait for the observer. |
|
80 let visitId; |
|
81 let deferUpdatePlaces = Promise.defer(); |
|
82 PlacesUtils.asyncHistory.updatePlaces({ |
|
83 uri: NetUtil.newURI("http://book.ma.rk/"), |
|
84 visits: [{ transitionType: TRANSITION_TYPED, visitDate: NOW }] |
|
85 }, { |
|
86 handleError: function TAV_handleError() { |
|
87 deferUpdatePlaces.reject(new Error("Unexpected error in adding visit.")); |
|
88 }, |
|
89 handleResult: function (aPlaceInfo) { |
|
90 visitId = aPlaceInfo.visits[0].visitId; |
|
91 }, |
|
92 handleCompletion: function TAV_handleCompletion() { |
|
93 deferUpdatePlaces.resolve(); |
|
94 } |
|
95 }); |
|
96 |
|
97 // Wait for both the observer and the asynchronous update, in any order. |
|
98 yield deferUpdatePlaces.promise; |
|
99 yield observerPromise; |
|
100 |
|
101 // Check that both asynchronous results are consistent. |
|
102 do_check_eq(observer.observedVisitId, visitId); |
|
103 }); |
|
104 |
|
105 add_task(function test_add_icon() |
|
106 { |
|
107 let observerPromise = observer.setupCompletionPromise(); |
|
108 PlacesUtils.favicons.setAndFetchFaviconForPage(NetUtil.newURI("http://book.ma.rk/"), |
|
109 SMALLPNG_DATA_URI, true, |
|
110 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE); |
|
111 yield observerPromise; |
|
112 }); |
|
113 |
|
114 add_task(function test_remove_page() |
|
115 { |
|
116 let observerPromise = observer.setupCompletionPromise(); |
|
117 PlacesUtils.history.removePage(NetUtil.newURI("http://book.ma.rk/")); |
|
118 yield observerPromise; |
|
119 }); |
|
120 |
|
121 add_task(function cleanup() |
|
122 { |
|
123 PlacesUtils.bookmarks.removeObserver(observer, false); |
|
124 }); |
|
125 |
|
126 add_task(function shutdown() |
|
127 { |
|
128 // Check that async observers don't try to create async statements after |
|
129 // shutdown. That would cause assertions, since the async thread is gone |
|
130 // already. Note that in such a case the notifications are not fired, so we |
|
131 // cannot test for them. |
|
132 // Put an history notification that triggers AsyncGetBookmarksForURI between |
|
133 // asyncClose() and the actual connection closing. Enqueuing a main-thread |
|
134 // event just after places-will-close-connection should ensure it runs before |
|
135 // places-connection-closed. |
|
136 // Notice this code is not using helpers cause it depends on a very specific |
|
137 // order, a change in the helpers code could make this test useless. |
|
138 let deferred = Promise.defer(); |
|
139 |
|
140 Services.obs.addObserver(function onNotification() { |
|
141 Services.obs.removeObserver(onNotification, "places-will-close-connection"); |
|
142 do_check_true(true, "Observed fake places shutdown"); |
|
143 |
|
144 Services.tm.mainThread.dispatch(() => { |
|
145 // WARNING: this is very bad, never use out of testing code. |
|
146 PlacesUtils.bookmarks.QueryInterface(Ci.nsINavHistoryObserver) |
|
147 .onPageChanged(NetUtil.newURI("http://book.ma.rk/"), |
|
148 Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON, |
|
149 "test", "test"); |
|
150 deferred.resolve(promiseTopicObserved("places-connection-closed")); |
|
151 }, Ci.nsIThread.DISPATCH_NORMAL); |
|
152 }, "places-will-close-connection", false); |
|
153 shutdownPlaces(); |
|
154 |
|
155 yield deferred.promise; |
|
156 }); |
|
157 |
|
158 function run_test() |
|
159 { |
|
160 // Add multiple bookmarks to the same uri. |
|
161 observer.bookmarks.push( |
|
162 PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, |
|
163 NetUtil.newURI("http://book.ma.rk/"), |
|
164 PlacesUtils.bookmarks.DEFAULT_INDEX, |
|
165 "Bookmark") |
|
166 ); |
|
167 observer.bookmarks.push( |
|
168 PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId, |
|
169 NetUtil.newURI("http://book.ma.rk/"), |
|
170 PlacesUtils.bookmarks.DEFAULT_INDEX, |
|
171 "Bookmark") |
|
172 ); |
|
173 |
|
174 run_next_test(); |
|
175 } |