1 /*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #define LOG_TAG "wds"
27 #include "config.h"
28
29 #include "AndroidLog.h"
30 #include "Command.h"
31 #include "Connection.h"
32 #include "DebugServer.h"
33 #include "Frame.h"
34 #include "RenderTreeAsText.h"
35 #include "RenderView.h"
36 #include "WebViewCore.h"
37 #include <utils/Log.h>
38 #include <wtf/text/CString.h>
39
40 #if ENABLE(WDS)
41
42 using namespace WebCore;
43
44 namespace android {
45
46 namespace WDS {
47
48 //------------------------------------------------------------------------------
49 // Actual commands -- XXX should be moved somewhere else
50 //------------------------------------------------------------------------------
callDumpRenderTree(const Frame * frame,const Connection * conn)51 static bool callDumpRenderTree(const Frame* frame, const Connection* conn) {
52 CString str = externalRepresentation(frame->contentRenderer()).latin1();
53 conn->write(str.data(), str.length());
54 return true;
55 }
56
callDumpDomTree(const Frame * frame,const Connection * conn)57 static bool callDumpDomTree(const Frame* frame, const Connection* conn) {
58 WebViewCore::getWebViewCore(frame->view())->dumpDomTree(true);
59
60 FILE* f = fopen(DOM_TREE_LOG_FILE, "r");
61 if (!f) {
62 conn->write("Dom tree written to logcat\n");
63 } else {
64 char buf[512];
65 while (true) {
66 int nread = fread(buf, 1, sizeof(buf), f);
67 if (nread <= 0)
68 break;
69 conn->write(buf, nread);
70 }
71 fclose(f);
72 }
73 return true;
74 }
75
76 class WebCoreHandler : public Handler {
77 public:
post(TargetThreadFunction func,void * v) const78 virtual void post(TargetThreadFunction func, void* v) const {
79 callOnMainThread(func, v);
80 }
81 };
82 static WebCoreHandler s_webcoreHandler;
83
84 //------------------------------------------------------------------------------
85 // End command section
86 //------------------------------------------------------------------------------
87
88 class InternalCommand : public Command {
89 public:
InternalCommand(const Command * comm,const Frame * frame,const Connection * connection)90 InternalCommand(const Command* comm, const Frame* frame,
91 const Connection* connection)
92 : Command(*comm)
93 , m_frame(frame)
94 , m_connection(connection) {}
~InternalCommand()95 virtual ~InternalCommand() { delete m_connection; }
96
doCommand() const97 void doCommand() const {
98 ALOGD("Executing command '%s' (%s)", m_name, m_description);
99 if (!m_dispatch(m_frame, m_connection))
100 // XXX: Have useful failure messages
101 m_connection->write("EPIC FAIL!\n", 11);
102 }
103
104 private:
105 const Frame* m_frame;
106 const Connection* m_connection;
107 };
108
commandDispatcher(void * v)109 static void commandDispatcher(void* v) {
110 InternalCommand* c = static_cast<InternalCommand*>(v);
111 c->doCommand();
112 delete c;
113 }
114
dispatch()115 void Command::dispatch() {
116 m_handler.post(commandDispatcher, this);
117 }
118
119 Vector<const Command*>* Command::s_commands;
120
Init()121 void Command::Init() {
122 // Do not initialize twice.
123 if (s_commands)
124 return;
125 // XXX: Move this somewhere else.
126 s_commands = new Vector<const Command*>();
127 s_commands->append(new Command("DDOM", "Dump Dom Tree",
128 callDumpDomTree, s_webcoreHandler));
129 s_commands->append(new Command("DDRT", "Dump Render Tree",
130 callDumpRenderTree, s_webcoreHandler));
131 }
132
Find(const Connection * conn)133 Command* Command::Find(const Connection* conn) {
134 char buf[COMMAND_LENGTH];
135 if (conn->read(buf, sizeof(buf)) != COMMAND_LENGTH)
136 return NULL;
137
138 // Linear search of commands. TODO: binary search when more commands are
139 // added.
140 Vector<const Command*>::const_iterator i = s_commands->begin();
141 Vector<const Command*>::const_iterator end = s_commands->end();
142 while (i != end) {
143 if (strncmp(buf, (*i)->name(), sizeof(buf)) == 0)
144 return new InternalCommand(*i, server()->getFrame(0), conn);
145 i++;
146 }
147 return NULL;
148 }
149
150 } // end namespace WDS
151
152 } // end namespace android
153
154 #endif
155