blob: 3b40669a20af948039f184b9b1527de02942b1f3 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/local_discovery/privet_notifications.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_context.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
namespace local_discovery {
namespace {
const int kTenMinutesInSeconds = 600;
const char kPrivetInfoKeyUptime[] = "uptime";
const char kPrivetNotificationIDPrefix[] = "privet_notification:";
const char kPrivetNotificationOriginUrl[] = "chrome://devices";
}
PrivetNotificationsListener::PrivetNotificationsListener(
scoped_ptr<PrivetHTTPAsynchronousFactory> privet_http_factory,
Delegate* delegate) : delegate_(delegate) {
privet_http_factory_.swap(privet_http_factory);
}
PrivetNotificationsListener::~PrivetNotificationsListener() {
}
void PrivetNotificationsListener::DeviceChanged(
bool added,
const std::string& name,
const DeviceDescription& description) {
DeviceContextMap::iterator found = devices_seen_.find(name);
if (found != devices_seen_.end()) {
if (!description.id.empty() && // Device is registered
found->second->notification_may_be_active) {
found->second->notification_may_be_active = false;
delegate_->PrivetRemoveNotification(name);
}
return; // Already saw this device.
}
linked_ptr<DeviceContext> device_context(new DeviceContext);
device_context->notification_may_be_active = false;
device_context->registered = !description.id.empty();
device_context->human_readable_name = description.name;
device_context->description = description.description;
devices_seen_.insert(make_pair(name, device_context));
if (!device_context->registered) {
device_context->privet_http_resolution =
privet_http_factory_->CreatePrivetHTTP(
name,
description.address,
base::Bind(&PrivetNotificationsListener::CreateInfoOperation,
base::Unretained(this)));
device_context->privet_http_resolution->Start();
}
}
void PrivetNotificationsListener::CreateInfoOperation(
scoped_ptr<PrivetHTTPClient> http_client) {
std::string name = http_client->GetName();
DeviceContextMap::iterator device_iter = devices_seen_.find(name);
DCHECK(device_iter != devices_seen_.end());
DeviceContext* device = device_iter->second.get();
device->privet_http.swap(http_client);
device->info_operation =
device->privet_http->CreateInfoOperation(this);
device->info_operation->Start();
}
void PrivetNotificationsListener::OnPrivetInfoDone(
PrivetInfoOperation* operation,
int http_code,
const base::DictionaryValue* json_value) {
std::string name = operation->GetHTTPClient()->GetName();
DeviceContextMap::iterator device_iter = devices_seen_.find(name);
DCHECK(device_iter != devices_seen_.end());
DeviceContext* device = device_iter->second.get();
int uptime;
if (!json_value ||
!json_value->GetInteger(kPrivetInfoKeyUptime, &uptime) ||
uptime > kTenMinutesInSeconds) {
return;
}
DCHECK(!device->notification_may_be_active);
device->notification_may_be_active = true;
delegate_->PrivetNotify(name, device->human_readable_name,
device->description);
}
void PrivetNotificationsListener::DeviceRemoved(const std::string& name) {
DCHECK_EQ(1u, devices_seen_.count(name));
DeviceContextMap::iterator device_iter = devices_seen_.find(name);
DCHECK(device_iter != devices_seen_.end());
DeviceContext* device = device_iter->second.get();
device->info_operation.reset();
device->privet_http_resolution.reset();
device->notification_may_be_active = false;
delegate_->PrivetRemoveNotification(name);
}
PrivetNotificationsListener::DeviceContext::DeviceContext() {
}
PrivetNotificationsListener::DeviceContext::~DeviceContext() {
}
PrivetNotificationService::PrivetNotificationService(
content::BrowserContext* profile,
NotificationUIManager* notification_manager)
: profile_(profile),
notification_manager_(notification_manager) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PrivetNotificationService::Start, AsWeakPtr()));
}
PrivetNotificationService::~PrivetNotificationService() {
ServiceDiscoveryHostClientFactory::ReleaseClient();
}
void PrivetNotificationService::DeviceChanged(
bool added,
const std::string& name,
const DeviceDescription& description) {
privet_notifications_listener_->DeviceChanged(added, name, description);
}
void PrivetNotificationService::DeviceRemoved(const std::string& name) {
privet_notifications_listener_->DeviceRemoved(name);
}
void PrivetNotificationService::PrivetNotify(
const std::string& device_name,
const std::string& human_readable_name,
const std::string& description) {
Profile* profile_object = Profile::FromBrowserContext(profile_);
Notification notification(
GURL(kPrivetNotificationOriginUrl),
GURL(),
l10n_util::GetStringUTF16(IDS_LOCAL_DISOCVERY_NOTIFICATION_TITLE_PRINTER),
l10n_util::GetStringFUTF16(
IDS_LOCAL_DISOCVERY_NOTIFICATION_CONTENTS_PRINTER,
UTF8ToUTF16(human_readable_name)),
WebKit::WebTextDirectionDefault,
l10n_util::GetStringUTF16(
IDS_LOCAL_DISOCVERY_NOTIFICATION_DISPLAY_SOURCE_PRINTER),
UTF8ToUTF16(kPrivetNotificationIDPrefix +
device_name),
new PrivetNotificationDelegate(device_name));
notification_manager_->Add(notification, profile_object);
}
void PrivetNotificationService::PrivetRemoveNotification(
const std::string& device_name) {
notification_manager_->CancelById(kPrivetNotificationIDPrefix + device_name);
}
void PrivetNotificationService::Start() {
service_discovery_client_ = ServiceDiscoveryHostClientFactory::GetClient();
device_lister_.reset(new PrivetDeviceListerImpl(service_discovery_client_,
this));
device_lister_->Start();
scoped_ptr<PrivetHTTPAsynchronousFactory> http_factory(
new PrivetHTTPAsynchronousFactoryImpl(service_discovery_client_.get(),
profile_->GetRequestContext()));
privet_notifications_listener_.reset(new PrivetNotificationsListener(
http_factory.Pass(), this));
}
PrivetNotificationDelegate::PrivetNotificationDelegate(
const std::string& device_id) : device_id_(device_id) {
}
PrivetNotificationDelegate::~PrivetNotificationDelegate() {
}
std::string PrivetNotificationDelegate::id() const {
return kPrivetNotificationIDPrefix + device_id_;
}
content::RenderViewHost* PrivetNotificationDelegate::GetRenderViewHost() const {
return NULL;
}
void PrivetNotificationDelegate::Display() {
}
void PrivetNotificationDelegate::Error() {
LOG(ERROR) << "Error displaying privet notification " << device_id_;
}
void PrivetNotificationDelegate::Close(bool by_user) {
}
void PrivetNotificationDelegate::Click() {
}
} // namespace local_discovery