chrome_bookmark_client.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1// Copyright 2014 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/bookmarks/chrome_bookmark_client.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/logging.h" 10#include "base/values.h" 11#include "chrome/browser/chrome_notification_types.h" 12#include "chrome/browser/favicon/favicon_changed_details.h" 13#include "chrome/browser/favicon/favicon_service.h" 14#include "chrome/browser/favicon/favicon_service_factory.h" 15#include "chrome/browser/history/history_service.h" 16#include "chrome/browser/history/history_service_factory.h" 17#include "chrome/browser/history/url_database.h" 18#include "chrome/browser/policy/profile_policy_connector.h" 19#include "chrome/browser/policy/profile_policy_connector_factory.h" 20#include "chrome/browser/profiles/profile.h" 21#include "chrome/browser/profiles/startup_task_runner_service.h" 22#include "chrome/browser/profiles/startup_task_runner_service_factory.h" 23#include "components/bookmarks/browser/bookmark_model.h" 24#include "components/bookmarks/browser/bookmark_node.h" 25#include "content/public/browser/browser_thread.h" 26#include "content/public/browser/notification_details.h" 27#include "content/public/browser/notification_source.h" 28#include "content/public/browser/user_metrics.h" 29#include "grit/components_strings.h" 30#include "policy/policy_constants.h" 31#include "ui/base/l10n/l10n_util.h" 32 33namespace { 34 35void NotifyHistoryOfRemovedURLs(Profile* profile, 36 const std::set<GURL>& removed_urls) { 37 HistoryService* history_service = 38 HistoryServiceFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS); 39 if (history_service) 40 history_service->URLsNoLongerBookmarked(removed_urls); 41} 42 43} // namespace 44 45ChromeBookmarkClient::ChromeBookmarkClient(Profile* profile) 46 : profile_(profile), model_(NULL), managed_node_(NULL) { 47} 48 49ChromeBookmarkClient::~ChromeBookmarkClient() { 50} 51 52void ChromeBookmarkClient::Init(BookmarkModel* model) { 53 DCHECK(model); 54 DCHECK(!model_); 55 model_ = model; 56 model_->AddObserver(this); 57 58 managed_bookmarks_tracker_.reset(new policy::ManagedBookmarksTracker( 59 model_, 60 profile_->GetPrefs(), 61 base::Bind(&ChromeBookmarkClient::GetManagedBookmarksDomain, 62 base::Unretained(this)))); 63 64 // Listen for changes to favicons so that we can update the favicon of the 65 // node appropriately. 66 registrar_.Add(this, 67 chrome::NOTIFICATION_FAVICON_CHANGED, 68 content::Source<Profile>(profile_)); 69} 70 71void ChromeBookmarkClient::Shutdown() { 72 if (model_) { 73 registrar_.RemoveAll(); 74 75 model_->RemoveObserver(this); 76 model_ = NULL; 77 } 78 BookmarkClient::Shutdown(); 79} 80 81bool ChromeBookmarkClient::IsDescendantOfManagedNode(const BookmarkNode* node) { 82 return node && node->HasAncestor(managed_node_); 83} 84 85bool ChromeBookmarkClient::HasDescendantsOfManagedNode( 86 const std::vector<const BookmarkNode*>& list) { 87 for (size_t i = 0; i < list.size(); ++i) { 88 if (IsDescendantOfManagedNode(list[i])) 89 return true; 90 } 91 return false; 92} 93 94bool ChromeBookmarkClient::PreferTouchIcon() { 95#if !defined(OS_IOS) 96 return false; 97#else 98 return true; 99#endif 100} 101 102base::CancelableTaskTracker::TaskId ChromeBookmarkClient::GetFaviconImageForURL( 103 const GURL& page_url, 104 int icon_types, 105 int desired_size_in_dip, 106 const favicon_base::FaviconImageCallback& callback, 107 base::CancelableTaskTracker* tracker) { 108 FaviconService* favicon_service = 109 FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 110 if (!favicon_service) 111 return base::CancelableTaskTracker::kBadTaskId; 112 return favicon_service->GetFaviconImageForPageURL( 113 FaviconService::FaviconForPageURLParams( 114 page_url, icon_types, desired_size_in_dip), 115 callback, 116 tracker); 117} 118 119bool ChromeBookmarkClient::SupportsTypedCountForNodes() { 120 return true; 121} 122 123void ChromeBookmarkClient::GetTypedCountForNodes( 124 const NodeSet& nodes, 125 NodeTypedCountPairs* node_typed_count_pairs) { 126 HistoryService* history_service = 127 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 128 history::URLDatabase* url_db = 129 history_service ? history_service->InMemoryDatabase() : NULL; 130 for (NodeSet::const_iterator i = nodes.begin(); i != nodes.end(); ++i) { 131 int typed_count = 0; 132 133 // If |url_db| is the InMemoryDatabase, it might not cache all URLRows, but 134 // it guarantees to contain those with |typed_count| > 0. Thus, if we cannot 135 // fetch the URLRow, it is safe to assume that its |typed_count| is 0. 136 history::URLRow url; 137 if (url_db && url_db->GetRowForURL((*i)->url(), &url)) 138 typed_count = url.typed_count(); 139 140 NodeTypedCountPair pair(*i, typed_count); 141 node_typed_count_pairs->push_back(pair); 142 } 143} 144 145bool ChromeBookmarkClient::IsPermanentNodeVisible( 146 const BookmarkPermanentNode* node) { 147 DCHECK(node->type() == BookmarkNode::BOOKMARK_BAR || 148 node->type() == BookmarkNode::OTHER_NODE || 149 node->type() == BookmarkNode::MOBILE || 150 node == managed_node_); 151 if (node == managed_node_) 152 return false; 153#if !defined(OS_IOS) 154 return node->type() != BookmarkNode::MOBILE; 155#else 156 return node->type() == BookmarkNode::MOBILE; 157#endif 158} 159 160void ChromeBookmarkClient::RecordAction(const base::UserMetricsAction& action) { 161 content::RecordAction(action); 162} 163 164bookmarks::LoadExtraCallback ChromeBookmarkClient::GetLoadExtraNodesCallback() { 165 // Create the managed_node now; it will be populated in the LoadExtraNodes 166 // callback. 167 managed_node_ = new BookmarkPermanentNode(0); 168 return base::Bind( 169 &ChromeBookmarkClient::LoadExtraNodes, 170 StartupTaskRunnerServiceFactory::GetForProfile(profile_) 171 ->GetBookmarkTaskRunner(), 172 managed_node_, 173 base::Passed(managed_bookmarks_tracker_->GetInitialManagedBookmarks())); 174} 175 176bool ChromeBookmarkClient::CanSetPermanentNodeTitle( 177 const BookmarkNode* permanent_node) { 178 // The |managed_node_| can have its title updated if the user signs in or 179 // out. 180 return !IsDescendantOfManagedNode(permanent_node) || 181 permanent_node == managed_node_; 182} 183 184bool ChromeBookmarkClient::CanSyncNode(const BookmarkNode* node) { 185 return !IsDescendantOfManagedNode(node); 186} 187 188bool ChromeBookmarkClient::CanBeEditedByUser(const BookmarkNode* node) { 189 return !IsDescendantOfManagedNode(node); 190} 191 192void ChromeBookmarkClient::Observe( 193 int type, 194 const content::NotificationSource& source, 195 const content::NotificationDetails& details) { 196 switch (type) { 197 case chrome::NOTIFICATION_FAVICON_CHANGED: { 198 content::Details<FaviconChangedDetails> favicon_details(details); 199 model_->OnFaviconChanged(favicon_details->urls); 200 break; 201 } 202 203 default: 204 NOTREACHED(); 205 break; 206 } 207} 208 209void ChromeBookmarkClient::BookmarkModelChanged() { 210} 211 212void ChromeBookmarkClient::BookmarkNodeRemoved( 213 BookmarkModel* model, 214 const BookmarkNode* parent, 215 int old_index, 216 const BookmarkNode* node, 217 const std::set<GURL>& removed_urls) { 218 NotifyHistoryOfRemovedURLs(profile_, removed_urls); 219} 220 221void ChromeBookmarkClient::BookmarkAllUserNodesRemoved( 222 BookmarkModel* model, 223 const std::set<GURL>& removed_urls) { 224 NotifyHistoryOfRemovedURLs(profile_, removed_urls); 225} 226 227void ChromeBookmarkClient::BookmarkModelLoaded(BookmarkModel* model, 228 bool ids_reassigned) { 229 // Start tracking the managed bookmarks. This will detect any changes that 230 // may have occurred while the initial managed bookmarks were being loaded 231 // on the background. 232 managed_bookmarks_tracker_->Init(managed_node_); 233} 234 235// static 236bookmarks::BookmarkPermanentNodeList ChromeBookmarkClient::LoadExtraNodes( 237 const scoped_refptr<base::DeferredSequencedTaskRunner>& profile_io_runner, 238 BookmarkPermanentNode* managed_node, 239 scoped_ptr<base::ListValue> initial_managed_bookmarks, 240 int64* next_node_id) { 241 DCHECK(profile_io_runner->RunsTasksOnCurrentThread()); 242 // Load the initial contents of the |managed_node| now, and assign it an 243 // unused ID. 244 int64 managed_id = *next_node_id; 245 managed_node->set_id(managed_id); 246 *next_node_id = policy::ManagedBookmarksTracker::LoadInitial( 247 managed_node, initial_managed_bookmarks.get(), managed_id + 1); 248 managed_node->set_visible(!managed_node->empty()); 249 managed_node->SetTitle( 250 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME)); 251 252 bookmarks::BookmarkPermanentNodeList extra_nodes; 253 extra_nodes.push_back(managed_node); 254 return extra_nodes.Pass(); 255} 256 257std::string ChromeBookmarkClient::GetManagedBookmarksDomain() { 258 policy::ProfilePolicyConnector* connector = 259 policy::ProfilePolicyConnectorFactory::GetForProfile(profile_); 260 if (connector->IsPolicyFromCloudPolicy(policy::key::kManagedBookmarks)) 261 return connector->GetManagementDomain(); 262 return std::string(); 263} 264