- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / flash_menu_resource.cc
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