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

Unified Diff: chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc

Issue 10829326: Add the webui handler for Android's bookmark section on the NTP. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 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 | « chrome/browser/ui/webui/ntp/android/bookmarks_handler.h ('k') | chrome/browser/ui/webui/ntp/new_tab_ui.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc
diff --git a/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc b/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dab968276526f735aaebf6989b0afa97cf64065e
--- /dev/null
+++ b/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc
@@ -0,0 +1,389 @@
+// Copyright (c) 2012 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 "chrome/browser/ui/webui/ntp/android/bookmarks_handler.h"
+
+#include "base/logging.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "chrome/browser/android/tab_android.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
+#include "chrome/browser/ui/webui/favicon_source.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/color_analysis.h"
+
+using base::Int64ToString;
+using content::BrowserThread;
+
+namespace {
+
+static const char* kParentIdParam = "parent_id";
+static const char* kNodeIdParam = "node_id";
+
+// Parses a bookmark ID passed back from the NTP. The IDs differ from the
+// normal int64 bookmark ID because we prepend a "p" if the ID represents a
+// partner bookmark.
+bool ParseNtpBookmarkId(const ListValue* args,
+ int64* out_id,
+ bool* out_is_partner) {
+ std::string string_id;
+ if (!args->GetString(0, &string_id))
+ return false;
+
+ if (string_id.empty())
+ return false;
+
+ if (StartsWithASCII(string_id, "p", true)) {
+ *out_is_partner = true;
+ return base::StringToInt64(string_id.substr(1), out_id);
+ }
+
+ *out_is_partner = false;
+ return base::StringToInt64(string_id, out_id);
+}
+
+std::string BookmarkTypeAsString(BookmarkNode::Type type) {
+ switch (type) {
+ case BookmarkNode::URL:
+ return "URL";
+ case BookmarkNode::FOLDER:
+ return "FOLDER";
+ case BookmarkNode::BOOKMARK_BAR:
+ return "BOOKMARK_BAR";
+ case BookmarkNode::OTHER_NODE:
+ return "OTHER_NODE";
+ case BookmarkNode::MOBILE:
+ return "MOBILE";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+SkColor GetDominantColorForFavicon(scoped_refptr<base::RefCountedMemory> png) {
+ color_utils::GridSampler sampler;
+ // 100 here is the darkness_limit which represents the minimum sum of the RGB
+ // components that is acceptable as a color choice. This can be from 0 to 765.
+ // 665 here is the brightness_limit represents the maximum sum of the RGB
+ // components that is acceptable as a color choice. This can be from 0 to 765.
+ return color_utils::CalculateKMeanColorOfPNG(png, 100, 665, sampler);
+}
+
+} // namespace
+
+BookmarksHandler::BookmarksHandler()
+ : bookmark_model_(NULL),
+ partner_bookmarks_shim_(NULL),
+ bookmark_data_requested_(false),
+ extensive_changes_(false) {
+}
+
+BookmarksHandler::~BookmarksHandler() {
+ if (bookmark_model_)
+ bookmark_model_->RemoveObserver(this);
+
+ if (partner_bookmarks_shim_)
+ partner_bookmarks_shim_->RemoveObserver(this);
+}
+
+void BookmarksHandler::RegisterMessages() {
+ // Listen for the bookmark change. We need the both bookmark and folder
+ // change, the NotificationService is not sufficient.
+ Profile* profile = Profile::FromBrowserContext(
+ web_ui()->GetWebContents()->GetBrowserContext());
+
+ ChromeURLDataManager::AddDataSource(profile,
+ new FaviconSource(profile, FaviconSource::ANY));
+
+ bookmark_model_ = BookmarkModelFactory::GetForProfile(profile);
+ if (bookmark_model_) {
+ bookmark_model_->AddObserver(this);
+ // Since a sync or import could have started before this class is
+ // initialized, we need to make sure that our initial state is
+ // up to date.
+ extensive_changes_ = bookmark_model_->IsDoingExtensiveChanges();
+ }
+
+ // Create the partner Bookmarks shim as early as possible (but don't attach).
+ if (!partner_bookmarks_shim_) {
+ partner_bookmarks_shim_ = PartnerBookmarksShim::GetInstance();
+ partner_bookmarks_shim_->AddObserver(this);
+ }
+
+ // Register ourselves as the handler for the bookmark javascript callbacks.
+ web_ui()->RegisterMessageCallback("getBookmarks",
+ base::Bind(&BookmarksHandler::HandleGetBookmarks,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback("deleteBookmark",
+ base::Bind(&BookmarksHandler::HandleDeleteBookmark,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback("createHomeScreenBookmarkShortcut",
+ base::Bind(&BookmarksHandler::HandleCreateHomeScreenBookmarkShortcut,
+ base::Unretained(this)));
+}
+
+void BookmarksHandler::HandleGetBookmarks(const ListValue* args) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ bookmark_data_requested_ = true;
+ Profile* profile = Profile::FromBrowserContext(
+ web_ui()->GetWebContents()->GetBrowserContext());
+ if (!BookmarkModelFactory::GetForProfile(profile)->IsLoaded())
+ return; // is handled in Loaded().
+
+ // Attach the Partner Bookmarks shim under the Mobile Bookmarks.
+ // Cannot do this earlier because mobile_node is not yet set.
+ DCHECK(partner_bookmarks_shim_ != NULL);
+ if (bookmark_model_) {
+ partner_bookmarks_shim_->AttachTo(
+ bookmark_model_, bookmark_model_->mobile_node());
+ }
+ if (!partner_bookmarks_shim_->IsLoaded())
+ return; // is handled with a PartnerShimLoaded() callback
+
+ int64 id;
+ bool is_partner;
+ if (args && !args->empty() && ParseNtpBookmarkId(args, &id, &is_partner))
+ QueryBookmarkFolder(id, is_partner);
+ else
+ QueryInitialBookmarks();
+}
+
+void BookmarksHandler::HandleDeleteBookmark(const ListValue* args) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ int64 id;
+ bool is_partner;
+ if (args && !args->empty() && ParseNtpBookmarkId(args, &id, &is_partner)) {
+ DCHECK(!is_partner);
+ const BookmarkNode* node = bookmark_model_->GetNodeByID(id);
+ if (node && node->parent()) {
+ const BookmarkNode* parent_node = node->parent();
+ bookmark_model_->Remove(parent_node, parent_node->GetIndexOf(node));
+ }
+ }
+}
+
+std::string BookmarksHandler::GetBookmarkIdForNtp(const BookmarkNode* node) {
+ return (partner_bookmarks_shim_->IsPartnerBookmark(node) ? "p" : "") +
+ Int64ToString(node->id());
+}
+
+void BookmarksHandler::SetParentInBookmarksResult(const BookmarkNode* parent,
+ DictionaryValue* result) {
+ result->SetString(kParentIdParam, GetBookmarkIdForNtp(parent));
+}
+
+void BookmarksHandler::PopulateBookmark(const BookmarkNode* node,
+ ListValue* result) {
+ if (!result)
+ return;
+
+ DictionaryValue* filler_value = new DictionaryValue();
+ filler_value->SetString("title", node->GetTitle());
+ // Mark reserved system nodes and partner bookmarks as uneditable
+ // (i.e. the bookmark bar along with the "Other Bookmarks" folder).
+ filler_value->SetBoolean("editable",
+ partner_bookmarks_shim_->IsBookmarkEditable(node));
+ if (node->is_url()) {
+ filler_value->SetBoolean("folder", false);
+ filler_value->SetString("url", node->url().spec());
+ } else {
+ filler_value->SetBoolean("folder", true);
+ }
+ filler_value->SetString("id", GetBookmarkIdForNtp(node));
+ filler_value->SetString("type", BookmarkTypeAsString(node->type()));
+ result->Append(filler_value);
+}
+
+void BookmarksHandler::PopulateBookmarksInFolder(
+ const BookmarkNode* folder,
+ DictionaryValue* result) {
+ ListValue* bookmarks = new ListValue();
+
+ for (int i = 0; i < folder->child_count(); i++) {
+ const BookmarkNode* bookmark= folder->GetChild(i);
+ PopulateBookmark(bookmark, bookmarks);
+ }
+
+ // Make sure we iterate over the partner's attach point
+ DCHECK(partner_bookmarks_shim_ != NULL);
+ if (partner_bookmarks_shim_->HasPartnerBookmarks() &&
+ folder == partner_bookmarks_shim_->get_attach_point()) {
+ PopulateBookmark(
+ partner_bookmarks_shim_->GetPartnerBookmarksRoot(), bookmarks);
+ }
+
+ ListValue* folder_hierarchy = new ListValue();
+ const BookmarkNode* parent = partner_bookmarks_shim_->GetParentOf(folder);
+
+ while (parent != NULL) {
+ DictionaryValue* hierarchy_entry = new DictionaryValue();
+ if (partner_bookmarks_shim_->IsRootNode(parent))
+ hierarchy_entry->SetBoolean("root", true);
+
+ hierarchy_entry->SetString("title", parent->GetTitle());
+ hierarchy_entry->SetString("id", GetBookmarkIdForNtp(parent));
+ folder_hierarchy->Append(hierarchy_entry);
+ parent = partner_bookmarks_shim_->GetParentOf(parent);
+ }
+
+ result->SetString("title", folder->GetTitle());
+ result->SetString("id", GetBookmarkIdForNtp(folder));
+ result->SetBoolean("root", partner_bookmarks_shim_->IsRootNode(folder));
+ result->Set("bookmarks", bookmarks);
+ result->Set("hierarchy", folder_hierarchy);
+}
+
+void BookmarksHandler::QueryBookmarkFolder(const int64& folder_id,
+ bool is_partner_bookmark) {
+ DCHECK(partner_bookmarks_shim_ != NULL);
+ const BookmarkNode* bookmarks =
+ partner_bookmarks_shim_->GetNodeByID(folder_id, is_partner_bookmark);
+ if (bookmarks) {
+ DictionaryValue result;
+ PopulateBookmarksInFolder(bookmarks, &result);
+ SendResult(result);
+ } else {
+ // If we receive an ID that no longer maps to a bookmark folder, just
+ // return the initial bookmark folder.
+ QueryInitialBookmarks();
+ }
+}
+
+void BookmarksHandler::QueryInitialBookmarks() {
+ DictionaryValue result;
+ DCHECK(partner_bookmarks_shim_ != NULL);
+ PopulateBookmarksInFolder(
+ // We have to go to the partner Root if it exists
+ partner_bookmarks_shim_->HasPartnerBookmarks() ?
+ partner_bookmarks_shim_->GetPartnerBookmarksRoot() :
+ bookmark_model_->mobile_node(),
+ &result);
+ SendResult(result);
+}
+
+void BookmarksHandler::SendResult(const DictionaryValue& result) {
+ web_ui()->CallJavascriptFunction("ntp.bookmarks", result);
+}
+
+void BookmarksHandler::Loaded(BookmarkModel* model, bool ids_reassigned) {
+ BookmarkModelChanged();
+}
+
+void BookmarksHandler::PartnerShimLoaded(PartnerBookmarksShim* shim) {
+ BookmarkModelChanged();
+}
+
+void BookmarksHandler::ShimBeingDeleted(PartnerBookmarksShim* shim) {
+ partner_bookmarks_shim_ = NULL;
+}
+
+void BookmarksHandler::ExtensiveBookmarkChangesBeginning(BookmarkModel* model) {
+ extensive_changes_ = true;
+}
+
+void BookmarksHandler::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
+ extensive_changes_ = false;
+ BookmarkModelChanged();
+}
+
+void BookmarksHandler::BookmarkNodeRemoved(BookmarkModel* model,
+ const BookmarkNode* parent,
+ int old_index,
+ const BookmarkNode* node) {
+ DictionaryValue result;
+ SetParentInBookmarksResult(parent, &result);
+ result.SetString(kNodeIdParam, Int64ToString(node->id()));
+ NotifyModelChanged(result);
+}
+
+void BookmarksHandler::BookmarkNodeAdded(BookmarkModel* model,
+ const BookmarkNode* parent,
+ int index) {
+ DictionaryValue result;
+ SetParentInBookmarksResult(parent, &result);
+ NotifyModelChanged(result);
+}
+
+void BookmarksHandler::BookmarkNodeChanged(BookmarkModel* model,
+ const BookmarkNode* node) {
+ DCHECK(partner_bookmarks_shim_);
+ DCHECK(!partner_bookmarks_shim_->IsPartnerBookmark(node));
+ DictionaryValue result;
+ SetParentInBookmarksResult(node->parent(), &result);
+ result.SetString(kNodeIdParam, Int64ToString(node->id()));
+ NotifyModelChanged(result);
+}
+
+void BookmarksHandler::BookmarkModelChanged() {
+ if (bookmark_data_requested_ && !extensive_changes_)
+ web_ui()->CallJavascriptFunction("ntp.bookmarkChanged");
+}
+
+void BookmarksHandler::NotifyModelChanged(const DictionaryValue& status) {
+ if (bookmark_data_requested_ && !extensive_changes_)
+ web_ui()->CallJavascriptFunction("ntp.bookmarkChanged", status);
+}
+
+void BookmarksHandler::HandleCreateHomeScreenBookmarkShortcut(
+ const ListValue* args) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ Profile* profile = Profile::FromBrowserContext(
+ web_ui()->GetWebContents()->GetBrowserContext());
+ if (!profile)
+ return;
+
+ int64 id;
+ bool is_partner;
+ if (args && !args->empty() && ParseNtpBookmarkId(args, &id, &is_partner)) {
+ DCHECK(partner_bookmarks_shim_ != NULL);
+ const BookmarkNode* node =
+ partner_bookmarks_shim_->GetNodeByID(id, is_partner);
+ if (!node)
+ return;
+
+ FaviconService* favicon_service = profile->GetFaviconService(
+ Profile::EXPLICIT_ACCESS);
+ FaviconService::Handle handle = favicon_service->GetFaviconForURL(
+ node->url(),
+ history::FAVICON | history::TOUCH_ICON,
+ &cancelable_consumer_,
+ base::Bind(&BookmarksHandler::OnShortcutFaviconDataAvailable,
+ base::Unretained(this)));
+ cancelable_consumer_.SetClientData(favicon_service, handle, node);
+ }
+}
+
+void BookmarksHandler::OnShortcutFaviconDataAvailable(
+ FaviconService::Handle handle,
+ history::FaviconData favicon) {
+ SkColor color = SK_ColorWHITE;
+ SkBitmap favicon_bitmap;
+ if (favicon.is_valid()) {
+ color = GetDominantColorForFavicon(favicon.image_data);
+ gfx::PNGCodec::Decode(favicon.image_data->front(),
+ favicon.image_data->size(),
+ &favicon_bitmap);
+ }
+
+ Profile* profile = Profile::FromBrowserContext(
+ web_ui()->GetWebContents()->GetBrowserContext());
+ const BookmarkNode* node = cancelable_consumer_.GetClientData(
+ profile->GetFaviconService(Profile::EXPLICIT_ACCESS), handle);
+
+ TabAndroid* tab = TabAndroid::FromWebContents(
+ web_ui()->GetWebContents());
+ if (tab) {
+ tab->AddShortcutToBookmark(node->url(), node->GetTitle(),
+ favicon_bitmap, SkColorGetR(color),
+ SkColorGetG(color), SkColorGetB(color));
+ }
+}
« no previous file with comments | « chrome/browser/ui/webui/ntp/android/bookmarks_handler.h ('k') | chrome/browser/ui/webui/ntp/new_tab_ui.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698