1 // Copyright 2014 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 "gn/visibility.h"
6
7 #include <memory>
8 #include <string_view>
9
10 #include "base/strings/string_util.h"
11 #include "base/values.h"
12 #include "gn/err.h"
13 #include "gn/filesystem_utils.h"
14 #include "gn/item.h"
15 #include "gn/label.h"
16 #include "gn/ohos_components.h"
17 #include "gn/ohos_components_checker.h"
18 #include "gn/scope.h"
19 #include "gn/value.h"
20 #include "gn/variables.h"
21
22 Visibility::Visibility() = default;
23
24 Visibility::~Visibility() = default;
25
Set(const SourceDir & current_dir,std::string_view source_root,const Value & value,Err * err)26 bool Visibility::Set(const SourceDir& current_dir,
27 std::string_view source_root,
28 const Value& value,
29 Err* err) {
30 patterns_.clear();
31
32 if (!value.VerifyTypeIs(Value::LIST, err)) {
33 CHECK(err->has_error());
34 return false;
35 }
36
37 for (const auto& item : value.list_value()) {
38 patterns_.push_back(
39 LabelPattern::GetPattern(current_dir, source_root, item, err));
40 if (err->has_error())
41 return false;
42 }
43 return true;
44 }
45
SetPublic()46 void Visibility::SetPublic() {
47 patterns_.clear();
48 patterns_.push_back(LabelPattern(LabelPattern::RECURSIVE_DIRECTORY,
49 SourceDir(), std::string(), Label()));
50 }
51
SetPrivate(const SourceDir & current_dir)52 void Visibility::SetPrivate(const SourceDir& current_dir) {
53 patterns_.clear();
54 patterns_.push_back(LabelPattern(LabelPattern::DIRECTORY, current_dir,
55 std::string(), Label()));
56 }
57
CanSeeMe(const Label & label) const58 bool Visibility::CanSeeMe(const Label& label) const {
59 return LabelPattern::VectorMatches(patterns_, label);
60 }
61
Describe(int indent,bool include_brackets) const62 std::string Visibility::Describe(int indent, bool include_brackets) const {
63 std::string outer_indent_string(indent, ' ');
64
65 if (patterns_.empty())
66 return outer_indent_string + "[] (no visibility)\n";
67
68 std::string result;
69
70 std::string inner_indent_string = outer_indent_string;
71 if (include_brackets) {
72 result += outer_indent_string + "[\n";
73 // Indent the insides more if brackets are requested.
74 inner_indent_string += " ";
75 }
76
77 for (const auto& pattern : patterns_)
78 result += inner_indent_string + pattern.Describe() + "\n";
79
80 if (include_brackets)
81 result += outer_indent_string + "]\n";
82 return result;
83 }
84
AsValue() const85 std::unique_ptr<base::Value> Visibility::AsValue() const {
86 auto res = std::make_unique<base::ListValue>();
87 for (const auto& pattern : patterns_)
88 res->AppendString(pattern.Describe());
89 return res;
90 }
91
92 // static
CheckItemVisibility(const Item * from,const Item * to,bool is_external_deps,Err * err)93 bool Visibility::CheckItemVisibility(const Item *from, const Item *to, bool is_external_deps, Err *err) {
94 std::string to_label = to->label().GetUserVisibleName(false);
95 std::string from_label = from->label().GetUserVisibleName(false);
96 if (!to->visibility().CanSeeMe(from->label())) {
97 *err = Err(from->defined_from(), "Dependency not allowed.",
98 "The item " + from->label().GetUserVisibleName(false) +
99 "\n"
100 "can not depend on " +
101 to_label +
102 "\n"
103 "because it is not in " +
104 to_label + "'s visibility list: " + to->visibility().Describe(0, true));
105 return false;
106 }
107 const OhosComponent *from_component = from->ohos_component();
108 const OhosComponent *to_component = to->ohos_component();
109 if ((from_component == nullptr) || (to_component == nullptr)) {
110 return true;
111 }
112 if (to_component->name() == "build_framework") {
113 return true;
114 }
115 if (from_component->name() == "build_framework") {
116 return true;
117 }
118 if (from_component == to_component) {
119 return true;
120 }
121
122 OhosComponentChecker *checker = OhosComponentChecker::getInstance();
123 if (checker != nullptr) {
124 if (!checker->CheckInnerApiNotLib(to, to_component, from_label, to_label, err) ||
125 !checker->CheckInnerApiNotDeclare(to, to_component, to_label, err) ||
126 !checker->CheckTargetAbsoluteDepsOther(from, to_component, from_label, to_label, is_external_deps, err) ||
127 !checker->CheckInnerApiVisibilityDenied(from, to_component, from_label, to_label, err)) {
128 return false;
129 }
130 }
131 return true;
132 }
133
134 // static
FillItemVisibility(Item * item,Scope * scope,Err * err)135 bool Visibility::FillItemVisibility(Item* item, Scope* scope, Err* err) {
136 const Value* vis_value = scope->GetValue(variables::kVisibility, true);
137 if (vis_value)
138 item->visibility().Set(
139 scope->GetSourceDir(),
140 scope->settings()->build_settings()->root_path_utf8(), *vis_value, err);
141 else // Default to public.
142 item->visibility().SetPublic();
143 return !err->has_error();
144 }
145