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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/webui/ntp/android/bookmarks_handler.h"
6
7 #include "base/logging.h"
8 #include "base/memory/ref_counted_memory.h"
9 #include "base/string_number_conversions.h"
10 #include "base/string_util.h"
11 #include "chrome/browser/android/tab_android.h"
12 #include "chrome/browser/bookmarks/bookmark_model.h"
13 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
17 #include "chrome/browser/ui/webui/favicon_source.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/web_contents.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "ui/gfx/codec/png_codec.h"
22 #include "ui/gfx/color_analysis.h"
23
24 using base::Int64ToString;
25 using content::BrowserThread;
26
27 namespace {
28
29 static const char* kParentIdParam = "parent_id";
30 static const char* kNodeIdParam = "node_id";
31
32 // Parses a bookmark ID passed back from the NTP. The IDs differ from the
33 // normal int64 bookmark ID because we prepend a "p" if the ID represents a
34 // partner bookmark.
35 bool ParseNtpBookmarkId(const ListValue* args,
36 int64* out_id,
37 bool* out_is_partner) {
38 std::string string_id;
39 if (!args->GetString(0, &string_id))
40 return false;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
41 if (string_id.empty())
42 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
43 if (StartsWithASCII(string_id, "p", true)) {
44 *out_is_partner = true;
45 return base::StringToInt64(string_id.substr(1), out_id);
46 } 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.
47 *out_is_partner = false;
48 return base::StringToInt64(string_id, out_id);
49 }
50 }
51
52 std::string BookmarkTypeAsString(BookmarkNode::Type type) {
53 switch (type) {
54 case BookmarkNode::URL:
55 return "URL";
56 case BookmarkNode::FOLDER:
57 return "FOLDER";
58 case BookmarkNode::BOOKMARK_BAR:
59 return "BOOKMARK_BAR";
60 case BookmarkNode::OTHER_NODE:
61 return "OTHER_NODE";
62 case BookmarkNode::MOBILE:
63 return "MOBILE";
64 default:
65 return "UNKNOWN";
66 }
67 }
68
69 SkColor GetDominantColorForFavicon(scoped_refptr<base::RefCountedMemory> png) {
70 color_utils::GridSampler sampler;
71 // 100 here is the darkness_limit which represents the minimum sum of the RGB
72 // components that is acceptable as a color choice. This can be from 0 to 765.
73 // 665 here is the brightness_limit represents the maximum sum of the RGB
74 // components that is acceptable as a color choice. This can be from 0 to 765.
75 return color_utils::CalculateKMeanColorOfPNG(png, 100, 665, sampler);
76 }
77
78 } // namespace
79
80 BookmarksHandler::BookmarksHandler()
81 : bookmark_model_(NULL),
82 partner_bookmarks_shim_(NULL),
83 extensive_changes_(false),
84 creating_shortcut_(false) {
85 }
86
87 BookmarksHandler::~BookmarksHandler() {
88 if (bookmark_model_)
89 bookmark_model_->RemoveObserver(this);
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
90 if (partner_bookmarks_shim_)
91 partner_bookmarks_shim_->RemoveObserver(this);
92 }
93
94 void BookmarksHandler::RegisterMessages() {
95 // Listen for the bookmark change. We need the both bookmark and folder
96 // change, the NotificationService is not sufficient.
97 Profile* profile = Profile::FromBrowserContext(
98 web_ui()->GetWebContents()->GetBrowserContext());
99
100 ChromeURLDataManager::AddDataSource(profile,
101 new FaviconSource(profile, FaviconSource::ANY));
102
103 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile);
104 if (bookmark_model_) {
105 bookmark_model_->AddObserver(this);
106 // Since a sync or import could have started before this class is
107 // initialized, we need to make sure that our initial state is
108 // up to date.
109 extensive_changes_ = bookmark_model_->IsDoingExtensiveChanges();
110 }
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
111 // Create the partner Bookmarks shim as early as possible (but don't attach).
112 if (!partner_bookmarks_shim_) {
113 partner_bookmarks_shim_ = PartnerBookmarksShim::GetInstance();
114 partner_bookmarks_shim_->AddObserver(this);
115 }
116
117 // Register ourselves as the handler for the bookmark javascript callbacks.
118 web_ui()->RegisterMessageCallback("getBookmarks",
119 base::Bind(&BookmarksHandler::HandleGetBookmarks,
120 base::Unretained(this)));
121 web_ui()->RegisterMessageCallback("deleteBookmark",
122 base::Bind(&BookmarksHandler::HandleDeleteBookmark,
123 base::Unretained(this)));
124 web_ui()->RegisterMessageCallback("shortcutToBookmark",
125 base::Bind(&BookmarksHandler::HandleShortcutToBookmark,
126 base::Unretained(this)));
127 }
128
129 void BookmarksHandler::HandleGetBookmarks(const ListValue* args) {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
131 Profile* profile = Profile::FromBrowserContext(
132 web_ui()->GetWebContents()->GetBrowserContext());
133 if (!BookmarkModelFactory::GetForProfile(profile)->IsLoaded())
134 return; // is handled in Loaded().
135
136 // Attach the Partner Bookmarks shim under the Mobile Bookmarks.
137 // Cannot do this earlier because mobile_node is not yet set.
138 DCHECK(partner_bookmarks_shim_ != NULL);
139 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.
140 partner_bookmarks_shim_->AttachTo(
141 bookmark_model_, bookmark_model_->mobile_node());
142 if (!partner_bookmarks_shim_->IsLoaded())
143 return; // is handled with a PartnerShimLoaded() callback
144
145 int64 id;
146 bool is_partner;
147 if (args && !args->empty() && ParseNtpBookmarkId(args, &id, &is_partner))
148 QueryBookmarkFolder(id, is_partner);
149 else
150 QueryInitialBookmarks();
151 }
152
153 void BookmarksHandler::HandleDeleteBookmark(const ListValue* args) {
154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
155 int64 id;
156 bool is_partner;
157 if (args && !args->empty() && ParseNtpBookmarkId(args, &id, &is_partner)) {
158 DCHECK(!is_partner);
159 const BookmarkNode* node = bookmark_model_->GetNodeByID(id);
160 if (node && node->parent()) {
161 const BookmarkNode* parent_node = node->parent();
162 bookmark_model_->Remove(parent_node, parent_node->GetIndexOf(node));
163 }
164 }
165 }
166
167 std::string BookmarksHandler::GetBookmarkIdForNtp(const BookmarkNode* node) {
168 if (partner_bookmarks_shim_->IsPartnerBookmark(node))
169 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.
170 return Int64ToString(node->id());
171 }
172
173 void BookmarksHandler::SetParentInBookmarksResult(const BookmarkNode& parent,
174 DictionaryValue* result) {
175 result->SetString(kParentIdParam, GetBookmarkIdForNtp(&parent));
176 }
177
178 void BookmarksHandler::PopulateBookmark(const BookmarkNode* node,
179 ListValue* result) {
180 if (!result)
181 return;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
182 DictionaryValue* filler_value = new DictionaryValue();
183 filler_value->SetString("title", node->GetTitle());
184 // Mark reserved system nodes and partner bookmarks as uneditable
185 // (i.e. the bookmark bar along with the "Other Bookmarks" folder).
186 filler_value->SetBoolean("editable",
187 partner_bookmarks_shim_->IsBookmarkEditable(node));
188 if (node->is_url()) {
189 filler_value->SetBoolean("folder", false);
190 filler_value->SetString("url", node->url().spec());
191 } else {
192 filler_value->SetBoolean("folder", true);
193 }
194 filler_value->SetString("id", GetBookmarkIdForNtp(node));
195 filler_value->SetString("type", BookmarkTypeAsString(node->type()));
196 result->Append(filler_value);
197 }
198
199 void BookmarksHandler::PopulateBookmarksInFolder(
200 const BookmarkNode* folder,
201 const scoped_ptr<DictionaryValue>& result) {
202 scoped_ptr<ListValue> bookmarks(new ListValue);
203
204 for (int i = 0; i < folder->child_count(); i++) {
205 const BookmarkNode* bookmark=
206 (const BookmarkNode*) folder->GetChild(i);
207 PopulateBookmark(bookmark, bookmarks.get());
208 }
209
210 // Make sure we iterate over the partner's attach point
211 DCHECK(partner_bookmarks_shim_ != NULL);
212 if (partner_bookmarks_shim_->HasPartnerBookmarks() &&
213 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.
214 PopulateBookmark(
215 partner_bookmarks_shim_->GetPartnerBookmarksRoot(), bookmarks.get());
216
217 scoped_ptr<ListValue> folder_hierarchy(new ListValue);
218 const BookmarkNode* parent = partner_bookmarks_shim_->GetParentOf(folder);
219
220 while (parent != NULL) {
221 scoped_ptr<DictionaryValue> hierarchy_entry(new DictionaryValue);
222 if (partner_bookmarks_shim_->IsRootNode(parent))
223 hierarchy_entry->SetBoolean("root", true);
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
224 hierarchy_entry->SetString("title", parent->GetTitle());
225 hierarchy_entry->SetString("id", GetBookmarkIdForNtp(parent));
226 folder_hierarchy->Append(hierarchy_entry.release());
227 parent = partner_bookmarks_shim_->GetParentOf(parent);
228 }
229
230 result->SetString("title", folder->GetTitle());
231 result->SetString("id", GetBookmarkIdForNtp(folder));
232 result->SetBoolean("root", partner_bookmarks_shim_->IsRootNode(folder));
233 result->Set("bookmarks", bookmarks.release());
234 result->Set("hierarchy", folder_hierarchy.release());
235 }
236
237 void BookmarksHandler::QueryBookmarkFolder(const int64& folder_id,
238 bool is_partner_bookmark) {
239 DCHECK(partner_bookmarks_shim_ != NULL);
240 const BookmarkNode* bookmarks =
241 partner_bookmarks_shim_->GetNodeByID(folder_id, is_partner_bookmark);
242 if (bookmarks) {
243 scoped_ptr<DictionaryValue> result(new DictionaryValue);
244 PopulateBookmarksInFolder(bookmarks, result);
245 SendResult(result);
246 } else {
247 // If we receive an ID that no longer maps to a bookmark folder, just
248 // return the initial bookmark folder.
249 QueryInitialBookmarks();
250 }
251 }
252
253 void BookmarksHandler::QueryInitialBookmarks() {
254 scoped_ptr<DictionaryValue> result(new DictionaryValue);
255 DCHECK(partner_bookmarks_shim_ != NULL);
256 PopulateBookmarksInFolder(
257 // We have to go to the partner Root if it exists
258 partner_bookmarks_shim_->HasPartnerBookmarks() ?
259 partner_bookmarks_shim_->GetPartnerBookmarksRoot() :
260 bookmark_model_->mobile_node(),
261 result);
262 SendResult(result);
263 }
264
265 void BookmarksHandler::SendResult(const scoped_ptr<DictionaryValue>& result) {
266 if (result.get())
267 web_ui()->CallJavascriptFunction("ntp.bookmarks", *(result.get()));
268 }
269
270 void BookmarksHandler::Loaded(BookmarkModel* model,
271 bool ids_reassigned) {
272 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
273 }
274
275 void BookmarksHandler::PartnerShimLoaded(PartnerBookmarksShim* shim) {
276 BookmarkModelChanged();
Evan Stade 2012/08/14 22:04:54 ditto (I guess)
277 }
278
279 void BookmarksHandler::ShimBeingDeleted(PartnerBookmarksShim* shim) {
280 partner_bookmarks_shim_ = NULL;
281 }
282
283 void BookmarksHandler::ExtensiveBookmarkChangesBeginning(BookmarkModel* model) {
284 extensive_changes_ = true;
285 }
286
287 void BookmarksHandler::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
288 extensive_changes_ = false;
289 BookmarkModelChanged();
290 }
291
292 void BookmarksHandler::BookmarkNodeRemoved(BookmarkModel* model,
293 const BookmarkNode* parent,
294 int old_index,
295 const BookmarkNode* node) {
296 scoped_ptr<DictionaryValue> result(new DictionaryValue);
297 SetParentInBookmarksResult(*parent, result.get());
298 result->SetString(kNodeIdParam, Int64ToString(node->id()));
299 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.
300 }
301
302 void BookmarksHandler::BookmarkNodeAdded(BookmarkModel* model,
303 const BookmarkNode* parent,
304 int index) {
305 scoped_ptr<DictionaryValue> result(new DictionaryValue);
306 SetParentInBookmarksResult(*parent, result.get());
307 NotifyModelChanged(*(result.get()));
308 }
309
310 void BookmarksHandler::BookmarkNodeChanged(BookmarkModel* model,
311 const BookmarkNode* node) {
312 scoped_ptr<DictionaryValue> result(new DictionaryValue);
313 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.
314 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.
315 SetParentInBookmarksResult(*(node->parent()), result.get());
316 result->SetString(kNodeIdParam, Int64ToString(node->id()));
317 NotifyModelChanged(*(result.get()));
318 }
319
320 void BookmarksHandler::BookmarkModelChanged() {
321 if (!extensive_changes_)
322 web_ui()->CallJavascriptFunction("ntp.bookmarkChanged");
323 }
324
325 void BookmarksHandler::NotifyModelChanged(const DictionaryValue& status) {
326 if (!extensive_changes_)
327 web_ui()->CallJavascriptFunction("ntp.bookmarkChanged", status);
328 }
329
330 void BookmarksHandler::HandleShortcutToBookmark(const ListValue* args) {
331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
332 Profile* profile = Profile::FromBrowserContext(
333 web_ui()->GetWebContents()->GetBrowserContext());
334 if (!profile)
335 return;
336
337 int64 id;
338 bool is_partner;
339 if (args && !args->empty() && ParseNtpBookmarkId(args, &id, &is_partner)) {
340 DCHECK(partner_bookmarks_shim_ != NULL);
341 BookmarkNode* node = const_cast<BookmarkNode*>(
342 partner_bookmarks_shim_->GetNodeByID(id, is_partner));
343 if (!node)
344 return;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
345 creating_shortcut_ = true;
346 FaviconService* favicon_service = profile->GetFaviconService(
347 Profile::EXPLICIT_ACCESS);
348 FaviconService::Handle handle = favicon_service->GetFaviconForURL(
349 node->url(),
350 history::FAVICON | history::TOUCH_ICON,
351 &cancelable_consumer_,
352 base::Bind(&BookmarksHandler::OnFaviconDataAvailable,
353 base::Unretained(this)));
354 cancelable_consumer_.SetClientData(favicon_service, handle, node);
355 }
356 }
357
358 void BookmarksHandler::OnFaviconDataAvailable(
359 FaviconService::Handle handle,
360 history::FaviconData favicon) {
361 if (!creating_shortcut_)
362 return;
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
363 SkColor color = SK_ColorWHITE;
364 SkBitmap favicon_bitmap;
365 if (favicon.is_valid()) {
366 color = GetDominantColorForFavicon(favicon.image_data);
367 gfx::PNGCodec::Decode(favicon.image_data->front(),
368 favicon.image_data->size(),
369 &favicon_bitmap);
370 }
Evan Stade 2012/08/14 22:04:54 \n
Ted C 2012/08/14 23:24:28 Done.
371 Profile* profile = Profile::FromBrowserContext(
372 web_ui()->GetWebContents()->GetBrowserContext());
373 BookmarkNode* node = cancelable_consumer_.GetClientData(
374 profile->GetFaviconService(Profile::EXPLICIT_ACCESS), handle);
375
376 TabAndroid* tab = TabAndroid::FromWebContents(
377 web_ui()->GetWebContents());
378 if (tab)
Evan Stade 2012/08/14 22:04:54 curlies
Ted C 2012/08/14 23:24:28 Done.
379 tab->AddShortcutToBookmark(node->url(), node->GetTitle(),
380 favicon_bitmap, SkColorGetR(color),
381 SkColorGetG(color), SkColorGetB(color));
382 creating_shortcut_ = false;
383 }
OLDNEW
« 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