• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 namespace {
34 
NotifyHistoryOfRemovedURLs(Profile * profile,const std::set<GURL> & removed_urls)35 void 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 
ChromeBookmarkClient(Profile * profile)45 ChromeBookmarkClient::ChromeBookmarkClient(Profile* profile)
46     : profile_(profile), model_(NULL), managed_node_(NULL) {
47 }
48 
~ChromeBookmarkClient()49 ChromeBookmarkClient::~ChromeBookmarkClient() {
50 }
51 
Init(BookmarkModel * model)52 void 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 
Shutdown()71 void ChromeBookmarkClient::Shutdown() {
72   if (model_) {
73     registrar_.RemoveAll();
74 
75     model_->RemoveObserver(this);
76     model_ = NULL;
77   }
78   BookmarkClient::Shutdown();
79 }
80 
IsDescendantOfManagedNode(const BookmarkNode * node)81 bool ChromeBookmarkClient::IsDescendantOfManagedNode(const BookmarkNode* node) {
82   return node && node->HasAncestor(managed_node_);
83 }
84 
HasDescendantsOfManagedNode(const std::vector<const BookmarkNode * > & list)85 bool 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 
PreferTouchIcon()94 bool ChromeBookmarkClient::PreferTouchIcon() {
95 #if !defined(OS_IOS)
96   return false;
97 #else
98   return true;
99 #endif
100 }
101 
GetFaviconImageForURL(const GURL & page_url,int icon_types,int desired_size_in_dip,const favicon_base::FaviconImageCallback & callback,base::CancelableTaskTracker * tracker)102 base::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 
SupportsTypedCountForNodes()119 bool ChromeBookmarkClient::SupportsTypedCountForNodes() {
120   return true;
121 }
122 
GetTypedCountForNodes(const NodeSet & nodes,NodeTypedCountPairs * node_typed_count_pairs)123 void 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 
IsPermanentNodeVisible(const BookmarkPermanentNode * node)145 bool 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 
RecordAction(const base::UserMetricsAction & action)160 void ChromeBookmarkClient::RecordAction(const base::UserMetricsAction& action) {
161   content::RecordAction(action);
162 }
163 
GetLoadExtraNodesCallback()164 bookmarks::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 
CanSetPermanentNodeTitle(const BookmarkNode * permanent_node)176 bool 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 
CanSyncNode(const BookmarkNode * node)184 bool ChromeBookmarkClient::CanSyncNode(const BookmarkNode* node) {
185   return !IsDescendantOfManagedNode(node);
186 }
187 
CanBeEditedByUser(const BookmarkNode * node)188 bool ChromeBookmarkClient::CanBeEditedByUser(const BookmarkNode* node) {
189   return !IsDescendantOfManagedNode(node);
190 }
191 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)192 void 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 
BookmarkModelChanged()209 void ChromeBookmarkClient::BookmarkModelChanged() {
210 }
211 
BookmarkNodeRemoved(BookmarkModel * model,const BookmarkNode * parent,int old_index,const BookmarkNode * node,const std::set<GURL> & removed_urls)212 void 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 
BookmarkAllUserNodesRemoved(BookmarkModel * model,const std::set<GURL> & removed_urls)221 void ChromeBookmarkClient::BookmarkAllUserNodesRemoved(
222     BookmarkModel* model,
223     const std::set<GURL>& removed_urls) {
224   NotifyHistoryOfRemovedURLs(profile_, removed_urls);
225 }
226 
BookmarkModelLoaded(BookmarkModel * model,bool ids_reassigned)227 void 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
LoadExtraNodes(const scoped_refptr<base::DeferredSequencedTaskRunner> & profile_io_runner,BookmarkPermanentNode * managed_node,scoped_ptr<base::ListValue> initial_managed_bookmarks,int64 * next_node_id)236 bookmarks::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 
GetManagedBookmarksDomain()257 std::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