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#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_PRIVET_NOTIFICATIONS_H_
6#define CHROME_BROWSER_LOCAL_DISCOVERY_PRIVET_NOTIFICATIONS_H_
7
8#include <map>
9#include <string>
10
11#include "base/prefs/pref_member.h"
12#include "chrome/browser/local_discovery/privet_device_lister.h"
13#include "chrome/browser/local_discovery/privet_http.h"
14#include "chrome/browser/notifications/notification_delegate.h"
15#include "components/keyed_service/core/keyed_service.h"
16
17class NotificationUIManager;
18
19namespace content {
20class BrowserContext;
21}  // namespace content
22
23namespace local_discovery {
24
25class ServiceDiscoverySharedClient;
26class PrivetDeviceLister;
27class PrivetHTTPAsynchronousFactory;
28class PrivetHTTPResolution;
29struct DeviceDescription;
30
31#if defined(ENABLE_MDNS)
32class PrivetTrafficDetector;
33#endif  // ENABLE_MDNS
34
35// Contains logic related to notifications not tied actually displaying them.
36class PrivetNotificationsListener  {
37 public:
38  class Delegate {
39   public:
40    virtual ~Delegate() {}
41
42    // Notify user of the existence of device |device_name|.
43    virtual void PrivetNotify(bool multiple, bool added) = 0;
44
45    // Remove the noitification for |device_name| if it still exists.
46    virtual void PrivetRemoveNotification() = 0;
47  };
48
49  PrivetNotificationsListener(
50      scoped_ptr<PrivetHTTPAsynchronousFactory> privet_http_factory,
51      Delegate* delegate);
52  virtual ~PrivetNotificationsListener();
53
54  // These two methods are akin to those of PrivetDeviceLister::Delegate. The
55  // user of PrivetNotificationListener should create a PrivetDeviceLister and
56  // forward device notifications to the PrivetNotificationLister.
57  void DeviceChanged(bool added,
58                     const std::string& name,
59                     const DeviceDescription& description);
60  void DeviceRemoved(const std::string& name);
61  virtual void DeviceCacheFlushed();
62
63 private:
64  struct DeviceContext {
65    DeviceContext();
66    ~DeviceContext();
67
68    bool notification_may_be_active;
69    bool registered;
70    scoped_ptr<PrivetJSONOperation> info_operation;
71    scoped_ptr<PrivetHTTPResolution> privet_http_resolution;
72    scoped_ptr<PrivetHTTPClient> privet_http;
73  };
74
75  typedef std::map<std::string, linked_ptr<DeviceContext> > DeviceContextMap;
76
77  void CreateInfoOperation(scoped_ptr<PrivetHTTPClient> http_client);
78  void OnPrivetInfoDone(DeviceContext* device,
79                        const base::DictionaryValue* json_value);
80
81
82  void NotifyDeviceRemoved();
83
84  Delegate* delegate_;
85  scoped_ptr<PrivetDeviceLister> device_lister_;
86  scoped_ptr<PrivetHTTPAsynchronousFactory> privet_http_factory_;
87  DeviceContextMap devices_seen_;
88  int devices_active_;
89};
90
91class PrivetNotificationService
92    : public KeyedService,
93      public PrivetDeviceLister::Delegate,
94      public PrivetNotificationsListener::Delegate,
95      public base::SupportsWeakPtr<PrivetNotificationService> {
96 public:
97  explicit PrivetNotificationService(content::BrowserContext* profile);
98  virtual ~PrivetNotificationService();
99
100  // PrivetDeviceLister::Delegate implementation:
101  virtual void DeviceChanged(bool added, const std::string& name,
102                             const DeviceDescription& description) OVERRIDE;
103  virtual void DeviceRemoved(const std::string& name) OVERRIDE;
104
105  // PrivetNotificationListener::Delegate implementation:
106  virtual void PrivetNotify(bool has_multiple, bool added) OVERRIDE;
107
108  virtual void PrivetRemoveNotification() OVERRIDE;
109  virtual void DeviceCacheFlushed() OVERRIDE;
110
111  static bool IsEnabled();
112  static bool IsForced();
113
114 private:
115  void Start();
116  void OnNotificationsEnabledChanged();
117  void StartLister();
118
119  content::BrowserContext* profile_;
120  scoped_ptr<PrivetDeviceLister> device_lister_;
121  scoped_refptr<ServiceDiscoverySharedClient> service_discovery_client_;
122  scoped_ptr<PrivetNotificationsListener> privet_notifications_listener_;
123  BooleanPrefMember enable_privet_notification_member_;
124
125#if defined(ENABLE_MDNS)
126  scoped_refptr<PrivetTrafficDetector> traffic_detector_;
127#endif  // ENABLE_MDNS
128};
129
130class PrivetNotificationDelegate : public NotificationDelegate {
131 public:
132  explicit PrivetNotificationDelegate(content::BrowserContext* profile);
133
134  // NotificationDelegate implementation.
135  virtual std::string id() const OVERRIDE;
136  virtual content::WebContents* GetWebContents() const OVERRIDE;
137  virtual void Display() OVERRIDE;
138  virtual void Error() OVERRIDE;
139  virtual void Close(bool by_user) OVERRIDE;
140  virtual void Click() OVERRIDE;
141  virtual void ButtonClick(int button_index) OVERRIDE;
142
143 private:
144  void OpenTab(const GURL& url);
145  void DisableNotifications();
146
147  virtual ~PrivetNotificationDelegate();
148
149  content::BrowserContext* profile_;
150};
151
152}  // namespace local_discovery
153
154#endif  // CHROME_BROWSER_LOCAL_DISCOVERY_PRIVET_NOTIFICATIONS_H_
155