Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(410)

Unified Diff: components/enhanced_bookmarks/bookmark_image_service.cc

Issue 513793002: Bring up of ImageService. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/enhanced_bookmarks/bookmark_image_service.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/enhanced_bookmarks/bookmark_image_service.cc
diff --git a/components/enhanced_bookmarks/bookmark_image_service.cc b/components/enhanced_bookmarks/bookmark_image_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5f515a9fbfd56e46d30323b27fd49f2dfd317b91
--- /dev/null
+++ b/components/enhanced_bookmarks/bookmark_image_service.cc
@@ -0,0 +1,340 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "components/enhanced_bookmarks/bookmark_image_service.h"
+
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_model_observer.h"
+#include "components/enhanced_bookmarks/enhanced_bookmark_utils.h"
+#include "components/enhanced_bookmarks/metadata_accessor.h"
+#include "components/enhanced_bookmarks/persistent_image_store.h"
+
+namespace {
+
+const char kSequenceToken[] = "BookmarkImagesSequenceToken";
+
+void ConstructPersistentImageStore(PersistentImageStore* store,
+ const base::FilePath& path) {
+ DCHECK(store);
+ new (store) PersistentImageStore(path);
+}
+
+void DeleteImageStore(ImageStore* store) {
+ DCHECK(store);
+ delete store;
+}
+
+void RetrieveImageFromStoreRelay(
+ ImageStore* store,
+ const GURL& page_url,
+ enhanced_bookmarks::BookmarkImageService::Callback callback,
+ scoped_refptr<base::SingleThreadTaskRunner> origin_loop) {
+ std::pair<gfx::Image, GURL> image_data = store->Get(page_url);
+ origin_loop->PostTask(
+ FROM_HERE, base::Bind(callback, image_data.first, image_data.second));
+}
+
+} // namespace
+
+namespace enhanced_bookmarks {
+BookmarkImageService::BookmarkImageService(
+ scoped_ptr<ImageStore> store,
+ BookmarkModel* bookmark_model,
+ scoped_refptr<base::SequencedWorkerPool> pool)
+ : bookmark_model_(bookmark_model), store_(store.Pass()), pool_(pool) {
+ DCHECK(CalledOnValidThread());
+ bookmark_model_->AddObserver(this);
+}
+
+BookmarkImageService::BookmarkImageService(
+ const base::FilePath& path,
+ BookmarkModel* bookmark_model,
+ scoped_refptr<base::SequencedWorkerPool> pool)
+ : bookmark_model_(bookmark_model), pool_(pool) {
+ DCHECK(CalledOnValidThread());
+ // PersistentImageStore has to be constructed in the thread it will be used,
+ // so we are posting the construction to the thread. However, we first
+ // allocate memory and keep here. The reason is that, before
+ // PersistentImageStore construction is done, it's possible that
+ // another member function, that posts store_ to the thread, is called.
+ // Although the construction might not be finished yet, we still want to post
+ // the task since it's guaranteed to be constructed by the time it is used, by
+ // the sequential thread task pool.
+ //
+ // Other alternatives:
+ // - Using a lock or WaitableEvent for PersistentImageStore construction.
+ // But waiting on UI thread is discouraged.
+ // - Posting the current BookmarkImageService instance instead of store_.
+ // But this will require using a weak pointer and can potentially block
+ // destroying BookmarkImageService.
+ PersistentImageStore* store =
+ (PersistentImageStore*)::operator new(sizeof(PersistentImageStore));
+ store_.reset(store);
+ pool_->PostNamedSequencedWorkerTask(
+ kSequenceToken,
+ FROM_HERE,
+ base::Bind(&ConstructPersistentImageStore, store, path));
+}
+
+BookmarkImageService::~BookmarkImageService() {
+ DCHECK(CalledOnValidThread());
+ bookmark_model_->RemoveObserver(this);
+ pool_->PostNamedSequencedWorkerTask(
+ kSequenceToken,
+ FROM_HERE,
+ base::Bind(&DeleteImageStore, store_.release()));
+}
+
+void BookmarkImageService::SalientImageForUrl(const GURL& page_url,
+ Callback callback) {
+ DCHECK(CalledOnValidThread());
+ SalientImageForUrl(page_url, true, callback);
+}
+
+void BookmarkImageService::RetrieveImageFromStore(
+ const GURL& page_url,
+ BookmarkImageService::Callback callback) {
+ DCHECK(CalledOnValidThread());
+ pool_->PostSequencedWorkerTaskWithShutdownBehavior(
+ pool_->GetNamedSequenceToken(kSequenceToken),
+ FROM_HERE,
+ base::Bind(&RetrieveImageFromStoreRelay,
+ base::Unretained(store_.get()),
+ page_url,
+ callback,
+ base::ThreadTaskRunnerHandle::Get()),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+}
+
+void BookmarkImageService::RetrieveSalientImageForPageUrl(
+ const GURL& page_url) {
+ DCHECK(CalledOnValidThread());
+ if (IsPageUrlInProgress(page_url))
+ return; // A request for this URL is already in progress.
+
+ in_progress_page_urls_.insert(page_url);
+
+ const BookmarkNode* bookmark =
+ bookmark_model_->GetMostRecentlyAddedUserNodeForURL(page_url);
+ GURL image_url;
+ if (bookmark) {
+ int width;
+ int height;
+ enhanced_bookmarks::ThumbnailImageFromBookmark(
+ bookmark, &image_url, &width, &height);
+ }
+
+ RetrieveSalientImage(
+ page_url,
+ image_url,
+ "",
+ net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
wtc 2014/08/28 23:45:50 If we're passing a hardcoded value here, does Retr
noyau (Ping after 24h) 2014/08/29 08:44:01 RetrieveSalientImage() is protected and also calle
+ false);
+}
+
+void BookmarkImageService::FetchCallback(const GURL& page_url,
+ Callback original_callback,
+ const gfx::Image& image,
+ const GURL& image_url) {
+ DCHECK(CalledOnValidThread());
+ if (!image.IsEmpty() || !image_url.is_empty()) {
+ // Either the image was in the store or there is no image in the store, but
+ // an URL for an image is present, indicating that a previous attempt to
+ // download the image failed. Just return the image.
+ original_callback.Run(image, image_url);
+ } else {
+ // There is no image in the store, and no previous attempts to retrieve
+ // one. Start a request to retrieve a salient image if there is an image
+ // url set on a bookmark, and then enqueue the request for the image to
+ // be triggered when the retrieval is finished.
+ RetrieveSalientImageForPageUrl(page_url);
+ SalientImageForUrl(page_url, false, original_callback);
+ }
+}
+
+void BookmarkImageService::SalientImageForUrl(const GURL& page_url,
+ bool fetch_from_bookmark,
+ Callback callback) {
+ DCHECK(CalledOnValidThread());
+
+ // If the request is done while the image is currently being retrieved, just
+ // store the appropriate callbacks to call once the image is retrieved.
+ if (IsPageUrlInProgress(page_url)) {
+ callbacks_[page_url].push_back(callback);
+ return;
+ }
+
+ if (!fetch_from_bookmark) {
+ RetrieveImageFromStore(page_url, callback);
+ } else {
+ RetrieveImageFromStore(page_url,
+ base::Bind(&BookmarkImageService::FetchCallback,
+ base::Unretained(this),
+ page_url,
+ callback));
+ }
+}
+
+void BookmarkImageService::ProcessNewImage(const GURL& page_url,
+ bool update_bookmarks,
+ const gfx::Image& image,
+ const GURL& image_url) {
+ DCHECK(CalledOnValidThread());
+ StoreImage(image, image_url, page_url);
+ in_progress_page_urls_.erase(page_url);
+ ProcessRequests(page_url, image, image_url);
+ if (update_bookmarks && image_url.is_valid()) {
+ const BookmarkNode* bookmark =
+ bookmark_model_->GetMostRecentlyAddedUserNodeForURL(page_url);
+ if (bookmark) {
+ const gfx::Size& size = image.Size();
+ bool result = enhanced_bookmarks::SetOriginalImageForBookmark(
+ bookmark_model_, bookmark, image_url, size.width(), size.height());
+ DCHECK(result);
+ }
+ }
+}
+
+bool BookmarkImageService::IsPageUrlInProgress(const GURL& page_url) {
+ DCHECK(CalledOnValidThread());
+ return in_progress_page_urls_.find(page_url) != in_progress_page_urls_.end();
+}
+
+void BookmarkImageService::StoreImage(const gfx::Image& image,
+ const GURL& image_url,
+ const GURL& page_url) {
+ DCHECK(CalledOnValidThread());
+ if (!image.IsEmpty()) {
+ pool_->PostNamedSequencedWorkerTask(
+ kSequenceToken,
+ FROM_HERE,
+ base::Bind(&ImageStore::Insert,
+ base::Unretained(store_.get()),
+ page_url,
+ image_url,
+ image));
+ }
+}
+
+void BookmarkImageService::RemoveImageForUrl(const GURL& page_url) {
+ DCHECK(CalledOnValidThread());
+ pool_->PostNamedSequencedWorkerTask(
+ kSequenceToken,
+ FROM_HERE,
+ base::Bind(&ImageStore::Erase, base::Unretained(store_.get()), page_url));
+ in_progress_page_urls_.erase(page_url);
+ ProcessRequests(page_url, gfx::Image(), GURL());
+}
+
+void BookmarkImageService::ChangeImageURL(const GURL& from, const GURL& to) {
+ DCHECK(CalledOnValidThread());
+ pool_->PostNamedSequencedWorkerTask(kSequenceToken,
+ FROM_HERE,
+ base::Bind(&ImageStore::ChangeImageURL,
+ base::Unretained(store_.get()),
+ from,
+ to));
+ in_progress_page_urls_.erase(from);
+ ProcessRequests(from, gfx::Image(), GURL());
+}
+
+void BookmarkImageService::ClearAll() {
+ DCHECK(CalledOnValidThread());
+ // Clears and executes callbacks.
+ pool_->PostNamedSequencedWorkerTask(
+ kSequenceToken,
+ FROM_HERE,
+ base::Bind(&ImageStore::ClearAll, base::Unretained(store_.get())));
+
+ for (std::map<const GURL, std::vector<Callback> >::const_iterator it =
+ callbacks_.begin();
+ it != callbacks_.end();
+ ++it) {
+ ProcessRequests(it->first, gfx::Image(), GURL());
+ }
+
+ in_progress_page_urls_.erase(in_progress_page_urls_.begin(),
+ in_progress_page_urls_.end());
+}
+
+void BookmarkImageService::ProcessRequests(const GURL& page_url,
+ const gfx::Image& image,
+ const GURL& image_url) {
+ DCHECK(CalledOnValidThread());
+
+ std::vector<Callback> callbacks = callbacks_[page_url];
+ for (std::vector<Callback>::const_iterator it = callbacks.begin();
+ it != callbacks.end();
+ ++it) {
+ it->Run(image, image_url);
+ }
+
+ callbacks_.erase(page_url);
+}
+
+// BookmarkModelObserver methods.
+
+void BookmarkImageService::BookmarkNodeRemoved(
+ BookmarkModel* model,
+ const BookmarkNode* parent,
+ int old_index,
+ const BookmarkNode* node,
+ const std::set<GURL>& removed_urls) {
+ DCHECK(CalledOnValidThread());
+ for (std::set<GURL>::const_iterator iter = removed_urls.begin();
+ iter != removed_urls.end();
+ ++iter) {
+ RemoveImageForUrl(*iter);
+ }
+}
+
+void BookmarkImageService::BookmarkModelLoaded(BookmarkModel* model,
+ bool ids_reassigned) {
+}
+
+void BookmarkImageService::BookmarkNodeMoved(BookmarkModel* model,
+ const BookmarkNode* old_parent,
+ int old_index,
+ const BookmarkNode* new_parent,
+ int new_index) {
+}
+
+void BookmarkImageService::BookmarkNodeAdded(BookmarkModel* model,
+ const BookmarkNode* parent,
+ int index) {
+}
+
+void BookmarkImageService::OnWillChangeBookmarkNode(BookmarkModel* model,
+ const BookmarkNode* node) {
+ DCHECK(CalledOnValidThread());
+ if (node->is_url())
+ previous_url_ = node->url();
+}
+
+void BookmarkImageService::BookmarkNodeChanged(BookmarkModel* model,
+ const BookmarkNode* node) {
+ DCHECK(CalledOnValidThread());
+ if (node->is_url() && previous_url_ != node->url())
+ ChangeImageURL(previous_url_, node->url());
+}
+
+void BookmarkImageService::BookmarkNodeFaviconChanged(
+ BookmarkModel* model,
+ const BookmarkNode* node) {
+}
+
+void BookmarkImageService::BookmarkNodeChildrenReordered(
+ BookmarkModel* model,
+ const BookmarkNode* node) {
+}
+
+void BookmarkImageService::BookmarkAllUserNodesRemoved(
+ BookmarkModel* model,
+ const std::set<GURL>& removed_urls) {
+ ClearAll();
+}
+
+} // namespace enhanced_bookmarks
« no previous file with comments | « components/enhanced_bookmarks/bookmark_image_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698