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 "CString.h" 31 #include "Command.h" 32 #include "Connection.h" 33 #include "DebugServer.h" 34 #include "Frame.h" 35 #include "RenderTreeAsText.h" 36 #include "RenderView.h" 37 #include "WebViewCore.h" 38 #include <utils/Log.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 //------------------------------------------------------------------------------ 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 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: 78 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: 90 InternalCommand(const Command* comm, const Frame* frame, 91 const Connection* connection) 92 : Command(*comm) 93 , m_frame(frame) 94 , m_connection(connection) {} 95 virtual ~InternalCommand() { delete m_connection; } 96 97 void doCommand() const { 98 LOGD("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 109 static void commandDispatcher(void* v) { 110 InternalCommand* c = static_cast<InternalCommand*>(v); 111 c->doCommand(); 112 delete c; 113 } 114 115 void Command::dispatch() { 116 m_handler.post(commandDispatcher, this); 117 } 118 119 Vector<const Command*>* Command::s_commands; 120 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 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