1 /*
2 * Copyright (c) 2002-2026 Gargoyle Software Inc.
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 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.javascript.host;
16
17 import java.util.ArrayList;
18 import java.util.List;
19
20 import org.htmlunit.corejs.javascript.Scriptable;
21 import org.htmlunit.javascript.HtmlUnitScriptable;
22 import org.htmlunit.javascript.JavaScriptEngine;
23 import org.htmlunit.javascript.configuration.JsxClass;
24 import org.htmlunit.javascript.configuration.JsxConstructor;
25 import org.htmlunit.javascript.configuration.JsxFunction;
26 import org.htmlunit.javascript.configuration.JsxGetter;
27 import org.htmlunit.javascript.configuration.JsxSymbol;
28
29 /**
30 * JavaScript host object for {@code PluginArray}.
31 *
32 * @author Marc Guillemot
33 * @author Ahmed Ashour
34 * @author Ronald Brill
35 *
36 * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/PluginArray">MDN Documentation</a>
37 */
38 @JsxClass
39 public class PluginArray extends HtmlUnitScriptable {
40
41 private final List<Plugin> elements_ = new ArrayList<>();
42
43 /**
44 * Creates an instance of this object.
45 */
46 @JsxConstructor
47 public void jsConstructor() {
48 // nothing to do
49 }
50
51 /**
52 * Returns the {@link Plugin} at the given index.
53 *
54 * @param index the index
55 * @return the {@link Plugin} at the given position, or {@code null} if out of range
56 */
57 @JsxFunction
58 public Plugin item(final int index) {
59 if (index >= 0 && index < elements_.size()) {
60 return elements_.get(index);
61 }
62 return null;
63 }
64
65 /**
66 * {@inheritDoc}
67 */
68 @Override
69 protected Object getWithPreemption(final String name) {
70 final Plugin response = namedItem(name);
71 if (response != null) {
72 return response;
73 }
74 return NOT_FOUND;
75 }
76
77 /**
78 * {@inheritDoc}
79 */
80 @Override
81 public boolean has(final String name, final Scriptable start) {
82 if (NOT_FOUND != getWithPreemption(name)) {
83 return true;
84 }
85
86 return super.has(name, start);
87 }
88
89 /**
90 * Returns the element at the specified index, or {@code null} if the index is invalid.
91 * {@inheritDoc}
92 */
93 @Override
94 public final Plugin get(final int index, final Scriptable start) {
95 final PluginArray array = (PluginArray) start;
96 final List<Plugin> elements = array.elements_;
97
98 if (index >= 0 && index < elements.size()) {
99 return elements.get(index);
100 }
101 return null;
102 }
103
104 /**
105 * Returns the {@link Plugin} with the given name.
106 *
107 * @param name the plugin name to look up
108 * @return the matching {@link Plugin}, or {@code null} if not found
109 */
110 @JsxFunction
111 public Plugin namedItem(final String name) {
112 for (final Plugin element : elements_) {
113 if (name.equals(getItemName(element))) {
114 return element;
115 }
116 }
117 return null;
118 }
119
120 /**
121 * Returns the number of plugins in this array.
122 *
123 * @return the number of elements
124 */
125 @JsxGetter
126 public int getLength() {
127 return elements_.size();
128 }
129
130 /**
131 * Refreshes the plugin list. Currently does nothing.
132 *
133 * @param reloadDocuments whether to reload all documents if the plugin list has changed
134 * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/PluginArray/refresh">MDN Documentation</a>
135 */
136 @JsxFunction
137 public void refresh(final boolean reloadDocuments) {
138 // nothing
139 }
140
141 /**
142 * Returns the name of the given plugin.
143 *
144 * @param element a {@link Plugin}
145 * @return the plugin name
146 */
147 protected String getItemName(final Object element) {
148 return ((Plugin) element).getName();
149 }
150
151 /**
152 * Adds a {@link Plugin} to this array.
153 *
154 * @param element the element to add
155 */
156 void add(final Plugin element) {
157 elements_.add(element);
158 }
159
160 /**
161 * Returns an iterator over the values in this array.
162 *
163 * @return the iterator
164 */
165 @JsxSymbol
166 public Scriptable iterator() {
167 return JavaScriptEngine.newArrayIteratorTypeValues(getParentScope(), this);
168 }
169 }