| // Copyright (c) 2012 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 "ppapi/proxy/ppb_network_monitor_private_proxy.h" |
| |
| #include "ppapi/proxy/enter_proxy.h" |
| #include "ppapi/proxy/ppapi_messages.h" |
| #include "ppapi/shared_impl/proxy_lock.h" |
| #include "ppapi/thunk/ppb_network_monitor_private_api.h" |
| |
| namespace ppapi { |
| namespace proxy { |
| |
| class PPB_NetworkMonitor_Private_Proxy::NetworkMonitor |
| : public Resource, |
| public thunk::PPB_NetworkMonitor_Private_API, |
| public base::SupportsWeakPtr< |
| PPB_NetworkMonitor_Private_Proxy::NetworkMonitor> { |
| public: |
| NetworkMonitor(PP_Instance instance, |
| PPB_NetworkMonitor_Private_Proxy* proxy, |
| PPB_NetworkMonitor_Callback callback, |
| void* user_data) |
| : Resource(OBJECT_IS_PROXY, instance), |
| proxy_(proxy), |
| callback_(callback), |
| user_data_(user_data) { |
| } |
| |
| virtual ~NetworkMonitor() { |
| proxy_->OnNetworkMonitorDeleted(this, pp_instance()); |
| } |
| |
| |
| // Resource overrides. |
| virtual ppapi::thunk::PPB_NetworkMonitor_Private_API* |
| AsPPB_NetworkMonitor_Private_API() OVERRIDE { |
| return this; |
| } |
| |
| // This is invoked when a network list is received for this monitor (either |
| // initially or on a change). It acquires the ProxyLock inside because |
| // ObserverListThreadSafe does not support Bind/Closure, otherwise we would |
| // wrap the call with a lock using RunWhileLocked. |
| void OnNetworkListReceivedLocks( |
| const scoped_refptr<NetworkListStorage>& list) { |
| ProxyAutoLock lock; |
| PP_Resource list_resource = |
| PPB_NetworkList_Private_Shared::Create( |
| OBJECT_IS_PROXY, pp_instance(), list); |
| CallWhileUnlocked(callback_, user_data_, list_resource); |
| } |
| |
| private: |
| PPB_NetworkMonitor_Private_Proxy* proxy_; |
| PPB_NetworkMonitor_Callback callback_; |
| void* user_data_; |
| |
| DISALLOW_COPY_AND_ASSIGN(NetworkMonitor); |
| }; |
| |
| PPB_NetworkMonitor_Private_Proxy::PPB_NetworkMonitor_Private_Proxy( |
| Dispatcher* dispatcher) |
| : InterfaceProxy(dispatcher), |
| monitors_(new ObserverListThreadSafe<NetworkMonitor>()), |
| monitors_count_(0) { |
| } |
| |
| PPB_NetworkMonitor_Private_Proxy::~PPB_NetworkMonitor_Private_Proxy() { |
| monitors_->AssertEmpty(); |
| } |
| |
| // static |
| PP_Resource PPB_NetworkMonitor_Private_Proxy::CreateProxyResource( |
| PP_Instance instance, |
| PPB_NetworkMonitor_Callback callback, |
| void* user_data) { |
| // TODO(dmichael): Check that this thread has a valid message loop associated |
| // with it. |
| if (!callback) |
| return 0; |
| |
| PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
| if (!dispatcher) |
| return 0; |
| PPB_NetworkMonitor_Private_Proxy* proxy = |
| static_cast<PPB_NetworkMonitor_Private_Proxy*>( |
| dispatcher->GetInterfaceProxy(kApiID)); |
| if (!proxy) |
| return 0; |
| |
| scoped_refptr<NetworkMonitor> result( |
| new NetworkMonitor(instance, proxy, callback, user_data)); |
| proxy->monitors_->AddObserver(result.get()); |
| |
| proxy->monitors_count_++; |
| if (proxy->monitors_count_ == 1) { |
| // If that is the first network monitor then send Start message. |
| PluginGlobals::Get()->GetBrowserSender()->Send( |
| new PpapiHostMsg_PPBNetworkMonitor_Start( |
| dispatcher->plugin_dispatcher_id())); |
| |
| // We could have received network list message after sending the |
| // previous Stop message. This list is stale now, so reset it |
| // here. |
| proxy->current_list_ = NULL; |
| } else if (proxy->current_list_.get()) { |
| base::MessageLoop::current()->PostTask( |
| FROM_HERE, |
| base::Bind(&NetworkMonitor::OnNetworkListReceivedLocks, |
| result->AsWeakPtr(), |
| proxy->current_list_)); |
| } |
| |
| return result->GetReference(); |
| } |
| |
| bool PPB_NetworkMonitor_Private_Proxy::OnMessageReceived( |
| const IPC::Message& msg) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(PPB_NetworkMonitor_Private_Proxy, msg) |
| IPC_MESSAGE_HANDLER(PpapiMsg_PPBNetworkMonitor_NetworkList, |
| OnPluginMsgNetworkList) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| void PPB_NetworkMonitor_Private_Proxy::OnPluginMsgNetworkList( |
| uint32 plugin_dispatcher_id, |
| const ppapi::NetworkList& list) { |
| scoped_refptr<NetworkListStorage> list_storage(new NetworkListStorage(list)); |
| current_list_ = list_storage; |
| monitors_->Notify(&NetworkMonitor::OnNetworkListReceivedLocks, list_storage); |
| } |
| |
| void PPB_NetworkMonitor_Private_Proxy::OnNetworkMonitorDeleted( |
| NetworkMonitor* monitor, |
| PP_Instance instance) { |
| monitors_->RemoveObserver(monitor); |
| monitors_count_--; |
| if (monitors_count_ == 0) { |
| // Send Stop message if that was the last NetworkMonitor. |
| PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
| if (dispatcher) { |
| PluginGlobals::Get()->GetBrowserSender()->Send( |
| new PpapiHostMsg_PPBNetworkMonitor_Stop( |
| dispatcher->plugin_dispatcher_id())); |
| } |
| current_list_ = NULL; |
| } |
| } |
| |
| } // namespace proxy |
| } // namespace ppapi |