• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
4  * Copyright (C) 2009 Google Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  *     * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "config.h"
34 #include "JSInspectorBackend.h"
35 
36 #include "Console.h"
37 #if ENABLE(DATABASE)
38 #include "Database.h"
39 #include "JSDatabase.h"
40 #endif
41 #include "ExceptionCode.h"
42 #include "Frame.h"
43 #include "FrameLoader.h"
44 #include "InspectorBackend.h"
45 #include "InspectorController.h"
46 #include "InspectorResource.h"
47 #include "JSDOMWindow.h"
48 #include "JSInspectedObjectWrapper.h"
49 #include "JSInspectorCallbackWrapper.h"
50 #include "JSNode.h"
51 #include "JSRange.h"
52 #include "Node.h"
53 #include "Page.h"
54 #include "TextIterator.h"
55 #include "VisiblePosition.h"
56 #include <runtime/JSArray.h>
57 #include <runtime/JSLock.h>
58 #include <wtf/Vector.h>
59 
60 #if ENABLE(JAVASCRIPT_DEBUGGER)
61 #include "JavaScriptCallFrame.h"
62 #include "JavaScriptDebugServer.h"
63 #include "JavaScriptProfile.h"
64 #include "JSJavaScriptCallFrame.h"
65 #include <profiler/Profile.h>
66 #include <profiler/Profiler.h>
67 #endif
68 
69 using namespace JSC;
70 
71 namespace WebCore {
72 
highlightDOMNode(JSC::ExecState *,const JSC::ArgList & args)73 JSValue JSInspectorBackend::highlightDOMNode(JSC::ExecState*, const JSC::ArgList& args)
74 {
75     if (args.size() < 1)
76         return jsUndefined();
77 
78     JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0));
79     if (!wrapper)
80         return jsUndefined();
81 
82     Node* node = toNode(wrapper->unwrappedObject());
83     if (!node)
84         return jsUndefined();
85 
86     impl()->highlight(node);
87 
88     return jsUndefined();
89 }
90 
search(ExecState * exec,const ArgList & args)91 JSValue JSInspectorBackend::search(ExecState* exec, const ArgList& args)
92 {
93     if (args.size() < 2)
94         return jsUndefined();
95 
96     Node* node = toNode(args.at(0));
97     if (!node)
98         return jsUndefined();
99 
100     String target = args.at(1).toString(exec);
101     if (exec->hadException())
102         return jsUndefined();
103 
104     MarkedArgumentBuffer result;
105     RefPtr<Range> searchRange(rangeOfContents(node));
106 
107     ExceptionCode ec = 0;
108     do {
109         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false));
110         if (resultRange->collapsed(ec))
111             break;
112 
113         // A non-collapsed result range can in some funky whitespace cases still not
114         // advance the range's start position (4509328). Break to avoid infinite loop.
115         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
116         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
117             break;
118 
119         result.append(toJS(exec, resultRange.get()));
120 
121         setStart(searchRange.get(), newStart);
122     } while (true);
123 
124     return constructArray(exec, result);
125 }
126 
127 #if ENABLE(DATABASE)
databaseTableNames(ExecState * exec,const ArgList & args)128 JSValue JSInspectorBackend::databaseTableNames(ExecState* exec, const ArgList& args)
129 {
130     if (args.size() < 1)
131         return jsUndefined();
132 
133     JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0));
134     if (!wrapper)
135         return jsUndefined();
136 
137     Database* database = toDatabase(wrapper->unwrappedObject());
138     if (!database)
139         return jsUndefined();
140 
141     MarkedArgumentBuffer result;
142 
143     Vector<String> tableNames = database->tableNames();
144     unsigned length = tableNames.size();
145     for (unsigned i = 0; i < length; ++i)
146         result.append(jsString(exec, tableNames[i]));
147 
148     return constructArray(exec, result);
149 }
150 #endif
151 
inspectedWindow(ExecState *,const ArgList &)152 JSValue JSInspectorBackend::inspectedWindow(ExecState*, const ArgList&)
153 {
154     InspectorController* ic = impl()->inspectorController();
155     if (!ic)
156         return jsUndefined();
157     JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame());
158     return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), inspectedWindow);
159 }
160 
setting(ExecState * exec,const ArgList & args)161 JSValue JSInspectorBackend::setting(ExecState* exec, const ArgList& args)
162 {
163     if (args.size() < 1)
164         return jsUndefined();
165 
166     String key = args.at(0).toString(exec);
167     if (exec->hadException())
168         return jsUndefined();
169 
170     InspectorController* ic = impl()->inspectorController();
171     if (!ic)
172         return jsUndefined();
173     const InspectorController::Setting& setting = ic->setting(key);
174 
175     switch (setting.type()) {
176         default:
177         case InspectorController::Setting::NoType:
178             return jsUndefined();
179         case InspectorController::Setting::StringType:
180             return jsString(exec, setting.string());
181         case InspectorController::Setting::DoubleType:
182             return jsNumber(exec, setting.doubleValue());
183         case InspectorController::Setting::IntegerType:
184             return jsNumber(exec, setting.integerValue());
185         case InspectorController::Setting::BooleanType:
186             return jsBoolean(setting.booleanValue());
187         case InspectorController::Setting::StringVectorType: {
188             MarkedArgumentBuffer stringsArray;
189             const Vector<String>& strings = setting.stringVector();
190             const unsigned length = strings.size();
191             for (unsigned i = 0; i < length; ++i)
192                 stringsArray.append(jsString(exec, strings[i]));
193             return constructArray(exec, stringsArray);
194         }
195     }
196 }
197 
setSetting(ExecState * exec,const ArgList & args)198 JSValue JSInspectorBackend::setSetting(ExecState* exec, const ArgList& args)
199 {
200     if (args.size() < 2)
201         return jsUndefined();
202 
203     String key = args.at(0).toString(exec);
204     if (exec->hadException())
205         return jsUndefined();
206 
207     InspectorController::Setting setting;
208 
209     JSValue value = args.at(1);
210     if (value.isUndefined() || value.isNull()) {
211         // Do nothing. The setting is already NoType.
212         ASSERT(setting.type() == InspectorController::Setting::NoType);
213     } else if (value.isString())
214         setting.set(value.toString(exec));
215     else if (value.isNumber())
216         setting.set(value.toNumber(exec));
217     else if (value.isBoolean())
218         setting.set(value.toBoolean(exec));
219     else {
220         JSArray* jsArray = asArray(value);
221         if (!jsArray)
222             return jsUndefined();
223         Vector<String> strings;
224         for (unsigned i = 0; i < jsArray->length(); ++i) {
225             String item = jsArray->get(exec, i).toString(exec);
226             if (exec->hadException())
227                 return jsUndefined();
228             strings.append(item);
229         }
230         setting.set(strings);
231     }
232 
233     if (exec->hadException())
234         return jsUndefined();
235 
236     InspectorController* ic = impl()->inspectorController();
237     if (ic)
238         ic->setSetting(key, setting);
239 
240     return jsUndefined();
241 }
242 
wrapCallback(ExecState * exec,const ArgList & args)243 JSValue JSInspectorBackend::wrapCallback(ExecState* exec, const ArgList& args)
244 {
245     if (args.size() < 1)
246         return jsUndefined();
247 
248     return JSInspectorCallbackWrapper::wrap(exec, args.at(0));
249 }
250 
251 #if ENABLE(JAVASCRIPT_DEBUGGER)
252 
currentCallFrame(ExecState * exec,const ArgList &)253 JSValue JSInspectorBackend::currentCallFrame(ExecState* exec, const ArgList&)
254 {
255     JavaScriptCallFrame* callFrame = impl()->currentCallFrame();
256     if (!callFrame || !callFrame->isValid())
257         return jsUndefined();
258 
259     // FIXME: I am not sure if this is actually needed. Can we just use exec?
260     ExecState* globalExec = callFrame->scopeChain()->globalObject()->globalExec();
261 
262     JSLock lock(SilenceAssertionsOnly);
263     return JSInspectedObjectWrapper::wrap(globalExec, toJS(exec, callFrame));
264 }
265 
profiles(JSC::ExecState * exec,const JSC::ArgList &)266 JSValue JSInspectorBackend::profiles(JSC::ExecState* exec, const JSC::ArgList&)
267 {
268     JSLock lock(SilenceAssertionsOnly);
269     MarkedArgumentBuffer result;
270     InspectorController* ic = impl()->inspectorController();
271     if (!ic)
272         return jsUndefined();
273     const Vector<RefPtr<Profile> >& profiles = ic->profiles();
274 
275     for (size_t i = 0; i < profiles.size(); ++i)
276         result.append(toJS(exec, profiles[i].get()));
277 
278     return constructArray(exec, result);
279 }
280 
281 #endif
282 
283 } // namespace WebCore
284