| OLD | NEW |
| (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/metrics/histogram.h" | |
| 10 #include "base/prefs/pref_service.h" | |
| 11 #include "base/strings/string_number_conversions.h" | |
| 12 #include "base/strings/string_util.h" | |
| 13 #include "chrome/browser/android/tab_android.h" | |
| 14 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | |
| 15 #include "chrome/browser/favicon/favicon_service_factory.h" | |
| 16 #include "chrome/browser/profiles/incognito_helpers.h" | |
| 17 #include "chrome/browser/profiles/profile.h" | |
| 18 #include "chrome/browser/profiles/profile_manager.h" | |
| 19 #include "chrome/browser/ui/webui/favicon_source.h" | |
| 20 #include "chrome/common/pref_names.h" | |
| 21 #include "components/bookmarks/core/browser/bookmark_model.h" | |
| 22 #include "components/bookmarks/core/browser/bookmark_utils.h" | |
| 23 #include "content/public/browser/browser_thread.h" | |
| 24 #include "content/public/browser/url_data_source.h" | |
| 25 #include "content/public/browser/web_contents.h" | |
| 26 #include "third_party/skia/include/core/SkBitmap.h" | |
| 27 #include "ui/gfx/codec/png_codec.h" | |
| 28 #include "ui/gfx/color_analysis.h" | |
| 29 #include "ui/gfx/favicon_size.h" | |
| 30 | |
| 31 using base::Int64ToString; | |
| 32 using content::BrowserThread; | |
| 33 | |
| 34 namespace { | |
| 35 | |
| 36 static const char* kParentIdParam = "parent_id"; | |
| 37 static const char* kNodeIdParam = "node_id"; | |
| 38 | |
| 39 // Defines actions taken by the user over the partner bookmarks on NTP for | |
| 40 // NewTabPage.BookmarkActionAndroid histogram. | |
| 41 // Should be kept in sync with the values in histograms.xml. | |
| 42 enum PartnerBookmarkAction { | |
| 43 BOOKMARK_ACTION_DELETE_BOOKMARK_PARTNER = 0, | |
| 44 BOOKMARK_ACTION_DELETE_ROOT_FOLDER_PARTNER = 1, | |
| 45 BOOKMARK_ACTION_EDIT_BOOKMARK_PARTNER = 2, | |
| 46 BOOKMARK_ACTION_EDIT_ROOT_FOLDER_PARTNER = 3, | |
| 47 BOOKMARK_ACTION_BUCKET_BOUNDARY = 4 | |
| 48 }; | |
| 49 | |
| 50 // Helper to record a bookmark action in BookmarkActionAndroid histogram. | |
| 51 void RecordBookmarkAction(PartnerBookmarkAction type) { | |
| 52 UMA_HISTOGRAM_ENUMERATION("NewTabPage.BookmarkActionAndroid", type, | |
| 53 BOOKMARK_ACTION_BUCKET_BOUNDARY); | |
| 54 } | |
| 55 | |
| 56 std::string BookmarkTypeAsString(BookmarkNode::Type type) { | |
| 57 switch (type) { | |
| 58 case BookmarkNode::URL: | |
| 59 return "URL"; | |
| 60 case BookmarkNode::FOLDER: | |
| 61 return "FOLDER"; | |
| 62 case BookmarkNode::BOOKMARK_BAR: | |
| 63 return "BOOKMARK_BAR"; | |
| 64 case BookmarkNode::OTHER_NODE: | |
| 65 return "OTHER_NODE"; | |
| 66 case BookmarkNode::MOBILE: | |
| 67 return "MOBILE"; | |
| 68 default: | |
| 69 return "UNKNOWN"; | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 SkColor GetDominantColorForFavicon(scoped_refptr<base::RefCountedMemory> png) { | |
| 74 color_utils::GridSampler sampler; | |
| 75 // 100 here is the darkness_limit which represents the minimum sum of the RGB | |
| 76 // components that is acceptable as a color choice. This can be from 0 to 765. | |
| 77 // 665 here is the brightness_limit represents the maximum sum of the RGB | |
| 78 // components that is acceptable as a color choice. This can be from 0 to 765. | |
| 79 return color_utils::CalculateKMeanColorOfPNG(png, 100, 665, &sampler); | |
| 80 } | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 BookmarksHandler::BookmarksHandler() | |
| 85 : bookmark_model_(NULL), | |
| 86 partner_bookmarks_shim_(NULL), | |
| 87 bookmark_data_requested_(false), | |
| 88 extensive_changes_(false) { | |
| 89 } | |
| 90 | |
| 91 BookmarksHandler::~BookmarksHandler() { | |
| 92 if (bookmark_model_) | |
| 93 bookmark_model_->RemoveObserver(this); | |
| 94 | |
| 95 if (partner_bookmarks_shim_) | |
| 96 partner_bookmarks_shim_->RemoveObserver(this); | |
| 97 | |
| 98 if (managed_bookmarks_shim_) | |
| 99 managed_bookmarks_shim_->RemoveObserver(this); | |
| 100 } | |
| 101 | |
| 102 void BookmarksHandler::RegisterMessages() { | |
| 103 // Listen for the bookmark change. We need the both bookmark and folder | |
| 104 // change, the NotificationService is not sufficient. | |
| 105 Profile* profile = Profile::FromBrowserContext( | |
| 106 web_ui()->GetWebContents()->GetBrowserContext()); | |
| 107 | |
| 108 content::URLDataSource::Add( | |
| 109 profile, new FaviconSource(profile, FaviconSource::ANY)); | |
| 110 | |
| 111 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile); | |
| 112 if (bookmark_model_) { | |
| 113 bookmark_model_->AddObserver(this); | |
| 114 // Since a sync or import could have started before this class is | |
| 115 // initialized, we need to make sure that our initial state is | |
| 116 // up to date. | |
| 117 extensive_changes_ = bookmark_model_->IsDoingExtensiveChanges(); | |
| 118 } | |
| 119 | |
| 120 // Create the partner Bookmarks shim as early as possible (but don't attach). | |
| 121 if (!partner_bookmarks_shim_) { | |
| 122 partner_bookmarks_shim_ = PartnerBookmarksShim::BuildForBrowserContext( | |
| 123 chrome::GetBrowserContextRedirectedInIncognito( | |
| 124 web_ui()->GetWebContents()->GetBrowserContext())); | |
| 125 partner_bookmarks_shim_->AddObserver(this); | |
| 126 } | |
| 127 | |
| 128 managed_bookmarks_shim_.reset(new ManagedBookmarksShim(profile->GetPrefs())); | |
| 129 managed_bookmarks_shim_->AddObserver(this); | |
| 130 | |
| 131 // Register ourselves as the handler for the bookmark javascript callbacks. | |
| 132 web_ui()->RegisterMessageCallback("getBookmarks", | |
| 133 base::Bind(&BookmarksHandler::HandleGetBookmarks, | |
| 134 base::Unretained(this))); | |
| 135 web_ui()->RegisterMessageCallback("deleteBookmark", | |
| 136 base::Bind(&BookmarksHandler::HandleDeleteBookmark, | |
| 137 base::Unretained(this))); | |
| 138 web_ui()->RegisterMessageCallback("editBookmark", | |
| 139 base::Bind(&BookmarksHandler::HandleEditBookmark, | |
| 140 base::Unretained(this))); | |
| 141 web_ui()->RegisterMessageCallback("createHomeScreenBookmarkShortcut", | |
| 142 base::Bind(&BookmarksHandler::HandleCreateHomeScreenBookmarkShortcut, | |
| 143 base::Unretained(this))); | |
| 144 } | |
| 145 | |
| 146 void BookmarksHandler::HandleGetBookmarks(const base::ListValue* args) { | |
| 147 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 148 | |
| 149 bookmark_data_requested_ = true; | |
| 150 if (!AreModelsLoaded()) | |
| 151 return; // is handled in Loaded()/PartnerShimLoaded() callback. | |
| 152 | |
| 153 const BookmarkNode* node = GetNodeByID(args); | |
| 154 if (node) | |
| 155 QueryBookmarkFolder(node); | |
| 156 else | |
| 157 QueryInitialBookmarks(); | |
| 158 } | |
| 159 | |
| 160 void BookmarksHandler::HandleDeleteBookmark(const base::ListValue* args) { | |
| 161 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 162 if (!AreModelsLoaded()) | |
| 163 return; | |
| 164 | |
| 165 const BookmarkNode* node = GetNodeByID(args); | |
| 166 if (!node) | |
| 167 return; | |
| 168 | |
| 169 if (!IsEditable(node)) { | |
| 170 NOTREACHED(); | |
| 171 return; | |
| 172 } | |
| 173 | |
| 174 if (partner_bookmarks_shim_->IsPartnerBookmark(node)) { | |
| 175 if (partner_bookmarks_shim_->GetPartnerBookmarksRoot() == node) | |
| 176 RecordBookmarkAction(BOOKMARK_ACTION_DELETE_ROOT_FOLDER_PARTNER); | |
| 177 else | |
| 178 RecordBookmarkAction(BOOKMARK_ACTION_DELETE_BOOKMARK_PARTNER); | |
| 179 partner_bookmarks_shim_->RemoveBookmark(node); | |
| 180 return; | |
| 181 } | |
| 182 | |
| 183 const BookmarkNode* parent_node = node->parent(); | |
| 184 bookmark_model_->Remove(parent_node, parent_node->GetIndexOf(node)); | |
| 185 } | |
| 186 | |
| 187 void BookmarksHandler::HandleEditBookmark(const base::ListValue* args) { | |
| 188 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 189 if (!AreModelsLoaded()) | |
| 190 return; | |
| 191 | |
| 192 const BookmarkNode* node = GetNodeByID(args); | |
| 193 if (!node) | |
| 194 return; | |
| 195 | |
| 196 if (!IsEditable(node)) { | |
| 197 NOTREACHED(); | |
| 198 return; | |
| 199 } | |
| 200 | |
| 201 TabAndroid* tab = TabAndroid::FromWebContents(web_ui()->GetWebContents()); | |
| 202 if (tab) { | |
| 203 if (partner_bookmarks_shim_->IsPartnerBookmark(node)) { | |
| 204 if (partner_bookmarks_shim_->GetPartnerBookmarksRoot() == node) | |
| 205 RecordBookmarkAction(BOOKMARK_ACTION_EDIT_ROOT_FOLDER_PARTNER); | |
| 206 else | |
| 207 RecordBookmarkAction(BOOKMARK_ACTION_EDIT_BOOKMARK_PARTNER); | |
| 208 } | |
| 209 tab->EditBookmark(node->id(), | |
| 210 GetTitle(node), | |
| 211 node->is_folder(), | |
| 212 partner_bookmarks_shim_->IsPartnerBookmark(node)); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 bool BookmarksHandler::AreModelsLoaded() const { | |
| 217 Profile* profile = Profile::FromBrowserContext( | |
| 218 web_ui()->GetWebContents()->GetBrowserContext()); | |
| 219 if (!profile) | |
| 220 return false; | |
| 221 | |
| 222 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile); | |
| 223 if (!model || !model->loaded()) | |
| 224 return false; | |
| 225 | |
| 226 return partner_bookmarks_shim_ && partner_bookmarks_shim_->IsLoaded(); | |
| 227 } | |
| 228 | |
| 229 void BookmarksHandler::NotifyModelChanged(const base::DictionaryValue& status) { | |
| 230 DCHECK(AreModelsLoaded()); | |
| 231 | |
| 232 if (bookmark_data_requested_ && !extensive_changes_) | |
| 233 web_ui()->CallJavascriptFunction("ntp.bookmarkChanged", status); | |
| 234 } | |
| 235 | |
| 236 std::string BookmarksHandler::GetBookmarkIdForNtp(const BookmarkNode* node) { | |
| 237 DCHECK(AreModelsLoaded()); | |
| 238 | |
| 239 std::string prefix; | |
| 240 if (partner_bookmarks_shim_->IsPartnerBookmark(node)) | |
| 241 prefix = "p"; | |
| 242 else if (managed_bookmarks_shim_->IsManagedBookmark(node)) | |
| 243 prefix = "m"; | |
| 244 return prefix + Int64ToString(node->id()); | |
| 245 } | |
| 246 | |
| 247 void BookmarksHandler::SetParentInBookmarksResult( | |
| 248 const BookmarkNode* parent, | |
| 249 base::DictionaryValue* result) { | |
| 250 result->SetString(kParentIdParam, GetBookmarkIdForNtp(parent)); | |
| 251 } | |
| 252 | |
| 253 void BookmarksHandler::PopulateBookmark(const BookmarkNode* node, | |
| 254 base::ListValue* result) { | |
| 255 if (!result) | |
| 256 return; | |
| 257 | |
| 258 DCHECK(AreModelsLoaded()); | |
| 259 if (!IsReachable(node)) | |
| 260 return; | |
| 261 | |
| 262 base::DictionaryValue* filler_value = new base::DictionaryValue(); | |
| 263 filler_value->SetString("title", GetTitle(node)); | |
| 264 filler_value->SetBoolean("editable", IsEditable(node)); | |
| 265 if (node->is_url()) { | |
| 266 filler_value->SetBoolean("folder", false); | |
| 267 filler_value->SetString("url", node->url().spec()); | |
| 268 } else { | |
| 269 filler_value->SetBoolean("folder", true); | |
| 270 } | |
| 271 filler_value->SetString("id", GetBookmarkIdForNtp(node)); | |
| 272 filler_value->SetString("type", BookmarkTypeAsString(node->type())); | |
| 273 result->Append(filler_value); | |
| 274 } | |
| 275 | |
| 276 void BookmarksHandler::PopulateBookmarksInFolder( | |
| 277 const BookmarkNode* folder, | |
| 278 base::DictionaryValue* result) { | |
| 279 DCHECK(AreModelsLoaded()); | |
| 280 if (!IsReachable(folder)) | |
| 281 return; | |
| 282 | |
| 283 base::ListValue* bookmarks = new base::ListValue(); | |
| 284 | |
| 285 // If this is the Mobile bookmarks folder then add the "Managed bookmarks" | |
| 286 // folder first, so that it's the first entry. | |
| 287 if (bookmark_model_ && folder == bookmark_model_->mobile_node() && | |
| 288 managed_bookmarks_shim_->HasManagedBookmarks()) { | |
| 289 PopulateBookmark(managed_bookmarks_shim_->GetManagedBookmarksRoot(), | |
| 290 bookmarks); | |
| 291 } | |
| 292 | |
| 293 for (int i = 0; i < folder->child_count(); i++) { | |
| 294 const BookmarkNode* bookmark= folder->GetChild(i); | |
| 295 PopulateBookmark(bookmark, bookmarks); | |
| 296 } | |
| 297 | |
| 298 // Make sure we iterate over the partner's attach point | |
| 299 if (bookmark_model_ && folder == bookmark_model_->mobile_node() && | |
| 300 partner_bookmarks_shim_->HasPartnerBookmarks()) { | |
| 301 PopulateBookmark(partner_bookmarks_shim_->GetPartnerBookmarksRoot(), | |
| 302 bookmarks); | |
| 303 } | |
| 304 | |
| 305 base::ListValue* folder_hierarchy = new base::ListValue(); | |
| 306 const BookmarkNode* parent = GetParentOf(folder); | |
| 307 | |
| 308 while (parent != NULL) { | |
| 309 base::DictionaryValue* hierarchy_entry = new base::DictionaryValue(); | |
| 310 if (IsRoot(parent)) | |
| 311 hierarchy_entry->SetBoolean("root", true); | |
| 312 | |
| 313 hierarchy_entry->SetString("title", GetTitle(parent)); | |
| 314 hierarchy_entry->SetString("id", GetBookmarkIdForNtp(parent)); | |
| 315 folder_hierarchy->Append(hierarchy_entry); | |
| 316 parent = GetParentOf(parent); | |
| 317 } | |
| 318 | |
| 319 result->SetString("title", GetTitle(folder)); | |
| 320 result->SetString("id", GetBookmarkIdForNtp(folder)); | |
| 321 result->SetBoolean("root", IsRoot(folder)); | |
| 322 result->Set("bookmarks", bookmarks); | |
| 323 result->Set("hierarchy", folder_hierarchy); | |
| 324 } | |
| 325 | |
| 326 void BookmarksHandler::QueryBookmarkFolder(const BookmarkNode* node) { | |
| 327 DCHECK(AreModelsLoaded()); | |
| 328 if (node->is_folder() && IsReachable(node)) { | |
| 329 base::DictionaryValue result; | |
| 330 PopulateBookmarksInFolder(node, &result); | |
| 331 SendResult(result); | |
| 332 } else { | |
| 333 // If we receive an ID that no longer maps to a bookmark folder, just | |
| 334 // return the initial bookmark folder. | |
| 335 QueryInitialBookmarks(); | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 void BookmarksHandler::QueryInitialBookmarks() { | |
| 340 DCHECK(AreModelsLoaded()); | |
| 341 base::DictionaryValue result; | |
| 342 PopulateBookmarksInFolder(bookmark_model_->mobile_node(), &result); | |
| 343 SendResult(result); | |
| 344 } | |
| 345 | |
| 346 void BookmarksHandler::SendResult(const base::DictionaryValue& result) { | |
| 347 web_ui()->CallJavascriptFunction("ntp.bookmarks", result); | |
| 348 } | |
| 349 | |
| 350 void BookmarksHandler::BookmarkModelLoaded(BookmarkModel* model, | |
| 351 bool ids_reassigned) { | |
| 352 if (AreModelsLoaded()) | |
| 353 BookmarkModelChanged(); | |
| 354 } | |
| 355 | |
| 356 void BookmarksHandler::PartnerShimChanged(PartnerBookmarksShim* shim) { | |
| 357 if (AreModelsLoaded()) | |
| 358 BookmarkModelChanged(); | |
| 359 } | |
| 360 | |
| 361 void BookmarksHandler::PartnerShimLoaded(PartnerBookmarksShim* shim) { | |
| 362 if (AreModelsLoaded()) | |
| 363 BookmarkModelChanged(); | |
| 364 } | |
| 365 | |
| 366 void BookmarksHandler::ShimBeingDeleted(PartnerBookmarksShim* shim) { | |
| 367 partner_bookmarks_shim_ = NULL; | |
| 368 } | |
| 369 | |
| 370 void BookmarksHandler::OnManagedBookmarksChanged() { | |
| 371 if (AreModelsLoaded()) | |
| 372 BookmarkModelChanged(); | |
| 373 } | |
| 374 | |
| 375 void BookmarksHandler::ExtensiveBookmarkChangesBeginning(BookmarkModel* model) { | |
| 376 extensive_changes_ = true; | |
| 377 } | |
| 378 | |
| 379 void BookmarksHandler::ExtensiveBookmarkChangesEnded(BookmarkModel* model) { | |
| 380 extensive_changes_ = false; | |
| 381 if (AreModelsLoaded()) | |
| 382 BookmarkModelChanged(); | |
| 383 } | |
| 384 | |
| 385 void BookmarksHandler::BookmarkNodeRemoved(BookmarkModel* model, | |
| 386 const BookmarkNode* parent, | |
| 387 int old_index, | |
| 388 const BookmarkNode* node) { | |
| 389 if (!AreModelsLoaded()) | |
| 390 return; | |
| 391 | |
| 392 base::DictionaryValue result; | |
| 393 SetParentInBookmarksResult(parent, &result); | |
| 394 result.SetString(kNodeIdParam, Int64ToString(node->id())); | |
| 395 NotifyModelChanged(result); | |
| 396 } | |
| 397 | |
| 398 void BookmarksHandler::BookmarkAllNodesRemoved(BookmarkModel* model) { | |
| 399 if (!AreModelsLoaded()) | |
| 400 return; | |
| 401 | |
| 402 if (bookmark_data_requested_ && !extensive_changes_) | |
| 403 web_ui()->CallJavascriptFunction("ntp.bookmarkChanged"); | |
| 404 } | |
| 405 | |
| 406 void BookmarksHandler::BookmarkNodeAdded( | |
| 407 BookmarkModel* model, const BookmarkNode* parent, int index) { | |
| 408 if (!AreModelsLoaded()) | |
| 409 return; | |
| 410 | |
| 411 base::DictionaryValue result; | |
| 412 SetParentInBookmarksResult(parent, &result); | |
| 413 NotifyModelChanged(result); | |
| 414 } | |
| 415 | |
| 416 void BookmarksHandler::BookmarkNodeChanged(BookmarkModel* model, | |
| 417 const BookmarkNode* node) { | |
| 418 if (!AreModelsLoaded()) | |
| 419 return; | |
| 420 | |
| 421 DCHECK(!partner_bookmarks_shim_->IsPartnerBookmark(node)); | |
| 422 base::DictionaryValue result; | |
| 423 SetParentInBookmarksResult(node->parent(), &result); | |
| 424 result.SetString(kNodeIdParam, Int64ToString(node->id())); | |
| 425 NotifyModelChanged(result); | |
| 426 } | |
| 427 | |
| 428 void BookmarksHandler::BookmarkModelChanged() { | |
| 429 if (!AreModelsLoaded()) | |
| 430 return; | |
| 431 | |
| 432 if (bookmark_data_requested_ && !extensive_changes_) | |
| 433 web_ui()->CallJavascriptFunction("ntp.bookmarkChanged"); | |
| 434 } | |
| 435 | |
| 436 void BookmarksHandler::HandleCreateHomeScreenBookmarkShortcut( | |
| 437 const base::ListValue* args) { | |
| 438 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 439 if (!AreModelsLoaded()) | |
| 440 return; | |
| 441 | |
| 442 Profile* profile = Profile::FromBrowserContext( | |
| 443 web_ui()->GetWebContents()->GetBrowserContext()); | |
| 444 if (!profile) | |
| 445 return; | |
| 446 | |
| 447 const BookmarkNode* node = GetNodeByID(args); | |
| 448 if (!node) | |
| 449 return; | |
| 450 | |
| 451 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( | |
| 452 profile, Profile::EXPLICIT_ACCESS); | |
| 453 favicon_service->GetRawFaviconForURL( | |
| 454 FaviconService::FaviconForURLParams(node->url(), | |
| 455 favicon_base::TOUCH_PRECOMPOSED_ICON | | |
| 456 favicon_base::TOUCH_ICON | | |
| 457 favicon_base::FAVICON, | |
| 458 0), // request the largest icon. | |
| 459 ui::SCALE_FACTOR_100P, // density doesn't matter for the largest icon. | |
| 460 base::Bind(&BookmarksHandler::OnShortcutFaviconDataAvailable, | |
| 461 base::Unretained(this), | |
| 462 node), | |
| 463 &cancelable_task_tracker_); | |
| 464 } | |
| 465 | |
| 466 void BookmarksHandler::OnShortcutFaviconDataAvailable( | |
| 467 const BookmarkNode* node, | |
| 468 const favicon_base::FaviconBitmapResult& bitmap_result) { | |
| 469 if (!AreModelsLoaded()) | |
| 470 return; | |
| 471 | |
| 472 SkColor color = SK_ColorWHITE; | |
| 473 SkBitmap favicon_bitmap; | |
| 474 if (bitmap_result.is_valid()) { | |
| 475 color = GetDominantColorForFavicon(bitmap_result.bitmap_data); | |
| 476 gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), | |
| 477 bitmap_result.bitmap_data->size(), | |
| 478 &favicon_bitmap); | |
| 479 } | |
| 480 TabAndroid* tab = TabAndroid::FromWebContents(web_ui()->GetWebContents()); | |
| 481 if (tab) { | |
| 482 tab->AddShortcutToBookmark(node->url(), | |
| 483 GetTitle(node), | |
| 484 favicon_bitmap, SkColorGetR(color), | |
| 485 SkColorGetG(color), SkColorGetB(color)); | |
| 486 } | |
| 487 } | |
| 488 | |
| 489 const BookmarkNode* BookmarksHandler::GetNodeByID( | |
| 490 const base::ListValue* args) const { | |
| 491 DCHECK(AreModelsLoaded()); | |
| 492 | |
| 493 // Parses a bookmark ID passed back from the NTP. The IDs differ from the | |
| 494 // normal int64 bookmark ID because we prepend a "p" if the ID represents a | |
| 495 // partner bookmark, and an "m" if the ID represents a managed bookmark. | |
| 496 | |
| 497 if (!args || args->empty()) | |
| 498 return NULL; | |
| 499 | |
| 500 std::string string_id; | |
| 501 if (!args->GetString(0, &string_id) || string_id.empty()) { | |
| 502 NOTREACHED(); | |
| 503 return NULL; | |
| 504 } | |
| 505 | |
| 506 bool is_partner = string_id[0] == 'p'; | |
| 507 bool is_managed = string_id[0] == 'm'; | |
| 508 | |
| 509 if (is_partner || is_managed) | |
| 510 string_id = string_id.substr(1); | |
| 511 | |
| 512 int64 id = 0; | |
| 513 if (!base::StringToInt64(string_id, &id)) { | |
| 514 NOTREACHED(); | |
| 515 return NULL; | |
| 516 } | |
| 517 | |
| 518 if (is_managed) | |
| 519 return managed_bookmarks_shim_->GetNodeByID(id); | |
| 520 | |
| 521 if (is_partner) | |
| 522 return partner_bookmarks_shim_->GetNodeByID(id); | |
| 523 | |
| 524 return GetBookmarkNodeByID(bookmark_model_, id); | |
| 525 } | |
| 526 | |
| 527 const BookmarkNode* BookmarksHandler::GetParentOf( | |
| 528 const BookmarkNode* node) const { | |
| 529 DCHECK(AreModelsLoaded()); | |
| 530 if (node == managed_bookmarks_shim_->GetManagedBookmarksRoot() || | |
| 531 node == partner_bookmarks_shim_->GetPartnerBookmarksRoot()) { | |
| 532 return bookmark_model_->mobile_node(); | |
| 533 } | |
| 534 | |
| 535 return node->parent(); | |
| 536 } | |
| 537 | |
| 538 base::string16 BookmarksHandler::GetTitle(const BookmarkNode* node) const { | |
| 539 DCHECK(AreModelsLoaded()); | |
| 540 if (partner_bookmarks_shim_->IsPartnerBookmark(node)) | |
| 541 return partner_bookmarks_shim_->GetTitle(node); | |
| 542 | |
| 543 return node->GetTitle(); | |
| 544 } | |
| 545 | |
| 546 bool BookmarksHandler::IsReachable(const BookmarkNode* node) const { | |
| 547 DCHECK(AreModelsLoaded()); | |
| 548 if (!partner_bookmarks_shim_->IsPartnerBookmark(node)) | |
| 549 return true; | |
| 550 | |
| 551 return partner_bookmarks_shim_->IsReachable(node); | |
| 552 } | |
| 553 | |
| 554 bool BookmarksHandler::IsEditable(const BookmarkNode* node) const { | |
| 555 DCHECK(AreModelsLoaded()); | |
| 556 | |
| 557 // Reserved system nodes and managed bookmarks are not editable. | |
| 558 // Additionally, bookmark editing may be completely disabled | |
| 559 // via a managed preference. | |
| 560 if (!node || | |
| 561 (node->type() != BookmarkNode::FOLDER && | |
| 562 node->type() != BookmarkNode::URL)) { | |
| 563 return false; | |
| 564 } | |
| 565 | |
| 566 const PrefService* pref = Profile::FromBrowserContext( | |
| 567 web_ui()->GetWebContents()->GetBrowserContext())->GetPrefs(); | |
| 568 if (!pref->GetBoolean(prefs::kEditBookmarksEnabled)) | |
| 569 return false; | |
| 570 | |
| 571 if (partner_bookmarks_shim_->IsPartnerBookmark(node)) | |
| 572 return true; | |
| 573 | |
| 574 return !managed_bookmarks_shim_->IsManagedBookmark(node); | |
| 575 } | |
| 576 | |
| 577 bool BookmarksHandler::IsRoot(const BookmarkNode* node) const { | |
| 578 DCHECK(AreModelsLoaded()); | |
| 579 | |
| 580 return node->is_root() && | |
| 581 node != partner_bookmarks_shim_->GetPartnerBookmarksRoot() && | |
| 582 node != managed_bookmarks_shim_->GetManagedBookmarksRoot(); | |
| 583 } | |
| OLD | NEW |