1 // Copyright (c) 2012 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.
5 #include "ppapi/proxy/ppb_network_monitor_private_proxy.h"
7 #include "ppapi/proxy/enter_proxy.h"
8 #include "ppapi/proxy/ppapi_messages.h"
9 #include "ppapi/shared_impl/proxy_lock.h"
10 #include "ppapi/thunk/ppb_network_monitor_private_api.h"
15 class PPB_NetworkMonitor_Private_Proxy::NetworkMonitor
17 public thunk::PPB_NetworkMonitor_Private_API
,
18 public base::SupportsWeakPtr
<
19 PPB_NetworkMonitor_Private_Proxy::NetworkMonitor
> {
21 NetworkMonitor(PP_Instance instance
,
22 PPB_NetworkMonitor_Private_Proxy
* proxy
,
23 PPB_NetworkMonitor_Callback callback
,
25 : Resource(OBJECT_IS_PROXY
, instance
),
28 user_data_(user_data
) {
31 virtual ~NetworkMonitor() {
32 proxy_
->OnNetworkMonitorDeleted(this, pp_instance());
36 // Resource overrides.
37 virtual ppapi::thunk::PPB_NetworkMonitor_Private_API
*
38 AsPPB_NetworkMonitor_Private_API() OVERRIDE
{
42 // This is invoked when a network list is received for this monitor (either
43 // initially or on a change). It acquires the ProxyLock inside because
44 // ObserverListThreadSafe does not support Bind/Closure, otherwise we would
45 // wrap the call with a lock using RunWhileLocked.
46 void OnNetworkListReceivedLocks(
47 const scoped_refptr
<NetworkListStorage
>& list
) {
49 PP_Resource list_resource
=
50 PPB_NetworkList_Private_Shared::Create(
51 OBJECT_IS_PROXY
, pp_instance(), list
);
52 CallWhileUnlocked(callback_
, user_data_
, list_resource
);
56 PPB_NetworkMonitor_Private_Proxy
* proxy_
;
57 PPB_NetworkMonitor_Callback callback_
;
60 DISALLOW_COPY_AND_ASSIGN(NetworkMonitor
);
63 PPB_NetworkMonitor_Private_Proxy::PPB_NetworkMonitor_Private_Proxy(
64 Dispatcher
* dispatcher
)
65 : InterfaceProxy(dispatcher
),
66 monitors_(new ObserverListThreadSafe
<NetworkMonitor
>()),
70 PPB_NetworkMonitor_Private_Proxy::~PPB_NetworkMonitor_Private_Proxy() {
71 monitors_
->AssertEmpty();
75 PP_Resource
PPB_NetworkMonitor_Private_Proxy::CreateProxyResource(
77 PPB_NetworkMonitor_Callback callback
,
79 // TODO(dmichael): Check that this thread has a valid message loop associated
84 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
87 PPB_NetworkMonitor_Private_Proxy
* proxy
=
88 static_cast<PPB_NetworkMonitor_Private_Proxy
*>(
89 dispatcher
->GetInterfaceProxy(kApiID
));
93 scoped_refptr
<NetworkMonitor
> result(
94 new NetworkMonitor(instance
, proxy
, callback
, user_data
));
95 proxy
->monitors_
->AddObserver(result
.get());
97 proxy
->monitors_count_
++;
98 if (proxy
->monitors_count_
== 1) {
99 // If that is the first network monitor then send Start message.
100 PluginGlobals::Get()->GetBrowserSender()->Send(
101 new PpapiHostMsg_PPBNetworkMonitor_Start(
102 dispatcher
->plugin_dispatcher_id()));
104 // We could have received network list message after sending the
105 // previous Stop message. This list is stale now, so reset it
107 proxy
->current_list_
= NULL
;
108 } else if (proxy
->current_list_
.get()) {
109 base::MessageLoop::current()->PostTask(
111 base::Bind(&NetworkMonitor::OnNetworkListReceivedLocks
,
113 proxy
->current_list_
));
116 return result
->GetReference();
119 bool PPB_NetworkMonitor_Private_Proxy::OnMessageReceived(
120 const IPC::Message
& msg
) {
122 IPC_BEGIN_MESSAGE_MAP(PPB_NetworkMonitor_Private_Proxy
, msg
)
123 IPC_MESSAGE_HANDLER(PpapiMsg_PPBNetworkMonitor_NetworkList
,
124 OnPluginMsgNetworkList
)
125 IPC_MESSAGE_UNHANDLED(handled
= false)
126 IPC_END_MESSAGE_MAP()
130 void PPB_NetworkMonitor_Private_Proxy::OnPluginMsgNetworkList(
131 uint32 plugin_dispatcher_id
,
132 const ppapi::NetworkList
& list
) {
133 scoped_refptr
<NetworkListStorage
> list_storage(new NetworkListStorage(list
));
134 current_list_
= list_storage
;
135 monitors_
->Notify(&NetworkMonitor::OnNetworkListReceivedLocks
, list_storage
);
138 void PPB_NetworkMonitor_Private_Proxy::OnNetworkMonitorDeleted(
139 NetworkMonitor
* monitor
,
140 PP_Instance instance
) {
141 monitors_
->RemoveObserver(monitor
);
143 if (monitors_count_
== 0) {
144 // Send Stop message if that was the last NetworkMonitor.
145 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
147 PluginGlobals::Get()->GetBrowserSender()->Send(
148 new PpapiHostMsg_PPBNetworkMonitor_Stop(
149 dispatcher
->plugin_dispatcher_id()));
151 current_list_
= NULL
;