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

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..7f34d1cc8d3958e2e6371c72da145122ab89f7f9
--- /dev/null
+++ b/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc
@@ -0,0 +1,383 @@
+// 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;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ if (string_id.empty())
+ return false;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Is your preference to have blank lines between dif
Evan Stade 2012/08/15 00:05:10 really I just want there to be more vertical spaci
+ if (StartsWithASCII(string_id, "p", true)) {
+ *out_is_partner = true;
+ return base::StringToInt64(string_id.substr(1), out_id);
+ } else {
Evan Stade 2012/08/15 00:05:10 you don't need this else because the if has a retu
Ted C 2012/08/15 21:21:00 Done.
+ *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),
+ extensive_changes_(false),
+ creating_shortcut_(false) {
+}
+
+BookmarksHandler::~BookmarksHandler() {
+ if (bookmark_model_)
+ bookmark_model_->RemoveObserver(this);
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ 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();
+ }
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ // 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("shortcutToBookmark",
+ base::Bind(&BookmarksHandler::HandleShortcutToBookmark,
+ base::Unretained(this)));
+}
+
+void BookmarksHandler::HandleGetBookmarks(const ListValue* args) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ 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_)
Evan Stade 2012/08/15 00:05:10 curlies are required if the contents of the condit
Ted C 2012/08/15 21:21:00 Done.
+ 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) {
+ if (partner_bookmarks_shim_->IsPartnerBookmark(node))
+ return "p" + Int64ToString(node->id());
Evan Stade 2012/08/15 00:05:10 ternary operator here: return (partner ? "p" : ""
Ted C 2012/08/15 21:21:00 Done.
+ return 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;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ 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,
+ const scoped_ptr<DictionaryValue>& result) {
+ scoped_ptr<ListValue> bookmarks(new ListValue);
+
+ for (int i = 0; i < folder->child_count(); i++) {
+ const BookmarkNode* bookmark=
+ (const BookmarkNode*) folder->GetChild(i);
+ PopulateBookmark(bookmark, bookmarks.get());
+ }
+
+ // 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())
Evan Stade 2012/08/14 22:04:54 curlies
Ted C 2012/08/14 23:24:28 Done.
+ PopulateBookmark(
+ partner_bookmarks_shim_->GetPartnerBookmarksRoot(), bookmarks.get());
+
+ scoped_ptr<ListValue> folder_hierarchy(new ListValue);
+ const BookmarkNode* parent = partner_bookmarks_shim_->GetParentOf(folder);
+
+ while (parent != NULL) {
+ scoped_ptr<DictionaryValue> hierarchy_entry(new DictionaryValue);
+ if (partner_bookmarks_shim_->IsRootNode(parent))
+ hierarchy_entry->SetBoolean("root", true);
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ hierarchy_entry->SetString("title", parent->GetTitle());
+ hierarchy_entry->SetString("id", GetBookmarkIdForNtp(parent));
+ folder_hierarchy->Append(hierarchy_entry.release());
+ 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.release());
+ result->Set("hierarchy", folder_hierarchy.release());
+}
+
+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) {
+ scoped_ptr<DictionaryValue> result(new DictionaryValue);
+ 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() {
+ scoped_ptr<DictionaryValue> result(new DictionaryValue);
+ 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 scoped_ptr<DictionaryValue>& result) {
+ if (result.get())
+ web_ui()->CallJavascriptFunction("ntp.bookmarks", *(result.get()));
+}
+
+void BookmarksHandler::Loaded(BookmarkModel* model,
+ bool ids_reassigned) {
+ BookmarkModelChanged();
Evan Stade 2012/08/14 22:04:54 the NTP may not be ready yet. This should not do a
Ted C 2012/08/14 23:24:28 Added a flag to track whether get has been called
+}
+
+void BookmarksHandler::PartnerShimLoaded(PartnerBookmarksShim* shim) {
+ BookmarkModelChanged();
Evan Stade 2012/08/14 22:04:54 ditto (I guess)
+}
+
+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) {
+ scoped_ptr<DictionaryValue> result(new DictionaryValue);
+ SetParentInBookmarksResult(*parent, result.get());
+ result->SetString(kNodeIdParam, Int64ToString(node->id()));
+ NotifyModelChanged(*(result.get()));
Evan Stade 2012/08/14 22:04:54 you can just do *result however, I don't understa
Ted C 2012/08/14 23:24:28 Done.
+}
+
+void BookmarksHandler::BookmarkNodeAdded(BookmarkModel* model,
+ const BookmarkNode* parent,
+ int index) {
+ scoped_ptr<DictionaryValue> result(new DictionaryValue);
+ SetParentInBookmarksResult(*parent, result.get());
+ NotifyModelChanged(*(result.get()));
+}
+
+void BookmarksHandler::BookmarkNodeChanged(BookmarkModel* model,
+ const BookmarkNode* node) {
+ scoped_ptr<DictionaryValue> result(new DictionaryValue);
+ DCHECK(partner_bookmarks_shim_ != NULL);
Evan Stade 2012/08/14 22:04:54 no need for !=
Ted C 2012/08/14 23:24:28 Done.
+ DCHECK(!partner_bookmarks_shim_->IsPartnerBookmark(node));
Evan Stade 2012/08/14 22:04:54 DCHECKS go at very beginning.
Ted C 2012/08/14 23:24:28 Done.
+ SetParentInBookmarksResult(*(node->parent()), result.get());
+ result->SetString(kNodeIdParam, Int64ToString(node->id()));
+ NotifyModelChanged(*(result.get()));
+}
+
+void BookmarksHandler::BookmarkModelChanged() {
+ if (!extensive_changes_)
+ web_ui()->CallJavascriptFunction("ntp.bookmarkChanged");
+}
+
+void BookmarksHandler::NotifyModelChanged(const DictionaryValue& status) {
+ if (!extensive_changes_)
+ web_ui()->CallJavascriptFunction("ntp.bookmarkChanged", status);
+}
+
+void BookmarksHandler::HandleShortcutToBookmark(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);
+ BookmarkNode* node = const_cast<BookmarkNode*>(
+ partner_bookmarks_shim_->GetNodeByID(id, is_partner));
+ if (!node)
+ return;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ creating_shortcut_ = true;
+ 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::OnFaviconDataAvailable,
+ base::Unretained(this)));
+ cancelable_consumer_.SetClientData(favicon_service, handle, node);
+ }
+}
+
+void BookmarksHandler::OnFaviconDataAvailable(
+ FaviconService::Handle handle,
+ history::FaviconData favicon) {
+ if (!creating_shortcut_)
+ return;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ 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);
+ }
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
+ Profile* profile = Profile::FromBrowserContext(
+ web_ui()->GetWebContents()->GetBrowserContext());
+ BookmarkNode* node = cancelable_consumer_.GetClientData(
+ profile->GetFaviconService(Profile::EXPLICIT_ACCESS), handle);
+
+ TabAndroid* tab = TabAndroid::FromWebContents(
+ web_ui()->GetWebContents());
+ if (tab)
Evan Stade 2012/08/14 22:04:54 curlies
Ted C 2012/08/14 23:24:28 Done.
+ tab->AddShortcutToBookmark(node->url(), node->GetTitle(),
+ favicon_bitmap, SkColorGetR(color),
+ SkColorGetG(color), SkColorGetB(color));
+ creating_shortcut_ = false;
+}
« 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