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 "content/browser/push_messaging_message_filter.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/strings/string_number_conversions.h"
11#include "content/browser/renderer_host/render_process_host_impl.h"
12#include "content/browser/service_worker/service_worker_context_wrapper.h"
13#include "content/common/push_messaging_messages.h"
14#include "content/public/browser/browser_context.h"
15#include "content/public/browser/browser_thread.h"
16#include "content/public/browser/push_messaging_service.h"
17
18namespace content {
19
20PushMessagingMessageFilter::PushMessagingMessageFilter(
21    int render_process_id,
22    ServiceWorkerContextWrapper* service_worker_context)
23    : BrowserMessageFilter(PushMessagingMsgStart),
24      render_process_id_(render_process_id),
25      service_worker_context_(service_worker_context),
26      service_(NULL),
27      weak_factory_(this) {
28}
29
30PushMessagingMessageFilter::~PushMessagingMessageFilter() {}
31
32bool PushMessagingMessageFilter::OnMessageReceived(
33    const IPC::Message& message) {
34  bool handled = true;
35  IPC_BEGIN_MESSAGE_MAP(PushMessagingMessageFilter, message)
36    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Register, OnRegister)
37    IPC_MESSAGE_UNHANDLED(handled = false)
38  IPC_END_MESSAGE_MAP()
39  return handled;
40}
41
42void PushMessagingMessageFilter::OnRegister(int render_frame_id,
43                                            int callbacks_id,
44                                            const std::string& sender_id,
45                                            bool user_gesture,
46                                            int service_worker_provider_id) {
47  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
48  // TODO(mvanouwerkerk): Validate arguments?
49  ServiceWorkerProviderHost* service_worker_host =
50      service_worker_context_->context()->GetProviderHost(
51          render_process_id_, service_worker_provider_id);
52  if (!service_worker_host || !service_worker_host->active_version()) {
53    Send(new PushMessagingMsg_RegisterError(
54        render_frame_id,
55        callbacks_id,
56        PUSH_MESSAGING_STATUS_REGISTRATION_FAILED_NO_SERVICE_WORKER));
57    return;
58  }
59  BrowserThread::PostTask(
60      BrowserThread::UI,
61      FROM_HERE,
62      base::Bind(&PushMessagingMessageFilter::DoRegister,
63                 weak_factory_.GetWeakPtr(),
64                 render_frame_id,
65                 callbacks_id,
66                 sender_id,
67                 user_gesture,
68                 service_worker_host->active_version()->scope().GetOrigin(),
69                 service_worker_host->active_version()->registration_id()));
70}
71
72void PushMessagingMessageFilter::DoRegister(
73    int render_frame_id,
74    int callbacks_id,
75    const std::string& sender_id,
76    bool user_gesture,
77    const GURL& origin,
78    int64 service_worker_registration_id) {
79  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
80  if (!service()) {
81    Send(new PushMessagingMsg_RegisterError(
82        render_frame_id,
83        callbacks_id,
84        PUSH_MESSAGING_STATUS_REGISTRATION_FAILED_SERVICE_NOT_AVAILABLE));
85    return;
86  }
87  service()->Register(origin,
88                      service_worker_registration_id,
89                      sender_id,
90                      render_process_id_,
91                      render_frame_id,
92                      user_gesture,
93                      base::Bind(&PushMessagingMessageFilter::DidRegister,
94                                 weak_factory_.GetWeakPtr(),
95                                 render_frame_id,
96                                 callbacks_id));
97}
98
99void PushMessagingMessageFilter::DidRegister(
100    int render_frame_id,
101    int callbacks_id,
102    const GURL& push_endpoint,
103    const std::string& push_registration_id,
104    PushMessagingStatus status) {
105  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
106  if (status == PUSH_MESSAGING_STATUS_OK) {
107    Send(new PushMessagingMsg_RegisterSuccess(
108        render_frame_id, callbacks_id, push_endpoint, push_registration_id));
109  } else {
110    Send(new PushMessagingMsg_RegisterError(
111        render_frame_id, callbacks_id, status));
112  }
113}
114
115PushMessagingService* PushMessagingMessageFilter::service() {
116  if (!service_) {
117    RenderProcessHost* process_host =
118        RenderProcessHost::FromID(render_process_id_);
119    if (!process_host)
120      return NULL;
121    service_ = process_host->GetBrowserContext()->GetPushMessagingService();
122  }
123  return service_;
124}
125
126}  // namespace content
127