• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 PDFium 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "fxjs/xfa/cjx_tree.h"
8 
9 #include <vector>
10 
11 #include "fxjs/cfxjse_engine.h"
12 #include "fxjs/cfxjse_value.h"
13 #include "fxjs/js_resources.h"
14 #include "third_party/base/ptr_util.h"
15 #include "xfa/fxfa/parser/cxfa_arraynodelist.h"
16 #include "xfa/fxfa/parser/cxfa_attachnodelist.h"
17 #include "xfa/fxfa/parser/cxfa_document.h"
18 #include "xfa/fxfa/parser/cxfa_node.h"
19 #include "xfa/fxfa/parser/cxfa_object.h"
20 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
21 
22 const CJX_MethodSpec CJX_Tree::MethodSpecs[] = {
23     {"resolveNode", resolveNode_static},
24     {"resolveNodes", resolveNodes_static}};
25 
CJX_Tree(CXFA_Object * obj)26 CJX_Tree::CJX_Tree(CXFA_Object* obj) : CJX_Object(obj) {
27   DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs));
28 }
29 
~CJX_Tree()30 CJX_Tree::~CJX_Tree() {}
31 
resolveNode(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)32 CJS_Return CJX_Tree::resolveNode(
33     CJS_V8* runtime,
34     const std::vector<v8::Local<v8::Value>>& params) {
35   if (params.size() != 1)
36     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
37 
38   WideString expression = runtime->ToWideString(params[0]);
39   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
40   if (!pScriptContext)
41     return CJS_Return(true);
42 
43   CXFA_Object* refNode = GetXFAObject();
44   if (refNode->GetElementType() == XFA_Element::Xfa)
45     refNode = pScriptContext->GetThisObject();
46 
47   uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
48                     XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
49                     XFA_RESOLVENODE_Siblings;
50   XFA_RESOLVENODE_RS resolveNodeRS;
51   if (!pScriptContext->ResolveObjects(ToNode(refNode),
52                                       expression.AsStringView(), &resolveNodeRS,
53                                       dwFlag, nullptr)) {
54     return CJS_Return(runtime->NewNull());
55   }
56 
57   if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
58     CXFA_Object* pObject = resolveNodeRS.objects.front();
59     CFXJSE_Value* value =
60         GetDocument()->GetScriptContext()->GetJSValueFromMap(pObject);
61     if (!value)
62       return CJS_Return(runtime->NewNull());
63 
64     return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate()));
65   }
66 
67   const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo =
68       resolveNodeRS.pScriptAttribute;
69   if (!lpAttributeInfo ||
70       lpAttributeInfo->eValueType != XFA_ScriptType::Object) {
71     return CJS_Return(runtime->NewNull());
72   }
73 
74   auto pValue = pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetIsolate());
75   CJX_Object* jsObject = resolveNodeRS.objects.front()->JSObject();
76   (jsObject->*(lpAttributeInfo->callback))(pValue.get(), false,
77                                            lpAttributeInfo->attribute);
78   return CJS_Return(pValue->DirectGetValue().Get(runtime->GetIsolate()));
79 }
80 
resolveNodes(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)81 CJS_Return CJX_Tree::resolveNodes(
82     CJS_V8* runtime,
83     const std::vector<v8::Local<v8::Value>>& params) {
84   if (params.size() != 1)
85     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
86 
87   CXFA_Object* refNode = GetXFAObject();
88   if (refNode->GetElementType() == XFA_Element::Xfa)
89     refNode = GetDocument()->GetScriptContext()->GetThisObject();
90 
91   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
92   if (!pScriptContext)
93     return CJS_Return(true);
94 
95   auto pValue = pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetIsolate());
96   ResolveNodeList(pValue.get(), runtime->ToWideString(params[0]),
97                   XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
98                       XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
99                       XFA_RESOLVENODE_Siblings,
100                   ToNode(refNode));
101   return CJS_Return(pValue->DirectGetValue().Get(runtime->GetIsolate()));
102 }
103 
all(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)104 void CJX_Tree::all(CFXJSE_Value* pValue,
105                    bool bSetting,
106                    XFA_Attribute eAttribute) {
107   if (bSetting) {
108     ThrowInvalidPropertyException();
109     return;
110   }
111 
112   uint32_t dwFlag = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL;
113   WideString wsExpression = GetAttribute(XFA_Attribute::Name) + L"[*]";
114   ResolveNodeList(pValue, wsExpression, dwFlag, nullptr);
115 }
116 
classAll(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)117 void CJX_Tree::classAll(CFXJSE_Value* pValue,
118                         bool bSetting,
119                         XFA_Attribute eAttribute) {
120   if (bSetting) {
121     ThrowInvalidPropertyException();
122     return;
123   }
124 
125   WideString wsExpression = L"#" + GetXFAObject()->GetClassName() + L"[*]";
126   ResolveNodeList(pValue, wsExpression,
127                   XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL, nullptr);
128 }
129 
name(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)130 void CJX_Tree::name(CFXJSE_Value* pValue,
131                     bool bSetting,
132                     XFA_Attribute eAttribute) {
133   Script_Attribute_String(pValue, bSetting, eAttribute);
134 }
135 
nodes(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)136 void CJX_Tree::nodes(CFXJSE_Value* pValue,
137                      bool bSetting,
138                      XFA_Attribute eAttribute) {
139   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
140   if (!pScriptContext)
141     return;
142 
143   if (bSetting) {
144     WideString wsMessage = L"Unable to set ";
145     FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView());
146     return;
147   }
148 
149   CXFA_AttachNodeList* pNodeList =
150       new CXFA_AttachNodeList(GetDocument(), ToNode(GetXFAObject()));
151   pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
152 }
153 
parent(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)154 void CJX_Tree::parent(CFXJSE_Value* pValue,
155                       bool bSetting,
156                       XFA_Attribute eAttribute) {
157   if (bSetting) {
158     ThrowInvalidPropertyException();
159     return;
160   }
161 
162   CXFA_Node* pParent = ToNode(GetXFAObject())->GetParent();
163   if (!pParent) {
164     pValue->SetNull();
165     return;
166   }
167 
168   pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pParent));
169 }
170 
index(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)171 void CJX_Tree::index(CFXJSE_Value* pValue,
172                      bool bSetting,
173                      XFA_Attribute eAttribute) {
174   if (bSetting) {
175     ThrowInvalidPropertyException();
176     return;
177   }
178   pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameNameIndex());
179 }
180 
classIndex(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)181 void CJX_Tree::classIndex(CFXJSE_Value* pValue,
182                           bool bSetting,
183                           XFA_Attribute eAttribute) {
184   if (bSetting) {
185     ThrowInvalidPropertyException();
186     return;
187   }
188   pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameClassIndex());
189 }
190 
somExpression(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)191 void CJX_Tree::somExpression(CFXJSE_Value* pValue,
192                              bool bSetting,
193                              XFA_Attribute eAttribute) {
194   if (bSetting) {
195     ThrowInvalidPropertyException();
196     return;
197   }
198 
199   WideString wsSOMExpression = GetXFAObject()->GetSOMExpression();
200   pValue->SetString(wsSOMExpression.UTF8Encode().AsStringView());
201 }
202 
ResolveNodeList(CFXJSE_Value * pValue,WideString wsExpression,uint32_t dwFlag,CXFA_Node * refNode)203 void CJX_Tree::ResolveNodeList(CFXJSE_Value* pValue,
204                                WideString wsExpression,
205                                uint32_t dwFlag,
206                                CXFA_Node* refNode) {
207   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
208   if (!pScriptContext)
209     return;
210   if (!refNode)
211     refNode = ToNode(GetXFAObject());
212 
213   XFA_RESOLVENODE_RS resolveNodeRS;
214   pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(),
215                                  &resolveNodeRS, dwFlag, nullptr);
216   CXFA_ArrayNodeList* pNodeList = new CXFA_ArrayNodeList(GetDocument());
217   if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
218     for (CXFA_Object* pObject : resolveNodeRS.objects) {
219       if (pObject->IsNode())
220         pNodeList->Append(pObject->AsNode());
221     }
222   } else {
223     if (resolveNodeRS.pScriptAttribute &&
224         resolveNodeRS.pScriptAttribute->eValueType == XFA_ScriptType::Object) {
225       for (CXFA_Object* pObject : resolveNodeRS.objects) {
226         auto pValue =
227             pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetIsolate());
228         CJX_Object* jsObject = pObject->JSObject();
229         (jsObject->*(resolveNodeRS.pScriptAttribute->callback))(
230             pValue.get(), false, resolveNodeRS.pScriptAttribute->attribute);
231 
232         CXFA_Object* obj = CFXJSE_Engine::ToObject(pValue.get(), nullptr);
233         if (obj->IsNode())
234           pNodeList->Append(obj->AsNode());
235       }
236     }
237   }
238   pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
239 }
240