Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1315)

Side by Side Diff: plugins/org.chromium.sdk.wipbackend.wk120709/src/org/chromium/sdk/internal/wip/WipValueLoader.java

Issue 11829027: drop old backends (Closed) Base URL: https://chromedevtools.googlecode.com/svn/trunk
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 package org.chromium.sdk.internal.wip;
6
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.Collection;
10 import java.util.Collections;
11 import java.util.HashMap;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.atomic.AtomicInteger;
15
16 import org.chromium.sdk.CallbackSemaphore;
17 import org.chromium.sdk.JsObjectProperty;
18 import org.chromium.sdk.JsVariable;
19 import org.chromium.sdk.RelayOk;
20 import org.chromium.sdk.RemoteValueMapping;
21 import org.chromium.sdk.SyncCallback;
22 import org.chromium.sdk.internal.wip.WipExpressionBuilder.PropertyNameBuilder;
23 import org.chromium.sdk.internal.wip.WipExpressionBuilder.ValueNameBuilder;
24 import org.chromium.sdk.internal.wip.protocol.input.debugger.FunctionDetailsValu e;
25 import org.chromium.sdk.internal.wip.protocol.input.debugger.GetFunctionDetailsD ata;
26 import org.chromium.sdk.internal.wip.protocol.input.debugger.LocationValue;
27 import org.chromium.sdk.internal.wip.protocol.input.runtime.GetPropertiesData;
28 import org.chromium.sdk.internal.wip.protocol.input.runtime.PropertyDescriptorVa lue;
29 import org.chromium.sdk.internal.wip.protocol.output.debugger.GetFunctionDetails Params;
30 import org.chromium.sdk.internal.wip.protocol.output.runtime.GetPropertiesParams ;
31 import org.chromium.sdk.util.AsyncFuture;
32 import org.chromium.sdk.util.AsyncFuture.Callback;
33 import org.chromium.sdk.util.AsyncFutureRef;
34 import org.chromium.sdk.util.GenericCallback;
35 import org.chromium.sdk.util.MethodIsBlockingException;
36
37 /**
38 * Responsible for loading values of properties. It works in pair with {@link Wi pValueBuilder}.
39 * TODO: add a cache for already loaded values if remote protocol ever has
40 * permanent object ids (same object reported under the same id within a debug c ontext).
41 */
42 public abstract class WipValueLoader implements RemoteValueMapping {
43 private final WipTabImpl tabImpl;
44 private final AtomicInteger cacheStateRef = new AtomicInteger(1);
45 private final WipValueBuilder valueBuilder = new WipValueBuilder(this);
46
47 public WipValueLoader(WipTabImpl tabImpl) {
48 this.tabImpl = tabImpl;
49 }
50
51 @Override
52 public void clearCaches() {
53 cacheStateRef.incrementAndGet();
54 }
55
56 WipValueBuilder getValueBuilder() {
57 return valueBuilder;
58 }
59
60 WipTabImpl getTabImpl() {
61 return tabImpl;
62 }
63
64 /**
65 * Loads object properties. It starts and executes a load operation of a corre sponding
66 * {@link AsyncFuture}. The operation is fully synchronous, so this method nor mally
67 * blocks. There is a chance that other thread is already executing load opera tion.
68 * In this case the method will return immediately, but {@link AsyncFuture} wi ll hold
69 * thread until the operation finishes.
70 * @param innerNameBuilder name builder for qualified names of all properties and subproperties
71 * @param futureRef future reference that will hold result of load operation
72 */
73 void loadJsObjectPropertiesInFuture(final String objectId,
74 PropertyNameBuilder innerNameBuilder, boolean reload, int currentCacheStat e,
75 AsyncFutureRef<Getter<ObjectProperties>> futureRef) throws MethodIsBlockin gException {
76 ObjectPropertyProcessor propertyProcessor =
77 new ObjectPropertyProcessor(innerNameBuilder, objectId);
78 loadPropertiesInFuture(objectId, propertyProcessor, reload, currentCacheStat e, futureRef);
79 }
80
81 int getCacheState() {
82 return cacheStateRef.get();
83 }
84
85 abstract String getObjectGroupId();
86
87 /**
88 * A utility method that initializes {@link AsyncFuture} of an object without properties.
89 */
90 static void setEmptyJsObjectProperties(AsyncFutureRef<Getter<ObjectProperties> > output) {
91 output.initializeTrivial(EMPTY_OBJECT_PROPERTIES_GETTER);
92 }
93
94 /**
95 * A getter that either returns a value or throws an exception with some failu re description.
96 * Exception is the only means of passing message about some problem to user i n SDK API.
97 */
98 static abstract class Getter<T> {
99 abstract T get();
100
101 static <V> Getter<V> newNormal(final V value) {
102 return new Getter<V>() {
103 @Override
104 V get() {
105 return value;
106 }
107 };
108 }
109
110 static <S> Getter<S> newFailure(final Exception cause) {
111 return new Getter<S>() {
112 @Override
113 S get() {
114 throw new RuntimeException("Failed to load properties", cause);
115 }
116 };
117 }
118 }
119
120 interface ObjectProperties {
121 List<? extends JsObjectProperty> properties();
122 JsVariable getProperty(String name);
123
124 List<? extends JsVariable> internalProperties();
125 int getCacheState();
126 }
127
128 /**
129 * An abstract processor that is reads protocol response and creates proper
130 * property objects. This may be implemented differently for objects, function s or
131 * scopes.
132 */
133 interface LoadPostprocessor<RES> {
134 RES process(List<? extends PropertyDescriptorValue> propertyList, int curren tCacheState);
135 RES getEmptyResult();
136 RES forException(Exception exception);
137 }
138
139 private class ObjectPropertyProcessor implements LoadPostprocessor<Getter<Obje ctProperties>> {
140 private final PropertyNameBuilder propertyNameBuilder;
141 private final String objectId;
142
143 ObjectPropertyProcessor(PropertyNameBuilder propertyNameBuilder, String obje ctId) {
144 this.propertyNameBuilder = propertyNameBuilder;
145 this.objectId = objectId;
146 }
147
148 @Override
149 public Getter<ObjectProperties> process(
150 List<? extends PropertyDescriptorValue> propertyList, final int currentC acheState) {
151 final List<JsObjectProperty> properties =
152 new ArrayList<JsObjectProperty>(propertyList.size());
153 final List<JsVariable> internalProperties = new ArrayList<JsVariable>(2);
154
155 for (PropertyDescriptorValue propertyDescriptor : propertyList) {
156 String name = propertyDescriptor.name();
157 boolean isInternal = INTERNAL_PROPERTY_NAME.contains(name);
158
159 ValueNameBuilder valueNameBuilder =
160 WipExpressionBuilder.createValueOfPropertyNameBuilder(name, property NameBuilder);
161
162 JsObjectProperty property = valueBuilder.createObjectProperty(propertyDe scriptor,
163 objectId, valueNameBuilder);
164 if (isInternal) {
165 internalProperties.add(property);
166 } else {
167 properties.add(property);
168 }
169 }
170
171 final ObjectProperties result = new ObjectProperties() {
172 private volatile Map<String, JsVariable> propertyMap = null;
173
174 @Override
175 public List<? extends JsObjectProperty> properties() {
176 return properties;
177 }
178
179 @Override
180 public List<? extends JsVariable> internalProperties() {
181 return internalProperties;
182 }
183
184 @Override
185 public JsVariable getProperty(String name) {
186 Map<String, JsVariable> map = propertyMap;
187 if (map == null) {
188 List<? extends JsVariable> list = properties();
189 map = new HashMap<String, JsVariable>(list.size());
190 for (JsVariable property : list) {
191 map.put(property.getName(), property);
192 }
193 // Possibly overwrite other already created map, but we don't care a bout instance here.
194 propertyMap = map;
195 }
196 return map.get(name);
197 }
198
199 @Override
200 public int getCacheState() {
201 return currentCacheState;
202 }
203 };
204 return Getter.newNormal(result);
205 }
206
207 @Override
208 public Getter<ObjectProperties> getEmptyResult() {
209 return EMPTY_OBJECT_PROPERTIES_GETTER;
210 }
211
212 @Override
213 public Getter<ObjectProperties> forException(Exception exception) {
214 return Getter.newFailure(exception);
215 }
216 }
217
218 private static final Getter<ObjectProperties> EMPTY_OBJECT_PROPERTIES_GETTER =
219 Getter.newNormal(((ObjectProperties) new ObjectProperties() {
220 @Override public List<? extends JsObjectProperty> properties() {
221 return Collections.emptyList();
222 }
223 @Override public JsVariable getProperty(String name) {
224 return null;
225 }
226 @Override public List<? extends JsVariable> internalProperties() {
227 return Collections.emptyList();
228 }
229 @Override public int getCacheState() {
230 return Integer.MAX_VALUE;
231 }
232 }));
233
234 <RES> void loadPropertiesInFuture(final String objectId,
235 final LoadPostprocessor<RES> propertyPostprocessor, boolean reload,
236 final int currentCacheState, AsyncFutureRef<RES> futureRef)
237 throws MethodIsBlockingException {
238 if (objectId == null) {
239 futureRef.initializeTrivial(propertyPostprocessor.getEmptyResult());
240 return;
241 }
242
243 // The entire operation that first loads properties from remote and then pos tprocess them
244 // (without occupying Dispatch thread).
245 // The operation is sync because we don't want to do postprocessing in Dispa tch thread.
246 AsyncFuture.SyncOperation<RES> syncOperation = new AsyncFuture.SyncOperation <RES>() {
247 @Override
248 protected RES runSync() throws MethodIsBlockingException {
249 // Get response from remote.
250 LoadPropertiesResponse response = loadRawPropertiesSync(objectId);
251
252 // Process result.
253 return response.accept(new LoadPropertiesResponse.Visitor<RES>() {
254 @Override
255 public RES visitData(GetPropertiesData data) {
256 // TODO: check exception.
257 return propertyPostprocessor.process(data.result(), currentCacheStat e);
258 }
259
260 @Override
261 public RES visitFailure(final Exception exception) {
262 return propertyPostprocessor.forException(new RuntimeException(
263 "Failed to read properties from remote", exception));
264 }
265 });
266 }
267 };
268
269 if (reload) {
270 futureRef.reinitializeRunning(syncOperation.asAsyncOperation());
271 } else {
272 futureRef.initializeRunning(syncOperation.asAsyncOperation());
273 }
274 syncOperation.execute();
275 }
276
277 void loadFunctionLocationInFuture(final String objectId,
278 AsyncFutureRef<Getter<FunctionDetailsValue>> loadedPositionRef)
279 throws MethodIsBlockingException {
280
281 AsyncFuture.Operation<Getter<FunctionDetailsValue>> operation =
282 new AsyncFuture.Operation<Getter<FunctionDetailsValue>>() {
283 @Override
284 public RelayOk start(final Callback<Getter<FunctionDetailsValue>> callback ,
285 SyncCallback syncCallback) {
286 GetFunctionDetailsParams request = new GetFunctionDetailsParams(objectId );
287 GenericCallback<GetFunctionDetailsData> wrappedCallback =
288 new GenericCallback<GetFunctionDetailsData>() {
289 @Override public void success(GetFunctionDetailsData value) {
290 callback.done(Getter.newNormal(value.details()));
291 }
292
293 @Override public void failure(Exception exception) {
294 callback.done(Getter.<FunctionDetailsValue>newFailure(exception));
295 }
296 };
297 return tabImpl.getCommandProcessor().send(request, wrappedCallback, sync Callback);
298 }
299 };
300
301 loadedPositionRef.initializeRunning(operation);
302 }
303
304 /**
305 * Response is either data or error message. We wrap whatever it is for postpr ocessing
306 * that is conducted off Dispatch thread.
307 */
308 private static abstract class LoadPropertiesResponse {
309 interface Visitor<R> {
310 R visitData(GetPropertiesData response);
311
312 R visitFailure(Exception exception);
313 }
314 abstract <R> R accept(Visitor<R> visitor);
315 }
316
317 private LoadPropertiesResponse loadRawPropertiesSync(String objectId)
318 throws MethodIsBlockingException {
319 final LoadPropertiesResponse[] result = { null };
320 GenericCallback<GetPropertiesData> callback =
321 new GenericCallback<GetPropertiesData>() {
322 @Override
323 public void success(final GetPropertiesData value) {
324 result[0] = new LoadPropertiesResponse() {
325 @Override
326 <R> R accept(Visitor<R> visitor) {
327 return visitor.visitData(value);
328 }
329 };
330 }
331
332 @Override
333 public void failure(final Exception exception) {
334 result[0] = new LoadPropertiesResponse() {
335 @Override
336 <R> R accept(Visitor<R> visitor) {
337 return visitor.visitFailure(exception);
338 }
339 };
340 }
341 };
342
343 final GetPropertiesParams request;
344 {
345 boolean ownProperties = true;
346 request = new GetPropertiesParams(objectId, ownProperties);
347 }
348
349 CallbackSemaphore callbackSemaphore = new CallbackSemaphore();
350 RelayOk relayOk =
351 tabImpl.getCommandProcessor().send(request, callback, callbackSemaphore) ;
352 callbackSemaphore.acquireDefault(relayOk);
353
354 return result[0];
355 }
356
357 static WipValueLoader castArgument(RemoteValueMapping mapping) {
358 try {
359 return (WipValueLoader) mapping;
360 } catch (ClassCastException e) {
361 throw new IllegalArgumentException("Incorrect evaluate context argument", e);
362 }
363 }
364
365 // List is too short to use HashSet.
366 private static final Collection<String> INTERNAL_PROPERTY_NAME =
367 Arrays.asList("__proto__", "constructor");
368 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698