• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/plugin_var_serialization_rules.h"
6 
7 #include "base/logging.h"
8 #include "ppapi/proxy/plugin_dispatcher.h"
9 #include "ppapi/proxy/plugin_globals.h"
10 #include "ppapi/proxy/plugin_resource_tracker.h"
11 #include "ppapi/proxy/plugin_var_tracker.h"
12 #include "ppapi/shared_impl/ppapi_globals.h"
13 #include "ppapi/shared_impl/var.h"
14 
15 namespace ppapi {
16 namespace proxy {
17 
PluginVarSerializationRules(const base::WeakPtr<PluginDispatcher> & dispatcher)18 PluginVarSerializationRules::PluginVarSerializationRules(
19     const base::WeakPtr<PluginDispatcher>& dispatcher)
20     : var_tracker_(PluginGlobals::Get()->plugin_var_tracker()),
21       dispatcher_(dispatcher) {
22 }
23 
~PluginVarSerializationRules()24 PluginVarSerializationRules::~PluginVarSerializationRules() {
25 }
26 
SendCallerOwned(const PP_Var & var)27 PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var) {
28   // Objects need special translations to get the IDs valid in the host.
29   if (var.type == PP_VARTYPE_OBJECT)
30     return var_tracker_->GetHostObject(var);
31   return var;
32 }
33 
BeginReceiveCallerOwned(const PP_Var & var)34 PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned(const PP_Var& var) {
35   if (var.type == PP_VARTYPE_OBJECT) {
36     return dispatcher_.get() ? var_tracker_->TrackObjectWithNoReference(
37                                    var, dispatcher_.get())
38                              : PP_MakeUndefined();
39   }
40 
41   return var;
42 }
43 
EndReceiveCallerOwned(const PP_Var & var)44 void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
45   if (var.type == PP_VARTYPE_OBJECT) {
46     var_tracker_->StopTrackingObjectWithNoReference(var);
47   } else if (var.type >= PP_VARTYPE_STRING) {
48     // Release our reference to the local Var.
49     var_tracker_->ReleaseVar(var);
50   }
51 }
52 
ReceivePassRef(const PP_Var & var)53 PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var) {
54   // Overview of sending an object with "pass ref" from the browser to the
55   // plugin:
56   //                                  Example 1             Example 2
57   //                               Plugin   Browser      Plugin   Browser
58   // Before send                      3        2            0        1
59   // Browser calls BeginSendPassRef   3        2            0        1
60   // Plugin calls ReceivePassRef      4        1            1        1
61   // Browser calls EndSendPassRef     4        1            1        1
62   //
63   // In example 1 before the send, the plugin has 3 refs which are represented
64   // as one ref in the browser (since the plugin only tells the browser when
65   // it's refcount goes from 1 -> 0). The initial state is that the browser
66   // plugin code started to return a value, which means it gets another ref
67   // on behalf of the caller. This needs to be transferred to the plugin and
68   // folded in to its set of refs it maintains (with one ref representing all
69   // of them in the browser).
70   if (var.type == PP_VARTYPE_OBJECT) {
71     return dispatcher_.get()
72                ? var_tracker_->ReceiveObjectPassRef(var, dispatcher_.get())
73                : PP_MakeUndefined();
74   }
75 
76   // Other types are unchanged.
77   return var;
78 }
79 
BeginSendPassRef(const PP_Var & var)80 PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var) {
81   // Overview of sending an object with "pass ref" from the plugin to the
82   // browser:
83   //                                  Example 1             Example 2
84   //                               Plugin   Browser      Plugin   Browser
85   // Before send                      3        1            1        1
86   // Plugin calls BeginSendPassRef    3        1            1        1
87   // Browser calls ReceivePassRef     3        2            1        2
88   // Plugin calls EndSendPassRef      2        2            0        1
89   //
90   // The plugin maintains one ref count in the browser on behalf of the
91   // entire ref count in the plugin. When the plugin refcount goes to 0, it
92   // will call the browser to deref the object. This is why in example 2
93   // transferring the object ref to the browser involves no net change in the
94   // browser's refcount.
95 
96   // Objects need special translations to get the IDs valid in the host.
97   if (var.type == PP_VARTYPE_OBJECT)
98     return var_tracker_->GetHostObject(var);
99   return var;
100 }
101 
EndSendPassRef(const PP_Var & var)102 void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var) {
103   // See BeginSendPassRef for an example of why we release our ref here.
104   // The var we have in our inner class has been converted to a host object
105   // by BeginSendPassRef. This means it's not a normal var valid in the plugin,
106   // so we need to use the special ReleaseHostObject.
107   if (var.type == PP_VARTYPE_OBJECT) {
108     if (dispatcher_.get())
109       var_tracker_->ReleaseHostObject(dispatcher_.get(), var);
110   } else if (var.type >= PP_VARTYPE_STRING) {
111     var_tracker_->ReleaseVar(var);
112   }
113 }
114 
ReleaseObjectRef(const PP_Var & var)115 void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
116   var_tracker_->ReleaseVar(var);
117 }
118 
119 }  // namespace proxy
120 }  // namespace ppapi
121