OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/app/spotlight/bookmarks_spotlight_manager.h" | 5 #import "ios/chrome/app/spotlight/bookmarks_spotlight_manager.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #import <CoreSpotlight/CoreSpotlight.h> | 9 #import <CoreSpotlight/CoreSpotlight.h> |
10 | 10 |
11 #include "base/ios/weak_nsobject.h" | |
12 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
13 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
14 #include "base/version.h" | 13 #include "base/version.h" |
15 #include "components/bookmarks/browser/base_bookmark_model_observer.h" | 14 #include "components/bookmarks/browser/base_bookmark_model_observer.h" |
16 #include "components/bookmarks/browser/bookmark_model.h" | 15 #include "components/bookmarks/browser/bookmark_model.h" |
17 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" | 16 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" |
18 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" | 17 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" |
19 | 18 |
| 19 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 20 #error "This file requires ARC support." |
| 21 #endif |
| 22 |
20 namespace { | 23 namespace { |
21 // Limit the size of the initial indexing. This will not limit the size of the | 24 // Limit the size of the initial indexing. This will not limit the size of the |
22 // index as new bookmarks can be added afterwards. | 25 // index as new bookmarks can be added afterwards. |
23 const int kMaxInitialIndexSize = 1000; | 26 const int kMaxInitialIndexSize = 1000; |
24 | 27 |
25 // Minimum delay between two global indexing of bookmarks. | 28 // Minimum delay between two global indexing of bookmarks. |
26 const int kDelayBetweenTwoIndexingInSeconds = 7 * 86400; // One week. | 29 const int kDelayBetweenTwoIndexingInSeconds = 7 * 86400; // One week. |
27 | 30 |
28 } // namespace | 31 } // namespace |
29 | 32 |
30 class SpotlightBookmarkModelBridge; | 33 class SpotlightBookmarkModelBridge; |
31 | 34 |
32 // Called from the BrowserBookmarkModelBridge from C++ -> ObjC. | 35 // Called from the BrowserBookmarkModelBridge from C++ -> ObjC. |
33 @interface BookmarksSpotlightManager () { | 36 @interface BookmarksSpotlightManager () { |
34 base::WeakNSProtocol<id<BookmarkUpdatedDelegate>> _delegate; | 37 __weak id<BookmarkUpdatedDelegate> _delegate; |
35 | 38 |
36 // Bridge to register for bookmark changes. | 39 // Bridge to register for bookmark changes. |
37 std::unique_ptr<SpotlightBookmarkModelBridge> _bookmarkModelBridge; | 40 std::unique_ptr<SpotlightBookmarkModelBridge> _bookmarkModelBridge; |
38 | 41 |
39 // Keep a reference to detach before deallocing. Life cycle of _bookmarkModel | 42 // Keep a reference to detach before deallocing. Life cycle of _bookmarkModel |
40 // is longer than life cycle of a SpotlightManager as | 43 // is longer than life cycle of a SpotlightManager as |
41 // |BookmarkModelBeingDeleted| will cause deletion of SpotlightManager. | 44 // |BookmarkModelBeingDeleted| will cause deletion of SpotlightManager. |
42 bookmarks::BookmarkModel* _bookmarkModel; // weak | 45 bookmarks::BookmarkModel* _bookmarkModel; // weak |
43 | 46 |
44 // Number of nodes indexed in initial scan. | 47 // Number of nodes indexed in initial scan. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 137 |
135 void BookmarkNodeMoved(bookmarks::BookmarkModel* model, | 138 void BookmarkNodeMoved(bookmarks::BookmarkModel* model, |
136 const bookmarks::BookmarkNode* old_parent, | 139 const bookmarks::BookmarkNode* old_parent, |
137 int old_index, | 140 int old_index, |
138 const bookmarks::BookmarkNode* new_parent, | 141 const bookmarks::BookmarkNode* new_parent, |
139 int new_index) override { | 142 int new_index) override { |
140 [owner_ refreshNodeInIndex:new_parent->GetChild(new_index) initial:NO]; | 143 [owner_ refreshNodeInIndex:new_parent->GetChild(new_index) initial:NO]; |
141 }; | 144 }; |
142 | 145 |
143 private: | 146 private: |
144 __unsafe_unretained BookmarksSpotlightManager* owner_; // Weak. | 147 __weak BookmarksSpotlightManager* owner_; |
145 }; | 148 }; |
146 | 149 |
147 @implementation BookmarksSpotlightManager | 150 @implementation BookmarksSpotlightManager |
148 | 151 |
149 + (BookmarksSpotlightManager*)bookmarksSpotlightManagerWithBrowserState: | 152 + (BookmarksSpotlightManager*)bookmarksSpotlightManagerWithBrowserState: |
150 (ios::ChromeBrowserState*)browserState { | 153 (ios::ChromeBrowserState*)browserState { |
151 return [[[BookmarksSpotlightManager alloc] | 154 return [[BookmarksSpotlightManager alloc] |
152 initWithLargeIconService:IOSChromeLargeIconServiceFactory:: | 155 initWithLargeIconService:IOSChromeLargeIconServiceFactory:: |
153 GetForBrowserState(browserState) | 156 GetForBrowserState(browserState) |
154 bookmarkModel:ios::BookmarkModelFactory::GetForBrowserState( | 157 bookmarkModel:ios::BookmarkModelFactory::GetForBrowserState( |
155 browserState)] autorelease]; | 158 browserState)]; |
156 } | 159 } |
157 | 160 |
158 - (instancetype) | 161 - (instancetype) |
159 initWithLargeIconService:(favicon::LargeIconService*)largeIconService | 162 initWithLargeIconService:(favicon::LargeIconService*)largeIconService |
160 bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel { | 163 bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel { |
161 self = [super initWithLargeIconService:largeIconService | 164 self = [super initWithLargeIconService:largeIconService |
162 domain:spotlight::DOMAIN_BOOKMARKS]; | 165 domain:spotlight::DOMAIN_BOOKMARKS]; |
163 if (self) { | 166 if (self) { |
164 _bookmarkModelBridge.reset(new SpotlightBookmarkModelBridge(self)); | 167 _bookmarkModelBridge.reset(new SpotlightBookmarkModelBridge(self)); |
165 _bookmarkModel = bookmarkModel; | 168 _bookmarkModel = bookmarkModel; |
166 bookmarkModel->AddObserver(_bookmarkModelBridge.get()); | 169 bookmarkModel->AddObserver(_bookmarkModelBridge.get()); |
167 } | 170 } |
168 return self; | 171 return self; |
169 } | 172 } |
170 | 173 |
171 - (void)dealloc { | 174 - (void)dealloc { |
172 [self detachBookmarkModel]; | 175 [self detachBookmarkModel]; |
173 [super dealloc]; | |
174 } | 176 } |
175 | 177 |
176 - (void)detachBookmarkModel { | 178 - (void)detachBookmarkModel { |
177 [self cancelAllLargeIconPendingTasks]; | 179 [self cancelAllLargeIconPendingTasks]; |
178 if (_bookmarkModelBridge.get()) { | 180 if (_bookmarkModelBridge.get()) { |
179 _bookmarkModel->RemoveObserver(_bookmarkModelBridge.get()); | 181 _bookmarkModel->RemoveObserver(_bookmarkModelBridge.get()); |
180 _bookmarkModelBridge.reset(); | 182 _bookmarkModelBridge.reset(); |
181 } | 183 } |
182 } | 184 } |
183 | 185 |
184 - (id<BookmarkUpdatedDelegate>)delegate { | 186 - (id<BookmarkUpdatedDelegate>)delegate { |
185 return _delegate; | 187 return _delegate; |
186 } | 188 } |
187 | 189 |
188 - (void)setDelegate:(id<BookmarkUpdatedDelegate>)delegate { | 190 - (void)setDelegate:(id<BookmarkUpdatedDelegate>)delegate { |
189 _delegate.reset(delegate); | 191 _delegate = delegate; |
190 } | 192 } |
191 | 193 |
192 - (void)getParentKeywordsForNode:(const bookmarks::BookmarkNode*)node | 194 - (void)getParentKeywordsForNode:(const bookmarks::BookmarkNode*)node |
193 inArray:(NSMutableArray*)keywords { | 195 inArray:(NSMutableArray*)keywords { |
194 if (!node) { | 196 if (!node) { |
195 return; | 197 return; |
196 } | 198 } |
197 if (node->is_folder() && !_bookmarkModel->is_permanent_node(node)) { | 199 if (node->is_folder() && !_bookmarkModel->is_permanent_node(node)) { |
198 [keywords addObject:base::SysUTF16ToNSString(node->GetTitle())]; | 200 [keywords addObject:base::SysUTF16ToNSString(node->GetTitle())]; |
199 } | 201 } |
200 [self getParentKeywordsForNode:node->parent() inArray:keywords]; | 202 [self getParentKeywordsForNode:node->parent() inArray:keywords]; |
201 } | 203 } |
202 | 204 |
203 - (void)removeNodeFromIndex:(const bookmarks::BookmarkNode*)node { | 205 - (void)removeNodeFromIndex:(const bookmarks::BookmarkNode*)node { |
204 if (node->is_url()) { | 206 if (node->is_url()) { |
205 GURL url(node->url()); | 207 GURL url(node->url()); |
206 NSString* title = base::SysUTF16ToNSString(node->GetTitle()); | 208 NSString* title = base::SysUTF16ToNSString(node->GetTitle()); |
207 NSString* spotlightID = [self spotlightIDForURL:url title:title]; | 209 NSString* spotlightID = [self spotlightIDForURL:url title:title]; |
208 base::WeakNSObject<BookmarksSpotlightManager> weakself(self); | 210 __weak BookmarksSpotlightManager* weakself = self; |
209 BlockWithError completion = ^(NSError* error) { | 211 BlockWithError completion = ^(NSError* error) { |
210 dispatch_async(dispatch_get_main_queue(), ^{ | 212 dispatch_async(dispatch_get_main_queue(), ^{ |
211 [weakself refreshItemsWithURL:url title:nil]; | 213 [weakself refreshItemsWithURL:url title:nil]; |
212 [_delegate bookmarkUpdated]; | 214 [_delegate bookmarkUpdated]; |
213 }); | 215 }); |
214 }; | 216 }; |
215 spotlight::DeleteItemsWithIdentifiers(@[ spotlightID ], completion); | 217 spotlight::DeleteItemsWithIdentifiers(@[ spotlightID ], completion); |
216 return; | 218 return; |
217 } | 219 } |
218 int childCount = node->child_count(); | 220 int childCount = node->child_count(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 } | 279 } |
278 int childCount = node->child_count(); | 280 int childCount = node->child_count(); |
279 for (int child = 0; child < childCount; child++) { | 281 for (int child = 0; child < childCount; child++) { |
280 [self refreshNodeInIndex:node->GetChild(child) initial:initial]; | 282 [self refreshNodeInIndex:node->GetChild(child) initial:initial]; |
281 } | 283 } |
282 } | 284 } |
283 | 285 |
284 - (NSArray*)spotlightItemsWithURL:(const GURL&)URL | 286 - (NSArray*)spotlightItemsWithURL:(const GURL&)URL |
285 favicon:(UIImage*)favicon | 287 favicon:(UIImage*)favicon |
286 defaultTitle:(NSString*)defaultTitle { | 288 defaultTitle:(NSString*)defaultTitle { |
287 base::scoped_nsobject<NSMutableDictionary> spotlightItems( | 289 NSMutableDictionary* spotlightItems = [[NSMutableDictionary alloc] init]; |
288 [[NSMutableDictionary alloc] init]); | |
289 std::vector<const bookmarks::BookmarkNode*> nodes; | 290 std::vector<const bookmarks::BookmarkNode*> nodes; |
290 _bookmarkModel->GetNodesByURL(URL, &nodes); | 291 _bookmarkModel->GetNodesByURL(URL, &nodes); |
291 for (auto node : nodes) { | 292 for (auto node : nodes) { |
292 NSString* nodeTitle = base::SysUTF16ToNSString(node->GetTitle()); | 293 NSString* nodeTitle = base::SysUTF16ToNSString(node->GetTitle()); |
293 NSString* spotlightID = [self spotlightIDForURL:URL title:nodeTitle]; | 294 NSString* spotlightID = [self spotlightIDForURL:URL title:nodeTitle]; |
294 CSSearchableItem* item = [spotlightItems objectForKey:spotlightID]; | 295 CSSearchableItem* item = [spotlightItems objectForKey:spotlightID]; |
295 if (!item) { | 296 if (!item) { |
296 item = [[super spotlightItemsWithURL:URL | 297 item = [[super spotlightItemsWithURL:URL |
297 favicon:favicon | 298 favicon:favicon |
298 defaultTitle:nodeTitle] objectAtIndex:0]; | 299 defaultTitle:nodeTitle] objectAtIndex:0]; |
299 } | 300 } |
300 base::scoped_nsobject<NSMutableArray> nodeKeywords( | 301 NSMutableArray* nodeKeywords = [[NSMutableArray alloc] init]; |
301 [[NSMutableArray alloc] init]); | 302 [self getParentKeywordsForNode:node inArray:nodeKeywords]; |
302 [self getParentKeywordsForNode:node inArray:nodeKeywords.get()]; | |
303 [self addKeywords:nodeKeywords toSearchableItem:item]; | 303 [self addKeywords:nodeKeywords toSearchableItem:item]; |
304 [spotlightItems setObject:item forKey:spotlightID]; | 304 [spotlightItems setObject:item forKey:spotlightID]; |
305 } | 305 } |
306 return [spotlightItems allValues]; | 306 return [spotlightItems allValues]; |
307 } | 307 } |
308 | 308 |
309 - (void)clearAndReindexModel { | 309 - (void)clearAndReindexModel { |
310 [self cancelAllLargeIconPendingTasks]; | 310 [self cancelAllLargeIconPendingTasks]; |
311 base::WeakNSObject<BookmarksSpotlightManager> weakself(self); | 311 __weak BookmarksSpotlightManager* weakself = self; |
312 BlockWithError completion = ^(NSError* error) { | 312 BlockWithError completion = ^(NSError* error) { |
313 if (!error) { | 313 if (!error) { |
314 dispatch_async(dispatch_get_main_queue(), ^{ | 314 dispatch_async(dispatch_get_main_queue(), ^{ |
315 base::scoped_nsobject<BookmarksSpotlightManager> strongSelf( | 315 BookmarksSpotlightManager* strongSelf = weakself; |
316 [weakself retain]); | |
317 if (!strongSelf) | 316 if (!strongSelf) |
318 return; | 317 return; |
319 | 318 |
320 NSDate* startOfReindexing = [NSDate date]; | 319 NSDate* startOfReindexing = [NSDate date]; |
321 strongSelf.get()->_nodesIndexed = 0; | 320 strongSelf->_nodesIndexed = 0; |
322 [strongSelf | 321 [strongSelf refreshNodeInIndex:strongSelf->_bookmarkModel->root_node() |
323 refreshNodeInIndex:strongSelf.get()->_bookmarkModel->root_node() | 322 initial:YES]; |
324 initial:YES]; | |
325 NSDate* endOfReindexing = [NSDate date]; | 323 NSDate* endOfReindexing = [NSDate date]; |
326 NSTimeInterval indexingDuration = | 324 NSTimeInterval indexingDuration = |
327 [endOfReindexing timeIntervalSinceDate:startOfReindexing]; | 325 [endOfReindexing timeIntervalSinceDate:startOfReindexing]; |
328 UMA_HISTOGRAM_TIMES( | 326 UMA_HISTOGRAM_TIMES( |
329 "IOS.Spotlight.BookmarksIndexingDuration", | 327 "IOS.Spotlight.BookmarksIndexingDuration", |
330 base::TimeDelta::FromMillisecondsD(1000 * indexingDuration)); | 328 base::TimeDelta::FromMillisecondsD(1000 * indexingDuration)); |
331 UMA_HISTOGRAM_COUNTS_1000("IOS.Spotlight.BookmarksInitialIndexSize", | 329 UMA_HISTOGRAM_COUNTS_1000("IOS.Spotlight.BookmarksInitialIndexSize", |
332 [strongSelf pendingLargeIconTasksCount]); | 330 [strongSelf pendingLargeIconTasksCount]); |
333 [[NSUserDefaults standardUserDefaults] | 331 [[NSUserDefaults standardUserDefaults] |
334 setObject:endOfReindexing | 332 setObject:endOfReindexing |
335 forKey:@(spotlight::kSpotlightLastIndexingDateKey)]; | 333 forKey:@(spotlight::kSpotlightLastIndexingDateKey)]; |
336 | 334 |
337 [[NSUserDefaults standardUserDefaults] | 335 [[NSUserDefaults standardUserDefaults] |
338 setObject:[NSNumber numberWithInteger: | 336 setObject:[NSNumber numberWithInteger: |
339 spotlight::kCurrentSpotlightIndexVersion] | 337 spotlight::kCurrentSpotlightIndexVersion] |
340 forKey:@(spotlight::kSpotlightLastIndexingVersionKey)]; | 338 forKey:@(spotlight::kSpotlightLastIndexingVersionKey)]; |
341 [_delegate bookmarkUpdated]; | 339 [_delegate bookmarkUpdated]; |
342 }); | 340 }); |
343 } | 341 } |
344 }; | 342 }; |
345 [self clearAllSpotlightItems:completion]; | 343 [self clearAllSpotlightItems:completion]; |
346 } | 344 } |
347 | 345 |
348 @end | 346 @end |
OLD | NEW |