Home | History | Annotate | Download | only in proxy
      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 "ppapi/proxy/flash_menu_resource.h"
      6 
      7 #include "ppapi/c/pp_errors.h"
      8 #include "ppapi/proxy/ppapi_messages.h"
      9 #include "ppapi/proxy/serialized_flash_menu.h"
     10 
     11 namespace ppapi {
     12 namespace proxy {
     13 
     14 FlashMenuResource::FlashMenuResource(Connection connection,
     15                                      PP_Instance instance)
     16     : PluginResource(connection, instance),
     17       selected_id_dest_(NULL) {
     18 }
     19 
     20 FlashMenuResource::~FlashMenuResource() {
     21 }
     22 
     23 bool FlashMenuResource::Initialize(const PP_Flash_Menu* menu_data) {
     24   SerializedFlashMenu serialized_menu;
     25   if (!menu_data || !serialized_menu.SetPPMenu(menu_data))
     26     return false;
     27   SendCreate(RENDERER, PpapiHostMsg_FlashMenu_Create(serialized_menu));
     28   return true;
     29 }
     30 
     31 thunk::PPB_Flash_Menu_API* FlashMenuResource::AsPPB_Flash_Menu_API() {
     32   return this;
     33 }
     34 
     35 int32_t FlashMenuResource::Show(
     36     const PP_Point* location,
     37     int32_t* selected_id,
     38     scoped_refptr<TrackedCallback> callback) {
     39   if (TrackedCallback::IsPending(callback_))
     40     return PP_ERROR_INPROGRESS;
     41 
     42   selected_id_dest_ = selected_id;
     43   callback_ = callback;
     44 
     45   // This must be a sync message even though we don't care about the result.
     46   // The actual reply will be sent asynchronously in the future. This sync
     47   // request is due to the following deadlock:
     48   //
     49   //  1. Flash sends a show request to the renderer.
     50   //  2. The show handler in the renderer (in the case of full screen) requests
     51   //     the window rect which is a sync message to the browser. This causes
     52   //     a nested message loop to be spun up in the renderer.
     53   //  3. Flash expects context menus to be synchronous so it starts a nested
     54   //     message loop. This creates a second nested message loop in both the
     55   //     plugin and renderer process.
     56   //  4. The browser sends the window rect reply to unblock the renderer, but
     57   //     it's in the second nested message loop and the reply will *not*
     58   //     unblock this loop.
     59   //  5. The second loop won't exit until the message loop is complete, but
     60   //     that can't start until the first one exits.
     61   //
     62   // Having this message sync forces the sync request from the renderer to the
     63   // browser for the window rect will complete before Flash can run a nested
     64   // message loop to wait for the result of the menu.
     65   SyncCall<IPC::Message>(RENDERER, PpapiHostMsg_FlashMenu_Show(*location));
     66   return PP_OK_COMPLETIONPENDING;
     67 }
     68 
     69 void FlashMenuResource::OnReplyReceived(
     70     const proxy::ResourceMessageReplyParams& params,
     71     const IPC::Message& msg) {
     72   // Because the Show call is synchronous but we ignore the sync result, we
     73   // can't use the normal reply dispatch and have to do it manually here.
     74   switch (msg.type()) {
     75     case PpapiPluginMsg_FlashMenu_ShowReply::ID: {
     76       int32_t selected_id;
     77       if (ppapi::UnpackMessage<PpapiPluginMsg_FlashMenu_ShowReply>(
     78               msg, &selected_id))
     79         OnShowReply(params, selected_id);
     80       break;
     81     }
     82   }
     83 }
     84 
     85 void FlashMenuResource::OnShowReply(
     86     const proxy::ResourceMessageReplyParams& params,
     87     int32_t selected_id) {
     88   if (!TrackedCallback::IsPending(callback_))
     89     return;
     90 
     91   *selected_id_dest_ = selected_id;
     92   selected_id_dest_ = NULL;
     93   callback_->Run(params.result());
     94 }
     95 
     96 }  // namespace proxy
     97 }  // namespace ppapi
     98