1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef AAPT_XML_XMLPATTERN_H
18 #define AAPT_XML_XMLPATTERN_H
19 
20 #include <functional>
21 #include <map>
22 #include <string>
23 #include <vector>
24 
25 #include "android-base/macros.h"
26 #include "androidfw/IDiagnostics.h"
27 #include "xml/XmlDom.h"
28 
29 namespace aapt {
30 namespace xml {
31 
32 enum class XmlActionExecutorPolicy {
33   // Actions are run if elements are matched, errors occur only when actions return false.
34   kNone,
35 
36   // The actions defined must match and run. If an element is found that does not match an action,
37   // an error occurs.
38   // Note: namespaced elements are always ignored.
39   kAllowList,
40 
41   // The actions defined should match and run. if an element is found that does not match an
42   // action, a warning is printed.
43   // Note: namespaced elements are always ignored.
44   kAllowListWarning,
45 };
46 
47 // Contains the actions to perform at this XML node. This is a recursive data structure that
48 // holds XmlNodeActions for child XML nodes.
49 class XmlNodeAction {
50  public:
51   using ActionFuncWithPolicyAndDiag =
52       std::function<bool(Element*, XmlActionExecutorPolicy, android::SourcePathDiagnostics*)>;
53   using ActionFuncWithDiag = std::function<bool(Element*, android::SourcePathDiagnostics*)>;
54   using ActionFunc = std::function<bool(Element*)>;
55 
56   // Find or create a child XmlNodeAction that will be performed for the child element with the
57   // name `name`.
58   XmlNodeAction& operator[](const std::string& name) {
59     return map_[name];
60   }
61 
62   // Add an action to be performed at this XmlNodeAction.
63   void Action(ActionFunc f);
64   void Action(ActionFuncWithDiag);
65   void Action(ActionFuncWithPolicyAndDiag);
66 
67  private:
68   friend class XmlActionExecutor;
69 
70   bool Execute(XmlActionExecutorPolicy policy, std::vector<::android::StringPiece>* bread_crumb,
71                android::SourcePathDiagnostics* diag, Element* el) const;
72 
73   std::map<std::string, XmlNodeAction> map_;
74   std::vector<ActionFuncWithPolicyAndDiag> actions_;
75 };
76 
77 // Allows the definition of actions to execute at specific XML elements defined by their hierarchy.
78 class XmlActionExecutor {
79  public:
80   XmlActionExecutor() = default;
81 
82   // Find or create a root XmlNodeAction that will be performed for the root XML element with the
83   // name `name`.
84   XmlNodeAction& operator[](const std::string& name) {
85     return map_[name];
86   }
87 
88   // Execute the defined actions for this XmlResource.
89   // Returns true if all actions return true, otherwise returns false.
90   bool Execute(XmlActionExecutorPolicy policy, android::IDiagnostics* diag, XmlResource* doc) const;
91 
92  private:
93   std::map<std::string, XmlNodeAction> map_;
94 
95   DISALLOW_COPY_AND_ASSIGN(XmlActionExecutor);
96 };
97 
98 }  // namespace xml
99 }  // namespace aapt
100 
101 #endif /* AAPT_XML_XMLPATTERN_H */
102