OLD | NEW |
| (Empty) |
1 // Copyright 2010 The Ginsu Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can | |
3 // be found in the LICENSE file. | |
4 | |
5 #include "c_salt/npapi/variant_converter.h" | |
6 | |
7 #include <cassert> | |
8 #include <cstring> | |
9 #include <sstream> | |
10 #include <string> | |
11 | |
12 #include "c_salt/npapi/browser_binding.h" | |
13 #include "c_salt/npapi/javascript_object_proxy.h" | |
14 #include "c_salt/scripting_interface.h" | |
15 #include "c_salt/scripting_interface_ptrs.h" | |
16 #include "c_salt/variant.h" | |
17 | |
18 namespace c_salt { | |
19 namespace npapi { | |
20 | |
21 VariantConverter::VariantConverter(NPP instance) : instance_(instance) {} | |
22 | |
23 SharedVariant | |
24 VariantConverter::CreateVariantFromNPVariant(const NPVariant& np_var) const { | |
25 SharedVariant retval; | |
26 switch (np_var.type) { | |
27 case NPVariantType_Void: | |
28 case NPVariantType_Null: { | |
29 retval.reset(new c_salt::Variant); | |
30 break; | |
31 } | |
32 case NPVariantType_Object: { | |
33 // TODO(c_salt authors): Currently, this will always turn NPObject in to | |
34 // a Proxy object, treating it like a JavaScript object as far as c_salt | |
35 // is concerned. This should work even for native objects, just adding | |
36 // some work by doing extra conversions to/from NPAPI types. Is there | |
37 // any nice way to see if an NPObject* represents a native-side object? | |
38 // Nothing is apparent in NPObject or NPClass. We could hold a set of all | |
39 // NPObjects that are native-side (i.e., all BrowserBindings) per | |
40 // Instance, but it would have to be shared across threads and would | |
41 // therefore need synchronization. D'oh! | |
42 SharedScriptingInterface scripting_if_ptr( | |
43 new JavaScriptObjectProxy(NPVARIANT_TO_OBJECT(np_var), instance_)); | |
44 retval.reset(new c_salt::Variant(scripting_if_ptr)); | |
45 assert(Variant::kObjectVariantType == retval->variant_type()); | |
46 break; | |
47 } | |
48 case NPVariantType_String: { | |
49 NPString np_string(NPVARIANT_TO_STRING(np_var)); | |
50 retval.reset(new c_salt::Variant(std::string(np_string.UTF8Characters, | |
51 np_string.UTF8Length))); | |
52 break; | |
53 } | |
54 case NPVariantType_Bool: { | |
55 retval.reset(new c_salt::Variant(NPVARIANT_TO_BOOLEAN(np_var))); | |
56 break; | |
57 } | |
58 case NPVariantType_Int32: { | |
59 retval.reset(new c_salt::Variant(NPVARIANT_TO_INT32(np_var))); | |
60 break; | |
61 } | |
62 case NPVariantType_Double: { | |
63 retval.reset(new c_salt::Variant(NPVARIANT_TO_DOUBLE(np_var))); | |
64 break; | |
65 } | |
66 default: { | |
67 assert(false); | |
68 } | |
69 } | |
70 return retval; | |
71 } | |
72 | |
73 void | |
74 VariantConverter::ConvertVariantToNPVariant(const c_salt::Variant& c_salt_var, | |
75 NPVariant* np_var) const { | |
76 assert(np_var); | |
77 switch (c_salt_var.variant_type()) { | |
78 case c_salt::Variant::kNullVariantType: { | |
79 NULL_TO_NPVARIANT(*np_var); | |
80 break; | |
81 } | |
82 case c_salt::Variant::kBoolVariantType: { | |
83 BOOLEAN_TO_NPVARIANT(c_salt_var.BoolValue(), *np_var); | |
84 break; | |
85 } | |
86 case c_salt::Variant::kInt32VariantType: { | |
87 INT32_TO_NPVARIANT(c_salt_var.Int32Value(), *np_var); | |
88 break; | |
89 } | |
90 case c_salt::Variant::kDoubleVariantType: { | |
91 DOUBLE_TO_NPVARIANT(c_salt_var.DoubleValue(), *np_var); | |
92 break; | |
93 } | |
94 case c_salt::Variant::kStringVariantType: { | |
95 // TODO(dmichael, dspringer): We could provide a method that means: | |
96 // "I know for sure it's a string; return it to me by const-reference. | |
97 // If I'm wrong, I take full responsibility." Name it something like: | |
98 // NoReallyImSureItsAStringJustGiveItToMePleaseWithoutCopying() | |
99 // As it is, here's what's happening: | |
100 // Get the string_value which makes a temporary copy in this scope. Bind | |
101 // the const-reference string_value to it. | |
102 const std::string& string_value = c_salt_var.StringValue(); | |
103 const std::string::size_type str_length(string_value.length()+1); | |
104 // Ask the browser to allocate memory; it will take ownership of | |
105 // string_copy. | |
106 NPUTF8* utf8_string = reinterpret_cast<NPUTF8*>(NPN_MemAlloc(str_length)); | |
107 std::strncpy(utf8_string, string_value.c_str(), str_length); | |
108 STRINGN_TO_NPVARIANT(utf8_string, str_length-1, *np_var); | |
109 break; | |
110 } | |
111 case c_salt::Variant::kObjectVariantType: { | |
112 SharedScriptingInterface scriptable = c_salt_var.ObjectValue(); | |
113 if (scriptable->IsNative()) { | |
114 // This must be implemented with ScriptingBridge; we support no other | |
115 // form of native-backed scripting object. | |
116 ScriptingBridge* bridge = | |
117 static_cast<ScriptingBridge*>(scriptable.get()); | |
118 const NPObject* const_np_obj = bridge->browser_binding(); | |
119 NPObject* np_obj = const_cast<NPObject*>(const_np_obj); | |
120 // TODO(c_salt authors): Should we bump ref count? This doesn't. | |
121 OBJECT_TO_NPVARIANT(np_obj, *np_var); | |
122 } else { | |
123 // It's a JavaScript object, and we're using NPAPI, so it must be a | |
124 // npapi::JavaScriptObjectProxy. | |
125 npapi::JavaScriptObjectProxy* proxy = | |
126 static_cast<JavaScriptObjectProxy*>(scriptable.get()); | |
127 // TODO(c_salt authors): Same question... bump ref count? I think not; | |
128 // the browser should take over, but we should check. | |
129 OBJECT_TO_NPVARIANT(proxy->np_object(), *np_var); | |
130 } | |
131 break; | |
132 } | |
133 default: { | |
134 assert(false); | |
135 } | |
136 } | |
137 return; | |
138 } | |
139 | |
140 } // namespace npapi | |
141 } // namespace c_salt | |
OLD | NEW |