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

Side by Side Diff: chrome/browser/local_discovery/privet_notifications.cc

Issue 1553333002: Move cloud print specific files out of local_discovery (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@moveprn
Patch Set: Created 4 years, 11 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
OLDNEW
(Empty)
1 // Copyright 2013 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/local_discovery/privet_notifications.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/location.h"
12 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/rand_util.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/local_discovery/privet_device_lister_impl.h"
20 #include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h"
21 #include "chrome/browser/local_discovery/service_discovery_shared_client.h"
22 #include "chrome/browser/notifications/notification.h"
23 #include "chrome/browser/notifications/notification_ui_manager.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/signin/signin_manager_factory.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_finder.h"
28 #include "chrome/browser/ui/browser_navigator_params.h"
29 #include "chrome/browser/ui/browser_window.h"
30 #include "chrome/browser/ui/host_desktop.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
33 #include "chrome/common/chrome_switches.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/grit/generated_resources.h"
36 #include "components/signin/core/browser/signin_manager_base.h"
37 #include "content/public/browser/browser_context.h"
38 #include "content/public/browser/navigation_controller.h"
39 #include "content/public/browser/web_contents.h"
40 #include "grit/theme_resources.h"
41 #include "ui/base/l10n/l10n_util.h"
42 #include "ui/base/page_transition_types.h"
43 #include "ui/base/resource/resource_bundle.h"
44 #include "ui/message_center/notifier_settings.h"
45
46 #if defined(ENABLE_MDNS)
47 #include "chrome/browser/local_discovery/privet_traffic_detector.h"
48 #endif
49
50 namespace local_discovery {
51
52 namespace {
53
54 const int kTenMinutesInSeconds = 600;
55 const char kPrivetInfoKeyUptime[] = "uptime";
56 const char kPrivetNotificationID[] = "privet_notification";
57 const char kPrivetNotificationOriginUrl[] = "chrome://devices";
58 const int kStartDelaySeconds = 5;
59
60 enum PrivetNotificationsEvent {
61 PRIVET_SERVICE_STARTED,
62 PRIVET_LISTER_STARTED,
63 PRIVET_DEVICE_CHANGED,
64 PRIVET_INFO_DONE,
65 PRIVET_NOTIFICATION_SHOWN,
66 PRIVET_NOTIFICATION_CANCELED,
67 PRIVET_NOTIFICATION_CLICKED,
68 PRIVET_DISABLE_NOTIFICATIONS_CLICKED,
69 PRIVET_EVENT_MAX,
70 };
71
72 void ReportPrivetUmaEvent(PrivetNotificationsEvent privet_event) {
73 UMA_HISTOGRAM_ENUMERATION("LocalDiscovery.PrivetNotificationsEvent",
74 privet_event, PRIVET_EVENT_MAX);
75 }
76
77 } // namespace
78
79 PrivetNotificationsListener::PrivetNotificationsListener(
80 scoped_ptr<PrivetHTTPAsynchronousFactory> privet_http_factory,
81 Delegate* delegate)
82 : delegate_(delegate), devices_active_(0) {
83 privet_http_factory_.swap(privet_http_factory);
84 }
85
86 PrivetNotificationsListener::~PrivetNotificationsListener() {
87 }
88
89 void PrivetNotificationsListener::DeviceChanged(
90 bool added,
91 const std::string& name,
92 const DeviceDescription& description) {
93 ReportPrivetUmaEvent(PRIVET_DEVICE_CHANGED);
94 DeviceContextMap::iterator found = devices_seen_.find(name);
95 if (found != devices_seen_.end()) {
96 if (!description.id.empty() && // Device is registered
97 found->second->notification_may_be_active) {
98 found->second->notification_may_be_active = false;
99 NotifyDeviceRemoved();
100 }
101 return; // Already saw this device.
102 }
103
104 linked_ptr<DeviceContext> device_context(new DeviceContext);
105
106 device_context->notification_may_be_active = false;
107 device_context->registered = !description.id.empty();
108
109 devices_seen_.insert(make_pair(name, device_context));
110
111 if (!device_context->registered) {
112 device_context->privet_http_resolution =
113 privet_http_factory_->CreatePrivetHTTP(name);
114 device_context->privet_http_resolution->Start(
115 description.address,
116 base::Bind(&PrivetNotificationsListener::CreateInfoOperation,
117 base::Unretained(this)));
118 }
119 }
120
121 void PrivetNotificationsListener::CreateInfoOperation(
122 scoped_ptr<PrivetHTTPClient> http_client) {
123 if (!http_client) {
124 // Do nothing if resolution fails.
125 return;
126 }
127
128 std::string name = http_client->GetName();
129 DeviceContextMap::iterator device_iter = devices_seen_.find(name);
130 if (device_iter == devices_seen_.end())
131 return;
132 DeviceContext* device = device_iter->second.get();
133 device->privet_http.swap(http_client);
134 device->info_operation = device->privet_http->CreateInfoOperation(
135 base::Bind(&PrivetNotificationsListener::OnPrivetInfoDone,
136 base::Unretained(this),
137 device));
138 device->info_operation->Start();
139 }
140
141 void PrivetNotificationsListener::OnPrivetInfoDone(
142 DeviceContext* device,
143 const base::DictionaryValue* json_value) {
144 int uptime;
145
146 if (!json_value ||
147 !json_value->GetInteger(kPrivetInfoKeyUptime, &uptime) ||
148 uptime > kTenMinutesInSeconds) {
149 return;
150 }
151
152 DCHECK(!device->notification_may_be_active);
153 device->notification_may_be_active = true;
154 devices_active_++;
155 delegate_->PrivetNotify(devices_active_, true);
156 }
157
158 void PrivetNotificationsListener::DeviceRemoved(const std::string& name) {
159 DeviceContextMap::iterator device_iter = devices_seen_.find(name);
160 if (device_iter == devices_seen_.end())
161 return;
162 DeviceContext* device = device_iter->second.get();
163
164 device->info_operation.reset();
165 device->privet_http_resolution.reset();
166 device->notification_may_be_active = false;
167 NotifyDeviceRemoved();
168 }
169
170 void PrivetNotificationsListener::DeviceCacheFlushed() {
171 for (DeviceContextMap::iterator i = devices_seen_.begin();
172 i != devices_seen_.end(); ++i) {
173 DeviceContext* device = i->second.get();
174
175 device->info_operation.reset();
176 device->privet_http_resolution.reset();
177 if (device->notification_may_be_active) {
178 device->notification_may_be_active = false;
179 }
180 }
181
182 devices_active_ = 0;
183 delegate_->PrivetRemoveNotification();
184 }
185
186 void PrivetNotificationsListener::NotifyDeviceRemoved() {
187 devices_active_--;
188 if (devices_active_ == 0) {
189 delegate_->PrivetRemoveNotification();
190 } else {
191 delegate_->PrivetNotify(devices_active_, false);
192 }
193 }
194
195 PrivetNotificationsListener::DeviceContext::DeviceContext() {
196 }
197
198 PrivetNotificationsListener::DeviceContext::~DeviceContext() {
199 }
200
201 PrivetNotificationService::PrivetNotificationService(
202 content::BrowserContext* profile)
203 : profile_(profile) {
204 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
205 FROM_HERE, base::Bind(&PrivetNotificationService::Start, AsWeakPtr()),
206 base::TimeDelta::FromSeconds(kStartDelaySeconds +
207 base::RandInt(0, kStartDelaySeconds / 4)));
208 }
209
210 PrivetNotificationService::~PrivetNotificationService() {
211 }
212
213 void PrivetNotificationService::DeviceChanged(
214 bool added,
215 const std::string& name,
216 const DeviceDescription& description) {
217 privet_notifications_listener_->DeviceChanged(added, name, description);
218 }
219
220 void PrivetNotificationService::DeviceRemoved(const std::string& name) {
221 privet_notifications_listener_->DeviceRemoved(name);
222 }
223
224 void PrivetNotificationService::DeviceCacheFlushed() {
225 privet_notifications_listener_->DeviceCacheFlushed();
226 }
227
228 // static
229 bool PrivetNotificationService::IsEnabled() {
230 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
231 return !command_line->HasSwitch(
232 switches::kDisableDeviceDiscoveryNotifications);
233 }
234
235 // static
236 bool PrivetNotificationService::IsForced() {
237 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
238 return command_line->HasSwitch(switches::kEnableDeviceDiscoveryNotifications);
239 }
240
241 void PrivetNotificationService::PrivetNotify(int devices_active,
242 bool added) {
243 base::string16 product_name = l10n_util::GetStringUTF16(
244 IDS_LOCAL_DISCOVERY_SERVICE_NAME_PRINTER);
245
246 base::string16 title = l10n_util::GetPluralStringFUTF16(
247 IDS_LOCAL_DISCOVERY_NOTIFICATION_TITLE_PRINTER, devices_active);
248 base::string16 body = l10n_util::GetPluralStringFUTF16(
249 IDS_LOCAL_DISCOVERY_NOTIFICATION_CONTENTS_PRINTER, devices_active);
250
251 Profile* profile_object = Profile::FromBrowserContext(profile_);
252 message_center::RichNotificationData rich_notification_data;
253
254 rich_notification_data.buttons.push_back(
255 message_center::ButtonInfo(l10n_util::GetStringUTF16(
256 IDS_LOCAL_DISCOVERY_NOTIFICATION_BUTTON_PRINTER)));
257
258 rich_notification_data.buttons.push_back(
259 message_center::ButtonInfo(l10n_util::GetStringUTF16(
260 IDS_LOCAL_DISCOVERY_NOTIFICATIONS_DISABLE_BUTTON_LABEL)));
261
262 Notification notification(
263 message_center::NOTIFICATION_TYPE_SIMPLE, title, body,
264 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
265 IDR_LOCAL_DISCOVERY_CLOUDPRINT_ICON),
266 message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT,
267 kPrivetNotificationID),
268 product_name, GURL(kPrivetNotificationOriginUrl), kPrivetNotificationID,
269 rich_notification_data, new PrivetNotificationDelegate(profile_));
270
271 bool updated = g_browser_process->notification_ui_manager()->Update(
272 notification, profile_object);
273 if (!updated && added && !LocalDiscoveryUIHandler::GetHasVisible()) {
274 ReportPrivetUmaEvent(PRIVET_NOTIFICATION_SHOWN);
275 g_browser_process->notification_ui_manager()->Add(notification,
276 profile_object);
277 }
278 }
279
280 void PrivetNotificationService::PrivetRemoveNotification() {
281 ReportPrivetUmaEvent(PRIVET_NOTIFICATION_CANCELED);
282 Profile* profile_object = Profile::FromBrowserContext(profile_);
283 g_browser_process->notification_ui_manager()->CancelById(
284 kPrivetNotificationID,
285 NotificationUIManager::GetProfileID(profile_object));
286 }
287
288 void PrivetNotificationService::Start() {
289 #if defined(CHROMEOS)
290 SigninManagerBase* signin_manager =
291 SigninManagerFactory::GetForProfileIfExists(
292 Profile::FromBrowserContext(profile_));
293
294 if (!signin_manager || !signin_manager->IsAuthenticated())
295 return;
296 #endif
297
298 enable_privet_notification_member_.Init(
299 prefs::kLocalDiscoveryNotificationsEnabled,
300 Profile::FromBrowserContext(profile_)->GetPrefs(),
301 base::Bind(&PrivetNotificationService::OnNotificationsEnabledChanged,
302 base::Unretained(this)));
303 OnNotificationsEnabledChanged();
304 }
305
306 void PrivetNotificationService::OnNotificationsEnabledChanged() {
307 #if defined(ENABLE_MDNS)
308 if (IsForced()) {
309 StartLister();
310 } else if (*enable_privet_notification_member_) {
311 ReportPrivetUmaEvent(PRIVET_SERVICE_STARTED);
312 traffic_detector_ =
313 new PrivetTrafficDetector(
314 net::ADDRESS_FAMILY_IPV4,
315 base::Bind(&PrivetNotificationService::StartLister, AsWeakPtr()));
316 traffic_detector_->Start();
317 } else {
318 traffic_detector_ = NULL;
319 device_lister_.reset();
320 service_discovery_client_ = NULL;
321 privet_notifications_listener_.reset();
322 }
323 #else
324 if (IsForced() || *enable_privet_notification_member_) {
325 StartLister();
326 } else {
327 device_lister_.reset();
328 service_discovery_client_ = NULL;
329 privet_notifications_listener_.reset();
330 }
331 #endif
332 }
333
334 void PrivetNotificationService::StartLister() {
335 ReportPrivetUmaEvent(PRIVET_LISTER_STARTED);
336 #if defined(ENABLE_MDNS)
337 traffic_detector_ = NULL;
338 #endif // ENABLE_MDNS
339 service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance();
340 device_lister_.reset(
341 new PrivetDeviceListerImpl(service_discovery_client_.get(), this));
342 device_lister_->Start();
343 device_lister_->DiscoverNewDevices(false);
344
345 scoped_ptr<PrivetHTTPAsynchronousFactory> http_factory(
346 PrivetHTTPAsynchronousFactory::CreateInstance(
347 profile_->GetRequestContext()));
348
349 privet_notifications_listener_.reset(
350 new PrivetNotificationsListener(std::move(http_factory), this));
351 }
352
353 PrivetNotificationDelegate::PrivetNotificationDelegate(
354 content::BrowserContext* profile)
355 : profile_(profile) {
356 }
357
358 PrivetNotificationDelegate::~PrivetNotificationDelegate() {
359 }
360
361 std::string PrivetNotificationDelegate::id() const {
362 return kPrivetNotificationID;
363 }
364
365 void PrivetNotificationDelegate::ButtonClick(int button_index) {
366 if (button_index == 0) {
367 ReportPrivetUmaEvent(PRIVET_NOTIFICATION_CLICKED);
368 OpenTab(GURL(kPrivetNotificationOriginUrl));
369 } else if (button_index == 1) {
370 ReportPrivetUmaEvent(PRIVET_DISABLE_NOTIFICATIONS_CLICKED);
371 DisableNotifications();
372 }
373 }
374
375 void PrivetNotificationDelegate::OpenTab(const GURL& url) {
376 Profile* profile_obj = Profile::FromBrowserContext(profile_);
377
378 chrome::NavigateParams params(profile_obj,
379 url,
380 ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
381 params.disposition = NEW_FOREGROUND_TAB;
382 chrome::Navigate(&params);
383 }
384
385 void PrivetNotificationDelegate::DisableNotifications() {
386 Profile* profile_obj = Profile::FromBrowserContext(profile_);
387
388 profile_obj->GetPrefs()->SetBoolean(
389 prefs::kLocalDiscoveryNotificationsEnabled,
390 false);
391 }
392
393 } // namespace local_discovery
OLDNEW
« no previous file with comments | « chrome/browser/local_discovery/privet_notifications.h ('k') | chrome/browser/local_discovery/privet_notifications_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698