| OLD | NEW | 
|---|
|  | (Empty) | 
| 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. |  | 
| 4 |  | 
| 5 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h" |  | 
| 6 |  | 
| 7 #include <cmath> |  | 
| 8 #include <cstddef> |  | 
| 9 #include <map> |  | 
| 10 #include <queue> |  | 
| 11 |  | 
| 12 #include "base/bind.h" |  | 
| 13 #include "base/callback.h" |  | 
| 14 #include "base/command_line.h" |  | 
| 15 #include "base/files/file_path.h" |  | 
| 16 #include "base/files/file_util_proxy.h" |  | 
| 17 #include "base/logging.h" |  | 
| 18 #include "base/platform_file.h" |  | 
| 19 #include "base/strings/string_split.h" |  | 
| 20 #include "base/sync_socket.h" |  | 
| 21 #include "base/time/time.h" |  | 
| 22 #include "content/child/child_process.h" |  | 
| 23 #include "content/child/npapi/webplugin.h" |  | 
| 24 #include "content/common/child_process_messages.h" |  | 
| 25 #include "content/common/gpu/client/context_provider_command_buffer.h" |  | 
| 26 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" |  | 
| 27 #include "content/common/pepper_messages.h" |  | 
| 28 #include "content/common/view_messages.h" |  | 
| 29 #include "content/public/common/content_switches.h" |  | 
| 30 #include "content/public/common/context_menu_params.h" |  | 
| 31 #include "content/public/common/media_stream_request.h" |  | 
| 32 #include "content/public/common/page_zoom.h" |  | 
| 33 #include "content/public/common/referrer.h" |  | 
| 34 #include "content/public/common/webplugininfo.h" |  | 
| 35 #include "content/public/renderer/content_renderer_client.h" |  | 
| 36 #include "content/renderer/gamepad_shared_memory_reader.h" |  | 
| 37 #include "content/renderer/media/media_stream_dispatcher.h" |  | 
| 38 #include "content/renderer/p2p/socket_dispatcher.h" |  | 
| 39 #include "content/renderer/pepper/content_renderer_pepper_host_factory.h" |  | 
| 40 #include "content/renderer/pepper/host_dispatcher_wrapper.h" |  | 
| 41 #include "content/renderer/pepper/pepper_broker.h" |  | 
| 42 #include "content/renderer/pepper/pepper_browser_connection.h" |  | 
| 43 #include "content/renderer/pepper/pepper_file_system_host.h" |  | 
| 44 #include "content/renderer/pepper/pepper_graphics_2d_host.h" |  | 
| 45 #include "content/renderer/pepper/pepper_hung_plugin_filter.h" |  | 
| 46 #include "content/renderer/pepper/pepper_in_process_resource_creation.h" |  | 
| 47 #include "content/renderer/pepper/pepper_in_process_router.h" |  | 
| 48 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" |  | 
| 49 #include "content/renderer/pepper/pepper_plugin_registry.h" |  | 
| 50 #include "content/renderer/pepper/pepper_url_loader_host.h" |  | 
| 51 #include "content/renderer/pepper/pepper_webplugin_impl.h" |  | 
| 52 #include "content/renderer/pepper/plugin_module.h" |  | 
| 53 #include "content/renderer/pepper/ppb_tcp_server_socket_private_impl.h" |  | 
| 54 #include "content/renderer/pepper/ppb_tcp_socket_private_impl.h" |  | 
| 55 #include "content/renderer/pepper/renderer_ppapi_host_impl.h" |  | 
| 56 #include "content/renderer/pepper/resource_helper.h" |  | 
| 57 #include "content/renderer/pepper/url_response_info_util.h" |  | 
| 58 #include "content/renderer/render_thread_impl.h" |  | 
| 59 #include "content/renderer/render_view_impl.h" |  | 
| 60 #include "content/renderer/render_widget_fullscreen_pepper.h" |  | 
| 61 #include "content/renderer/webplugin_delegate_proxy.h" |  | 
| 62 #include "ipc/ipc_channel_handle.h" |  | 
| 63 #include "ipc/ipc_platform_file.h" |  | 
| 64 #include "media/video/capture/video_capture_proxy.h" |  | 
| 65 #include "ppapi/c/dev/pp_video_dev.h" |  | 
| 66 #include "ppapi/c/pp_errors.h" |  | 
| 67 #include "ppapi/c/private/ppb_flash.h" |  | 
| 68 #include "ppapi/proxy/ppapi_messages.h" |  | 
| 69 #include "ppapi/proxy/url_loader_resource.h" |  | 
| 70 #include "ppapi/shared_impl/api_id.h" |  | 
| 71 #include "ppapi/shared_impl/file_path.h" |  | 
| 72 #include "ppapi/shared_impl/platform_file.h" |  | 
| 73 #include "ppapi/shared_impl/ppapi_globals.h" |  | 
| 74 #include "ppapi/shared_impl/ppapi_preferences.h" |  | 
| 75 #include "ppapi/shared_impl/ppb_device_ref_shared.h" |  | 
| 76 #include "ppapi/shared_impl/ppp_instance_combined.h" |  | 
| 77 #include "ppapi/shared_impl/resource_tracker.h" |  | 
| 78 #include "ppapi/shared_impl/socket_option_data.h" |  | 
| 79 #include "ppapi/thunk/enter.h" |  | 
| 80 #include "ppapi/thunk/ppb_tcp_server_socket_private_api.h" |  | 
| 81 #include "third_party/WebKit/public/web/WebCursorInfo.h" |  | 
| 82 #include "third_party/WebKit/public/web/WebFrame.h" |  | 
| 83 #include "third_party/WebKit/public/web/WebInputEvent.h" |  | 
| 84 #include "third_party/WebKit/public/web/WebScreenInfo.h" |  | 
| 85 #include "third_party/WebKit/public/web/WebView.h" |  | 
| 86 #include "ui/gfx/size.h" |  | 
| 87 #include "url/gurl.h" |  | 
| 88 |  | 
| 89 using WebKit::WebFrame; |  | 
| 90 |  | 
| 91 namespace content { |  | 
| 92 |  | 
| 93 namespace { |  | 
| 94 |  | 
| 95 void CreateHostForInProcessModule(RenderViewImpl* render_view, |  | 
| 96                                   PluginModule* module, |  | 
| 97                                   const WebPluginInfo& webplugin_info) { |  | 
| 98   // First time an in-process plugin was used, make a host for it. |  | 
| 99   const PepperPluginInfo* info = |  | 
| 100       PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info); |  | 
| 101   DCHECK(!info->is_out_of_process); |  | 
| 102 |  | 
| 103   ppapi::PpapiPermissions perms( |  | 
| 104       PepperPluginRegistry::GetInstance()->GetInfoForPlugin( |  | 
| 105           webplugin_info)->permissions); |  | 
| 106   RendererPpapiHostImpl* host_impl = |  | 
| 107       RendererPpapiHostImpl::CreateOnModuleForInProcess( |  | 
| 108           module, perms); |  | 
| 109   render_view->PpapiPluginCreated(host_impl); |  | 
| 110 } |  | 
| 111 |  | 
| 112 }  // namespace |  | 
| 113 |  | 
| 114 PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderViewImpl* render_view) |  | 
| 115     : RenderViewObserver(render_view), |  | 
| 116       render_view_(render_view), |  | 
| 117       pepper_browser_connection_(this), |  | 
| 118       focused_plugin_(NULL), |  | 
| 119       last_mouse_event_target_(NULL) { |  | 
| 120 } |  | 
| 121 |  | 
| 122 PepperPluginDelegateImpl::~PepperPluginDelegateImpl() { |  | 
| 123 } |  | 
| 124 |  | 
| 125 WebKit::WebPlugin* PepperPluginDelegateImpl::CreatePepperWebPlugin( |  | 
| 126     const WebPluginInfo& webplugin_info, |  | 
| 127     const WebKit::WebPluginParams& params) { |  | 
| 128   bool pepper_plugin_was_registered = false; |  | 
| 129   scoped_refptr<PluginModule> pepper_module( |  | 
| 130       CreatePepperPluginModule(webplugin_info, &pepper_plugin_was_registered)); |  | 
| 131 |  | 
| 132   if (pepper_plugin_was_registered) { |  | 
| 133     if (!pepper_module.get()) |  | 
| 134       return NULL; |  | 
| 135     return new PepperWebPluginImpl( |  | 
| 136         pepper_module.get(), params, AsWeakPtr(), render_view_->AsWeakPtr()); |  | 
| 137   } |  | 
| 138 |  | 
| 139   return NULL; |  | 
| 140 } |  | 
| 141 |  | 
| 142 scoped_refptr<PluginModule> PepperPluginDelegateImpl::CreatePepperPluginModule( |  | 
| 143     const WebPluginInfo& webplugin_info, |  | 
| 144     bool* pepper_plugin_was_registered) { |  | 
| 145   *pepper_plugin_was_registered = true; |  | 
| 146 |  | 
| 147   // See if a module has already been loaded for this plugin. |  | 
| 148   base::FilePath path(webplugin_info.path); |  | 
| 149   scoped_refptr<PluginModule> module = |  | 
| 150       PepperPluginRegistry::GetInstance()->GetLiveModule(path); |  | 
| 151   if (module.get()) { |  | 
| 152     if (!module->renderer_ppapi_host()) { |  | 
| 153       // If the module exists and no embedder state was associated with it, |  | 
| 154       // then the module was one of the ones preloaded and is an in-process |  | 
| 155       // plugin. We need to associate our host state with it. |  | 
| 156       CreateHostForInProcessModule(render_view_, module.get(), webplugin_info); |  | 
| 157     } |  | 
| 158     return module; |  | 
| 159   } |  | 
| 160 |  | 
| 161   // In-process plugins will have always been created up-front to avoid the |  | 
| 162   // sandbox restrictions. So getting here implies it doesn't exist or should |  | 
| 163   // be out of process. |  | 
| 164   const PepperPluginInfo* info = |  | 
| 165       PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info); |  | 
| 166   if (!info) { |  | 
| 167     *pepper_plugin_was_registered = false; |  | 
| 168     return scoped_refptr<PluginModule>(); |  | 
| 169   } else if (!info->is_out_of_process) { |  | 
| 170     // In-process plugin not preloaded, it probably couldn't be initialized. |  | 
| 171     return scoped_refptr<PluginModule>(); |  | 
| 172   } |  | 
| 173 |  | 
| 174   ppapi::PpapiPermissions permissions = |  | 
| 175       ppapi::PpapiPermissions::GetForCommandLine(info->permissions); |  | 
| 176 |  | 
| 177   // Out of process: have the browser start the plugin process for us. |  | 
| 178   IPC::ChannelHandle channel_handle; |  | 
| 179   base::ProcessId peer_pid; |  | 
| 180   int plugin_child_id = 0; |  | 
| 181   Send(new ViewHostMsg_OpenChannelToPepperPlugin( |  | 
| 182       path, &channel_handle, &peer_pid, &plugin_child_id)); |  | 
| 183   if (channel_handle.name.empty()) { |  | 
| 184     // Couldn't be initialized. |  | 
| 185     return scoped_refptr<PluginModule>(); |  | 
| 186   } |  | 
| 187 |  | 
| 188   // AddLiveModule must be called before any early returns since the |  | 
| 189   // module's destructor will remove itself. |  | 
| 190   module = new PluginModule(info->name, path, permissions); |  | 
| 191   PepperPluginRegistry::GetInstance()->AddLiveModule(path, module.get()); |  | 
| 192 |  | 
| 193   if (!CreateOutOfProcessModule(module.get(), |  | 
| 194                                 path, |  | 
| 195                                 permissions, |  | 
| 196                                 channel_handle, |  | 
| 197                                 peer_pid, |  | 
| 198                                 plugin_child_id, |  | 
| 199                                 false))  // is_external = false |  | 
| 200     return scoped_refptr<PluginModule>(); |  | 
| 201 |  | 
| 202   return module; |  | 
| 203 } |  | 
| 204 |  | 
| 205 scoped_refptr<PepperBroker> PepperPluginDelegateImpl::CreateBroker( |  | 
| 206     PluginModule* plugin_module) { |  | 
| 207   DCHECK(plugin_module); |  | 
| 208   DCHECK(!plugin_module->GetBroker()); |  | 
| 209 |  | 
| 210   // The broker path is the same as the plugin. |  | 
| 211   const base::FilePath& broker_path = plugin_module->path(); |  | 
| 212 |  | 
| 213   scoped_refptr<PepperBroker> broker = new PepperBroker(plugin_module, this); |  | 
| 214 |  | 
| 215   int request_id = |  | 
| 216       pending_connect_broker_.Add(new scoped_refptr<PepperBroker>(broker)); |  | 
| 217 |  | 
| 218   // Have the browser start the broker process for us. |  | 
| 219   Send(new ViewHostMsg_OpenChannelToPpapiBroker( |  | 
| 220       routing_id(), request_id, broker_path)); |  | 
| 221 |  | 
| 222   return broker; |  | 
| 223 } |  | 
| 224 |  | 
| 225 RendererPpapiHost* PepperPluginDelegateImpl::CreateOutOfProcessModule( |  | 
| 226     PluginModule* module, |  | 
| 227     const base::FilePath& path, |  | 
| 228     ppapi::PpapiPermissions permissions, |  | 
| 229     const IPC::ChannelHandle& channel_handle, |  | 
| 230     base::ProcessId peer_pid, |  | 
| 231     int plugin_child_id, |  | 
| 232     bool is_external) { |  | 
| 233   scoped_refptr<PepperHungPluginFilter> hung_filter( |  | 
| 234       new PepperHungPluginFilter(path, routing_id(), plugin_child_id)); |  | 
| 235   scoped_ptr<HostDispatcherWrapper> dispatcher( |  | 
| 236       new HostDispatcherWrapper(module, |  | 
| 237                                 peer_pid, |  | 
| 238                                 plugin_child_id, |  | 
| 239                                 permissions, |  | 
| 240                                 is_external)); |  | 
| 241   if (!dispatcher->Init( |  | 
| 242           channel_handle, |  | 
| 243           PluginModule::GetLocalGetInterfaceFunc(), |  | 
| 244           ppapi::Preferences(render_view_->webkit_preferences()), |  | 
| 245           hung_filter.get())) |  | 
| 246     return NULL; |  | 
| 247 |  | 
| 248   RendererPpapiHostImpl* host_impl = |  | 
| 249       RendererPpapiHostImpl::CreateOnModuleForOutOfProcess( |  | 
| 250           module, dispatcher->dispatcher(), permissions); |  | 
| 251   render_view_->PpapiPluginCreated(host_impl); |  | 
| 252 |  | 
| 253   module->InitAsProxied(dispatcher.release()); |  | 
| 254   return host_impl; |  | 
| 255 } |  | 
| 256 |  | 
| 257 void PepperPluginDelegateImpl::OnPpapiBrokerChannelCreated( |  | 
| 258     int request_id, |  | 
| 259     base::ProcessId broker_pid, |  | 
| 260     const IPC::ChannelHandle& handle) { |  | 
| 261   scoped_refptr<PepperBroker>* broker_ptr = |  | 
| 262       pending_connect_broker_.Lookup(request_id); |  | 
| 263   if (broker_ptr) { |  | 
| 264     scoped_refptr<PepperBroker> broker = *broker_ptr; |  | 
| 265     pending_connect_broker_.Remove(request_id); |  | 
| 266     broker->OnBrokerChannelConnected(broker_pid, handle); |  | 
| 267   } else { |  | 
| 268     // There is no broker waiting for this channel. Close it so the broker can |  | 
| 269     // clean up and possibly exit. |  | 
| 270     // The easiest way to clean it up is to just put it in an object |  | 
| 271     // and then close them. This failure case is not performance critical. |  | 
| 272     PepperBrokerDispatcherWrapper temp_dispatcher; |  | 
| 273     temp_dispatcher.Init(broker_pid, handle); |  | 
| 274   } |  | 
| 275 } |  | 
| 276 |  | 
| 277 // Iterates through pending_connect_broker_ to find the broker. |  | 
| 278 // Cannot use Lookup() directly because pending_connect_broker_ does not store |  | 
| 279 // the raw pointer to the broker. Assumes maximum of one copy of broker exists. |  | 
| 280 bool PepperPluginDelegateImpl::StopWaitingForBrokerConnection( |  | 
| 281     PepperBroker* broker) { |  | 
| 282   for (BrokerMap::iterator i(&pending_connect_broker_); |  | 
| 283        !i.IsAtEnd(); i.Advance()) { |  | 
| 284     if (i.GetCurrentValue()->get() == broker) { |  | 
| 285       pending_connect_broker_.Remove(i.GetCurrentKey()); |  | 
| 286       return true; |  | 
| 287     } |  | 
| 288   } |  | 
| 289 |  | 
| 290   return false; |  | 
| 291 } |  | 
| 292 |  | 
| 293 void PepperPluginDelegateImpl::ViewWillInitiatePaint() { |  | 
| 294   // Notify all of our instances that we started painting. This is used for |  | 
| 295   // internal bookkeeping only, so we know that the set can not change under |  | 
| 296   // us. |  | 
| 297   for (std::set<PepperPluginInstanceImpl*>::iterator i = |  | 
| 298            active_instances_.begin(); |  | 
| 299        i != active_instances_.end(); ++i) |  | 
| 300     (*i)->ViewWillInitiatePaint(); |  | 
| 301 } |  | 
| 302 |  | 
| 303 void PepperPluginDelegateImpl::ViewInitiatedPaint() { |  | 
| 304   // Notify all instances that we painted.  The same caveats apply as for |  | 
| 305   // ViewFlushedPaint regarding instances closing themselves, so we take |  | 
| 306   // similar precautions. |  | 
| 307   std::set<PepperPluginInstanceImpl*> plugins = active_instances_; |  | 
| 308   for (std::set<PepperPluginInstanceImpl*>::iterator i = plugins.begin(); |  | 
| 309        i != plugins.end(); ++i) { |  | 
| 310     if (active_instances_.find(*i) != active_instances_.end()) |  | 
| 311       (*i)->ViewInitiatedPaint(); |  | 
| 312   } |  | 
| 313 } |  | 
| 314 |  | 
| 315 void PepperPluginDelegateImpl::ViewFlushedPaint() { |  | 
| 316   // Notify all instances that we flushed. This will call into the plugin, and |  | 
| 317   // we it may ask to close itself as a result. This will, in turn, modify our |  | 
| 318   // set, possibly invalidating the iterator. So we iterate on a copy that |  | 
| 319   // won't change out from under us. |  | 
| 320   std::set<PepperPluginInstanceImpl*> plugins = active_instances_; |  | 
| 321   for (std::set<PepperPluginInstanceImpl*>::iterator i = plugins.begin(); |  | 
| 322        i != plugins.end(); ++i) { |  | 
| 323     // The copy above makes sure our iterator is never invalid if some plugins |  | 
| 324     // are destroyed. But some plugin may decide to close all of its views in |  | 
| 325     // response to a paint in one of them, so we need to make sure each one is |  | 
| 326     // still "current" before using it. |  | 
| 327     // |  | 
| 328     // It's possible that a plugin was destroyed, but another one was created |  | 
| 329     // with the same address. In this case, we'll call ViewFlushedPaint on that |  | 
| 330     // new plugin. But that's OK for this particular case since we're just |  | 
| 331     // notifying all of our instances that the view flushed, and the new one is |  | 
| 332     // one of our instances. |  | 
| 333     // |  | 
| 334     // What about the case where a new one is created in a callback at a new |  | 
| 335     // address and we don't issue the callback? We're still OK since this |  | 
| 336     // callback is used for flush callbacks and we could not have possibly |  | 
| 337     // started a new paint (ViewWillInitiatePaint) for the new plugin while |  | 
| 338     // processing a previous paint for an existing one. |  | 
| 339     if (active_instances_.find(*i) != active_instances_.end()) |  | 
| 340       (*i)->ViewFlushedPaint(); |  | 
| 341   } |  | 
| 342 } |  | 
| 343 |  | 
| 344 PepperPluginInstanceImpl* PepperPluginDelegateImpl:: |  | 
| 345     GetBitmapForOptimizedPluginPaint( |  | 
| 346         const gfx::Rect& paint_bounds, |  | 
| 347         TransportDIB** dib, |  | 
| 348         gfx::Rect* location, |  | 
| 349         gfx::Rect* clip, |  | 
| 350         float* scale_factor) { |  | 
| 351   for (std::set<PepperPluginInstanceImpl*>::iterator i = |  | 
| 352            active_instances_.begin(); |  | 
| 353        i != active_instances_.end(); ++i) { |  | 
| 354     PepperPluginInstanceImpl* instance = *i; |  | 
| 355     // In Flash fullscreen , the plugin contents should be painted onto the |  | 
| 356     // fullscreen widget instead of the web page. |  | 
| 357     if (!instance->FlashIsFullscreenOrPending() && |  | 
| 358         instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location, |  | 
| 359                                                    clip, scale_factor)) |  | 
| 360       return *i; |  | 
| 361   } |  | 
| 362   return NULL; |  | 
| 363 } |  | 
| 364 |  | 
| 365 void PepperPluginDelegateImpl::PluginFocusChanged( |  | 
| 366     PepperPluginInstanceImpl* instance, |  | 
| 367     bool focused) { |  | 
| 368   if (focused) |  | 
| 369     focused_plugin_ = instance; |  | 
| 370   else if (focused_plugin_ == instance) |  | 
| 371     focused_plugin_ = NULL; |  | 
| 372   if (render_view_) |  | 
| 373     render_view_->PpapiPluginFocusChanged(); |  | 
| 374 } |  | 
| 375 |  | 
| 376 void PepperPluginDelegateImpl::PluginTextInputTypeChanged( |  | 
| 377     PepperPluginInstanceImpl* instance) { |  | 
| 378   if (focused_plugin_ == instance && render_view_) |  | 
| 379     render_view_->PpapiPluginTextInputTypeChanged(); |  | 
| 380 } |  | 
| 381 |  | 
| 382 void PepperPluginDelegateImpl::PluginCaretPositionChanged( |  | 
| 383     PepperPluginInstanceImpl* instance) { |  | 
| 384   if (focused_plugin_ == instance && render_view_) |  | 
| 385     render_view_->PpapiPluginCaretPositionChanged(); |  | 
| 386 } |  | 
| 387 |  | 
| 388 void PepperPluginDelegateImpl::PluginRequestedCancelComposition( |  | 
| 389     PepperPluginInstanceImpl* instance) { |  | 
| 390   if (focused_plugin_ == instance && render_view_) |  | 
| 391     render_view_->PpapiPluginCancelComposition(); |  | 
| 392 } |  | 
| 393 |  | 
| 394 void PepperPluginDelegateImpl::PluginSelectionChanged( |  | 
| 395     PepperPluginInstanceImpl* instance) { |  | 
| 396   if (focused_plugin_ == instance && render_view_) |  | 
| 397     render_view_->PpapiPluginSelectionChanged(); |  | 
| 398 } |  | 
| 399 |  | 
| 400 void PepperPluginDelegateImpl::OnImeSetComposition( |  | 
| 401     const string16& text, |  | 
| 402     const std::vector<WebKit::WebCompositionUnderline>& underlines, |  | 
| 403     int selection_start, |  | 
| 404     int selection_end) { |  | 
| 405   if (!IsPluginAcceptingCompositionEvents()) { |  | 
| 406     composition_text_ = text; |  | 
| 407   } else { |  | 
| 408     // TODO(kinaba) currently all composition events are sent directly to |  | 
| 409     // plugins. Use DOM event mechanism after WebKit is made aware about |  | 
| 410     // plugins that support composition. |  | 
| 411     // The code below mimics the behavior of WebCore::Editor::setComposition. |  | 
| 412 |  | 
| 413     // Empty -> nonempty: composition started. |  | 
| 414     if (composition_text_.empty() && !text.empty()) |  | 
| 415       focused_plugin_->HandleCompositionStart(string16()); |  | 
| 416     // Nonempty -> empty: composition canceled. |  | 
| 417     if (!composition_text_.empty() && text.empty()) |  | 
| 418        focused_plugin_->HandleCompositionEnd(string16()); |  | 
| 419     composition_text_ = text; |  | 
| 420     // Nonempty: composition is ongoing. |  | 
| 421     if (!composition_text_.empty()) { |  | 
| 422       focused_plugin_->HandleCompositionUpdate(composition_text_, underlines, |  | 
| 423                                                selection_start, selection_end); |  | 
| 424     } |  | 
| 425   } |  | 
| 426 } |  | 
| 427 |  | 
| 428 void PepperPluginDelegateImpl::OnImeConfirmComposition(const string16& text) { |  | 
| 429   // Here, text.empty() has a special meaning. It means to commit the last |  | 
| 430   // update of composition text (see RenderWidgetHost::ImeConfirmComposition()). |  | 
| 431   const string16& last_text = text.empty() ? composition_text_ : text; |  | 
| 432 |  | 
| 433   // last_text is empty only when both text and composition_text_ is. Ignore it. |  | 
| 434   if (last_text.empty()) |  | 
| 435     return; |  | 
| 436 |  | 
| 437   if (!IsPluginAcceptingCompositionEvents()) { |  | 
| 438     for (size_t i = 0; i < text.size(); ++i) { |  | 
| 439       WebKit::WebKeyboardEvent char_event; |  | 
| 440       char_event.type = WebKit::WebInputEvent::Char; |  | 
| 441       char_event.timeStampSeconds = base::Time::Now().ToDoubleT(); |  | 
| 442       char_event.modifiers = 0; |  | 
| 443       char_event.windowsKeyCode = last_text[i]; |  | 
| 444       char_event.nativeKeyCode = last_text[i]; |  | 
| 445       char_event.text[0] = last_text[i]; |  | 
| 446       char_event.unmodifiedText[0] = last_text[i]; |  | 
| 447       if (render_view_->webwidget()) |  | 
| 448         render_view_->webwidget()->handleInputEvent(char_event); |  | 
| 449     } |  | 
| 450   } else { |  | 
| 451     // Mimics the order of events sent by WebKit. |  | 
| 452     // See WebCore::Editor::setComposition() for the corresponding code. |  | 
| 453     focused_plugin_->HandleCompositionEnd(last_text); |  | 
| 454     focused_plugin_->HandleTextInput(last_text); |  | 
| 455   } |  | 
| 456   composition_text_.clear(); |  | 
| 457 } |  | 
| 458 |  | 
| 459 gfx::Rect PepperPluginDelegateImpl::GetCaretBounds() const { |  | 
| 460   if (!focused_plugin_) |  | 
| 461     return gfx::Rect(0, 0, 0, 0); |  | 
| 462   return focused_plugin_->GetCaretBounds(); |  | 
| 463 } |  | 
| 464 |  | 
| 465 ui::TextInputType PepperPluginDelegateImpl::GetTextInputType() const { |  | 
| 466   if (!focused_plugin_) |  | 
| 467     return ui::TEXT_INPUT_TYPE_NONE; |  | 
| 468   return focused_plugin_->text_input_type(); |  | 
| 469 } |  | 
| 470 |  | 
| 471 void PepperPluginDelegateImpl::GetSurroundingText(string16* text, |  | 
| 472                                                   ui::Range* range) const { |  | 
| 473   if (!focused_plugin_) |  | 
| 474     return; |  | 
| 475   return focused_plugin_->GetSurroundingText(text, range); |  | 
| 476 } |  | 
| 477 |  | 
| 478 bool PepperPluginDelegateImpl::IsPluginAcceptingCompositionEvents() const { |  | 
| 479   if (!focused_plugin_) |  | 
| 480     return false; |  | 
| 481   return focused_plugin_->IsPluginAcceptingCompositionEvents(); |  | 
| 482 } |  | 
| 483 |  | 
| 484 bool PepperPluginDelegateImpl::CanComposeInline() const { |  | 
| 485   return IsPluginAcceptingCompositionEvents(); |  | 
| 486 } |  | 
| 487 |  | 
| 488 void PepperPluginDelegateImpl::InstanceCreated( |  | 
| 489     PepperPluginInstanceImpl* instance) { |  | 
| 490   active_instances_.insert(instance); |  | 
| 491 |  | 
| 492   // Set the initial focus. |  | 
| 493   instance->SetContentAreaFocus(render_view_->has_focus()); |  | 
| 494 } |  | 
| 495 |  | 
| 496 void PepperPluginDelegateImpl::InstanceDeleted( |  | 
| 497     PepperPluginInstanceImpl* instance) { |  | 
| 498   active_instances_.erase(instance); |  | 
| 499 |  | 
| 500   if (last_mouse_event_target_ == instance) |  | 
| 501     last_mouse_event_target_ = NULL; |  | 
| 502   if (focused_plugin_ == instance) |  | 
| 503     PluginFocusChanged(instance, false); |  | 
| 504 } |  | 
| 505 |  | 
| 506 // If a broker has not already been created for this plugin, creates one. |  | 
| 507 PepperBroker* PepperPluginDelegateImpl::ConnectToBroker( |  | 
| 508     PPB_Broker_Impl* client) { |  | 
| 509   DCHECK(client); |  | 
| 510 |  | 
| 511   PluginModule* plugin_module = ResourceHelper::GetPluginModule(client); |  | 
| 512   if (!plugin_module) |  | 
| 513     return NULL; |  | 
| 514 |  | 
| 515   scoped_refptr<PepperBroker> broker = |  | 
| 516       static_cast<PepperBroker*>(plugin_module->GetBroker()); |  | 
| 517   if (!broker.get()) |  | 
| 518     broker = CreateBroker(plugin_module); |  | 
| 519 |  | 
| 520   int request_id = pending_permission_requests_.Add( |  | 
| 521       new base::WeakPtr<PPB_Broker_Impl>(client->AsWeakPtr())); |  | 
| 522   Send(new ViewHostMsg_RequestPpapiBrokerPermission( |  | 
| 523       routing_id(), |  | 
| 524       request_id, |  | 
| 525       client->GetDocumentUrl(), |  | 
| 526       plugin_module->path())); |  | 
| 527 |  | 
| 528   // Adds a reference, ensuring that the broker is not deleted when |  | 
| 529   // |broker| goes out of scope. |  | 
| 530   broker->AddPendingConnect(client); |  | 
| 531 |  | 
| 532   return broker.get(); |  | 
| 533 } |  | 
| 534 |  | 
| 535 void PepperPluginDelegateImpl::OnPpapiBrokerPermissionResult( |  | 
| 536     int request_id, |  | 
| 537     bool result) { |  | 
| 538   scoped_ptr<base::WeakPtr<PPB_Broker_Impl> > client_ptr( |  | 
| 539       pending_permission_requests_.Lookup(request_id)); |  | 
| 540   DCHECK(client_ptr.get()); |  | 
| 541   pending_permission_requests_.Remove(request_id); |  | 
| 542   base::WeakPtr<PPB_Broker_Impl> client = *client_ptr; |  | 
| 543   if (!client.get()) |  | 
| 544     return; |  | 
| 545 |  | 
| 546   PluginModule* plugin_module = ResourceHelper::GetPluginModule(client.get()); |  | 
| 547   if (!plugin_module) |  | 
| 548     return; |  | 
| 549 |  | 
| 550   PepperBroker* broker = static_cast<PepperBroker*>(plugin_module->GetBroker()); |  | 
| 551   broker->OnBrokerPermissionResult(client.get(), result); |  | 
| 552 } |  | 
| 553 |  | 
| 554 bool PepperPluginDelegateImpl::AsyncOpenFile( |  | 
| 555     const base::FilePath& path, |  | 
| 556     int flags, |  | 
| 557     const AsyncOpenFileCallback& callback) { |  | 
| 558   int message_id = pending_async_open_files_.Add( |  | 
| 559       new AsyncOpenFileCallback(callback)); |  | 
| 560   return Send(new ViewHostMsg_AsyncOpenFile( |  | 
| 561       routing_id(), path, flags, message_id)); |  | 
| 562 } |  | 
| 563 |  | 
| 564 void PepperPluginDelegateImpl::OnAsyncFileOpened( |  | 
| 565     base::PlatformFileError error_code, |  | 
| 566     IPC::PlatformFileForTransit file_for_transit, |  | 
| 567     int message_id) { |  | 
| 568   AsyncOpenFileCallback* callback = |  | 
| 569       pending_async_open_files_.Lookup(message_id); |  | 
| 570   DCHECK(callback); |  | 
| 571   pending_async_open_files_.Remove(message_id); |  | 
| 572 |  | 
| 573   base::PlatformFile file = |  | 
| 574       IPC::PlatformFileForTransitToPlatformFile(file_for_transit); |  | 
| 575   callback->Run(error_code, base::PassPlatformFile(&file)); |  | 
| 576   // Make sure we won't leak file handle if the requester has died. |  | 
| 577   if (file != base::kInvalidPlatformFileValue) { |  | 
| 578     base::FileUtilProxy::Close( |  | 
| 579         RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), |  | 
| 580         file, |  | 
| 581         base::FileUtilProxy::StatusCallback()); |  | 
| 582   } |  | 
| 583   delete callback; |  | 
| 584 } |  | 
| 585 |  | 
| 586 void PepperPluginDelegateImpl::OnSetFocus(bool has_focus) { |  | 
| 587   for (std::set<PepperPluginInstanceImpl*>::iterator i = |  | 
| 588            active_instances_.begin(); |  | 
| 589        i != active_instances_.end(); ++i) |  | 
| 590     (*i)->SetContentAreaFocus(has_focus); |  | 
| 591 } |  | 
| 592 |  | 
| 593 void PepperPluginDelegateImpl::PageVisibilityChanged(bool is_visible) { |  | 
| 594   for (std::set<PepperPluginInstanceImpl*>::iterator i = |  | 
| 595            active_instances_.begin(); |  | 
| 596        i != active_instances_.end(); ++i) |  | 
| 597     (*i)->PageVisibilityChanged(is_visible); |  | 
| 598 } |  | 
| 599 |  | 
| 600 bool PepperPluginDelegateImpl::IsPluginFocused() const { |  | 
| 601   return focused_plugin_ != NULL; |  | 
| 602 } |  | 
| 603 |  | 
| 604 void PepperPluginDelegateImpl::WillHandleMouseEvent() { |  | 
| 605   // This method is called for every mouse event that the render view receives. |  | 
| 606   // And then the mouse event is forwarded to WebKit, which dispatches it to the |  | 
| 607   // event target. Potentially a Pepper plugin will receive the event. |  | 
| 608   // In order to tell whether a plugin gets the last mouse event and which it |  | 
| 609   // is, we set |last_mouse_event_target_| to NULL here. If a plugin gets the |  | 
| 610   // event, it will notify us via DidReceiveMouseEvent() and set itself as |  | 
| 611   // |last_mouse_event_target_|. |  | 
| 612   last_mouse_event_target_ = NULL; |  | 
| 613 } |  | 
| 614 |  | 
| 615 void PepperPluginDelegateImpl::RegisterTCPSocket( |  | 
| 616     PPB_TCPSocket_Private_Impl* socket, |  | 
| 617     uint32 socket_id) { |  | 
| 618   tcp_sockets_.AddWithID(socket, socket_id); |  | 
| 619 } |  | 
| 620 |  | 
| 621 void PepperPluginDelegateImpl::UnregisterTCPSocket(uint32 socket_id) { |  | 
| 622   // There is no DCHECK(tcp_sockets_.Lookup(socket_id)) because this method |  | 
| 623   // can be called before TCPSocketConnect or TCPSocketConnectWithNetAddress. |  | 
| 624   if (tcp_sockets_.Lookup(socket_id)) |  | 
| 625     tcp_sockets_.Remove(socket_id); |  | 
| 626 } |  | 
| 627 |  | 
| 628 void PepperPluginDelegateImpl::TCPServerSocketStopListening(uint32 socket_id) { |  | 
| 629   tcp_server_sockets_.Remove(socket_id); |  | 
| 630 } |  | 
| 631 |  | 
| 632 void PepperPluginDelegateImpl::HandleDocumentLoad( |  | 
| 633     PepperPluginInstanceImpl* instance, |  | 
| 634     const WebKit::WebURLResponse& response) { |  | 
| 635   DCHECK(!instance->document_loader()); |  | 
| 636 |  | 
| 637   PP_Instance pp_instance = instance->pp_instance(); |  | 
| 638   RendererPpapiHostImpl* host_impl = instance->module()->renderer_ppapi_host(); |  | 
| 639 |  | 
| 640   // Create a loader resource host for this load. Note that we have to set |  | 
| 641   // the document_loader before issuing the in-process |  | 
| 642   // PPP_Instance.HandleDocumentLoad call below, since this may reentrantly |  | 
| 643   // call into the instance and expect it to be valid. |  | 
| 644   PepperURLLoaderHost* loader_host = |  | 
| 645       new PepperURLLoaderHost(host_impl, true, pp_instance, 0); |  | 
| 646   instance->set_document_loader(loader_host); |  | 
| 647   loader_host->didReceiveResponse(NULL, response); |  | 
| 648 |  | 
| 649   // This host will be pending until the resource object attaches to it. |  | 
| 650   int pending_host_id = host_impl->GetPpapiHost()->AddPendingResourceHost( |  | 
| 651       scoped_ptr<ppapi::host::ResourceHost>(loader_host)); |  | 
| 652   DCHECK(pending_host_id); |  | 
| 653   ppapi::URLResponseInfoData data = |  | 
| 654       DataFromWebURLResponse(pp_instance, response); |  | 
| 655 |  | 
| 656   if (host_impl->in_process_router()) { |  | 
| 657     // Running in-process, we can just create the resource and call the |  | 
| 658     // PPP_Instance function directly. |  | 
| 659     scoped_refptr<ppapi::proxy::URLLoaderResource> loader_resource( |  | 
| 660         new ppapi::proxy::URLLoaderResource( |  | 
| 661             host_impl->in_process_router()->GetPluginConnection(pp_instance), |  | 
| 662             pp_instance, pending_host_id, data)); |  | 
| 663 |  | 
| 664     PP_Resource loader_pp_resource = loader_resource->GetReference(); |  | 
| 665     if (!instance->instance_interface()->HandleDocumentLoad( |  | 
| 666             instance->pp_instance(), loader_pp_resource)) |  | 
| 667       loader_resource->Close(); |  | 
| 668     // We don't pass a ref into the plugin, if it wants one, it will have taken |  | 
| 669     // an additional one. |  | 
| 670     ppapi::PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource( |  | 
| 671         loader_pp_resource); |  | 
| 672 |  | 
| 673     // Danger! If the plugin doesn't take a ref in HandleDocumentLoad, the |  | 
| 674     // resource host will be destroyed as soon as our scoped_refptr for the |  | 
| 675     // resource goes out of scope. |  | 
| 676     // |  | 
| 677     // Null it out so people don't accidentally add code below that uses it. |  | 
| 678     loader_host = NULL; |  | 
| 679   } else { |  | 
| 680     // Running out-of-process. Initiate an IPC call to notify the plugin |  | 
| 681     // process. |  | 
| 682     ppapi::proxy::HostDispatcher* dispatcher = |  | 
| 683         ppapi::proxy::HostDispatcher::GetForInstance(pp_instance); |  | 
| 684     dispatcher->Send(new PpapiMsg_PPPInstance_HandleDocumentLoad( |  | 
| 685         ppapi::API_ID_PPP_INSTANCE, pp_instance, pending_host_id, data)); |  | 
| 686   } |  | 
| 687 } |  | 
| 688 |  | 
| 689 RendererPpapiHost* PepperPluginDelegateImpl::CreateExternalPluginModule( |  | 
| 690     scoped_refptr<PluginModule> module, |  | 
| 691     const base::FilePath& path, |  | 
| 692     ppapi::PpapiPermissions permissions, |  | 
| 693     const IPC::ChannelHandle& channel_handle, |  | 
| 694     base::ProcessId peer_pid, |  | 
| 695     int plugin_child_id) { |  | 
| 696   // We don't call PepperPluginRegistry::AddLiveModule, as this module is |  | 
| 697   // managed externally. |  | 
| 698   return CreateOutOfProcessModule(module.get(), |  | 
| 699                                   path, |  | 
| 700                                   permissions, |  | 
| 701                                   channel_handle, |  | 
| 702                                   peer_pid, |  | 
| 703                                   plugin_child_id, |  | 
| 704                                   true);  // is_external = true |  | 
| 705 } |  | 
| 706 |  | 
| 707 void PepperPluginDelegateImpl::DidChangeCursor( |  | 
| 708     PepperPluginInstanceImpl* instance, |  | 
| 709     const WebKit::WebCursorInfo& cursor) { |  | 
| 710   // Update the cursor appearance immediately if the requesting plugin is the |  | 
| 711   // one which receives the last mouse event. Otherwise, the new cursor won't be |  | 
| 712   // picked up until the plugin gets the next input event. That is bad if, e.g., |  | 
| 713   // the plugin would like to set an invisible cursor when there isn't any user |  | 
| 714   // input for a while. |  | 
| 715   if (instance == last_mouse_event_target_) |  | 
| 716     render_view_->didChangeCursor(cursor); |  | 
| 717 } |  | 
| 718 |  | 
| 719 void PepperPluginDelegateImpl::DidReceiveMouseEvent( |  | 
| 720     PepperPluginInstanceImpl* instance) { |  | 
| 721   last_mouse_event_target_ = instance; |  | 
| 722 } |  | 
| 723 |  | 
| 724 void PepperPluginDelegateImpl::SampleGamepads(WebKit::WebGamepads* data) { |  | 
| 725   if (!gamepad_shared_memory_reader_) |  | 
| 726     gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader); |  | 
| 727   gamepad_shared_memory_reader_->SampleGamepads(*data); |  | 
| 728 } |  | 
| 729 |  | 
| 730 bool PepperPluginDelegateImpl::OnMessageReceived(const IPC::Message& message) { |  | 
| 731   if (pepper_browser_connection_.OnMessageReceived(message)) |  | 
| 732     return true; |  | 
| 733 |  | 
| 734   bool handled = true; |  | 
| 735   IPC_BEGIN_MESSAGE_MAP(PepperPluginDelegateImpl, message) |  | 
| 736     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK, |  | 
| 737                         OnTCPSocketConnectACK) |  | 
| 738     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SSLHandshakeACK, |  | 
| 739                         OnTCPSocketSSLHandshakeACK) |  | 
| 740     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK, OnTCPSocketReadACK) |  | 
| 741     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK, OnTCPSocketWriteACK) |  | 
| 742     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetOptionACK, |  | 
| 743                         OnTCPSocketSetOptionACK) |  | 
| 744     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_ListenACK, |  | 
| 745                         OnTCPServerSocketListenACK) |  | 
| 746     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_AcceptACK, |  | 
| 747                         OnTCPServerSocketAcceptACK) |  | 
| 748     IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerChannelCreated, |  | 
| 749                         OnPpapiBrokerChannelCreated) |  | 
| 750     IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenFile_ACK, OnAsyncFileOpened) |  | 
| 751     IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerPermissionResult, |  | 
| 752                         OnPpapiBrokerPermissionResult) |  | 
| 753     IPC_MESSAGE_UNHANDLED(handled = false) |  | 
| 754   IPC_END_MESSAGE_MAP() |  | 
| 755   return handled; |  | 
| 756 } |  | 
| 757 |  | 
| 758 void PepperPluginDelegateImpl::OnDestruct() { |  | 
| 759   // Nothing to do here. Default implementation in RenderViewObserver does |  | 
| 760   // 'delete this' but it's not suitable for PepperPluginDelegateImpl because |  | 
| 761   // it's non-pointer member in RenderViewImpl. |  | 
| 762 } |  | 
| 763 |  | 
| 764 void PepperPluginDelegateImpl::OnTCPSocketConnectACK( |  | 
| 765     uint32 plugin_dispatcher_id, |  | 
| 766     uint32 socket_id, |  | 
| 767     int32_t result, |  | 
| 768     const PP_NetAddress_Private& local_addr, |  | 
| 769     const PP_NetAddress_Private& remote_addr) { |  | 
| 770   PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id); |  | 
| 771   if (socket) |  | 
| 772     socket->OnConnectCompleted(result, local_addr, remote_addr); |  | 
| 773   if (result != PP_OK) |  | 
| 774     tcp_sockets_.Remove(socket_id); |  | 
| 775 } |  | 
| 776 |  | 
| 777 void PepperPluginDelegateImpl::OnTCPSocketSSLHandshakeACK( |  | 
| 778     uint32 plugin_dispatcher_id, |  | 
| 779     uint32 socket_id, |  | 
| 780     bool succeeded, |  | 
| 781     const ppapi::PPB_X509Certificate_Fields& certificate_fields) { |  | 
| 782   PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id); |  | 
| 783   if (socket) |  | 
| 784     socket->OnSSLHandshakeCompleted(succeeded, certificate_fields); |  | 
| 785 } |  | 
| 786 |  | 
| 787 void PepperPluginDelegateImpl::OnTCPSocketReadACK(uint32 plugin_dispatcher_id, |  | 
| 788                                                   uint32 socket_id, |  | 
| 789                                                   int32_t result, |  | 
| 790                                                   const std::string& data) { |  | 
| 791   PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id); |  | 
| 792   if (socket) |  | 
| 793     socket->OnReadCompleted(result, data); |  | 
| 794 } |  | 
| 795 |  | 
| 796 void PepperPluginDelegateImpl::OnTCPSocketWriteACK(uint32 plugin_dispatcher_id, |  | 
| 797                                                    uint32 socket_id, |  | 
| 798                                                    int32_t result) { |  | 
| 799   PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id); |  | 
| 800   if (socket) |  | 
| 801     socket->OnWriteCompleted(result); |  | 
| 802 } |  | 
| 803 |  | 
| 804 void PepperPluginDelegateImpl::OnTCPSocketSetOptionACK( |  | 
| 805     uint32 plugin_dispatcher_id, |  | 
| 806     uint32 socket_id, |  | 
| 807     int32_t result) { |  | 
| 808   PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id); |  | 
| 809   if (socket) |  | 
| 810     socket->OnSetOptionCompleted(result); |  | 
| 811 } |  | 
| 812 |  | 
| 813 void PepperPluginDelegateImpl::OnTCPServerSocketListenACK( |  | 
| 814     uint32 plugin_dispatcher_id, |  | 
| 815     PP_Resource socket_resource, |  | 
| 816     uint32 socket_id, |  | 
| 817     const PP_NetAddress_Private& local_addr, |  | 
| 818     int32_t status) { |  | 
| 819   ppapi::thunk::EnterResource<ppapi::thunk::PPB_TCPServerSocket_Private_API> |  | 
| 820       enter(socket_resource, true); |  | 
| 821   if (enter.succeeded()) { |  | 
| 822     ppapi::PPB_TCPServerSocket_Shared* socket = |  | 
| 823         static_cast<ppapi::PPB_TCPServerSocket_Shared*>(enter.object()); |  | 
| 824     if (status == PP_OK) |  | 
| 825       tcp_server_sockets_.AddWithID(socket, socket_id); |  | 
| 826     socket->OnListenCompleted(socket_id, local_addr, status); |  | 
| 827   } else if (socket_id != 0 && status == PP_OK) { |  | 
| 828     // StopListening was called before completion of Listen. |  | 
| 829     Send(new PpapiHostMsg_PPBTCPServerSocket_Destroy(socket_id)); |  | 
| 830   } |  | 
| 831 } |  | 
| 832 |  | 
| 833 void PepperPluginDelegateImpl::OnTCPServerSocketAcceptACK( |  | 
| 834     uint32 plugin_dispatcher_id, |  | 
| 835     uint32 server_socket_id, |  | 
| 836     uint32 accepted_socket_id, |  | 
| 837     const PP_NetAddress_Private& local_addr, |  | 
| 838     const PP_NetAddress_Private& remote_addr) { |  | 
| 839   ppapi::PPB_TCPServerSocket_Shared* socket = |  | 
| 840       tcp_server_sockets_.Lookup(server_socket_id); |  | 
| 841   if (socket) { |  | 
| 842     bool succeeded = (accepted_socket_id != 0); |  | 
| 843     socket->OnAcceptCompleted(succeeded, |  | 
| 844                               accepted_socket_id, |  | 
| 845                               local_addr, |  | 
| 846                               remote_addr); |  | 
| 847   } else if (accepted_socket_id != 0) { |  | 
| 848     Send(new PpapiHostMsg_PPBTCPSocket_Disconnect(accepted_socket_id)); |  | 
| 849   } |  | 
| 850 } |  | 
| 851 |  | 
| 852 }  // namespace content |  | 
| OLD | NEW | 
|---|