1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "WebDevToolsFrontendImpl.h" 33 34 #include "InspectorFrontendClientImpl.h" 35 #include "V8InspectorFrontendHost.h" 36 #include "V8MouseEvent.h" 37 #include "V8Node.h" 38 #include "WebDevToolsFrontendClient.h" 39 #include "WebFrameImpl.h" 40 #include "WebScriptSource.h" 41 #include "WebViewImpl.h" 42 #include "bindings/v8/ScriptController.h" 43 #include "bindings/v8/V8Binding.h" 44 #include "bindings/v8/V8DOMWrapper.h" 45 #include "bindings/v8/V8Utilities.h" 46 #include "core/dom/Document.h" 47 #include "core/dom/Event.h" 48 #include "core/dom/Node.h" 49 #include "core/inspector/InspectorController.h" 50 #include "core/inspector/InspectorFrontendHost.h" 51 #include "core/page/ContextMenuController.h" 52 #include "core/page/DOMWindow.h" 53 #include "core/page/Frame.h" 54 #include "core/page/Page.h" 55 #include "core/page/Settings.h" 56 #include "core/platform/ContextMenuItem.h" 57 #include "core/platform/Pasteboard.h" 58 #include "weborigin/SecurityOrigin.h" 59 #include "wtf/OwnPtr.h" 60 #include "wtf/Vector.h" 61 #include "wtf/text/WTFString.h" 62 63 using namespace WebCore; 64 65 namespace WebKit { 66 67 class WebDevToolsFrontendImpl::InspectorFrontendResumeObserver : public ActiveDOMObject { 68 WTF_MAKE_NONCOPYABLE(InspectorFrontendResumeObserver); 69 public: 70 InspectorFrontendResumeObserver(WebDevToolsFrontendImpl* webDevToolsFrontendImpl, Document* document) 71 : ActiveDOMObject(document) 72 , m_webDevToolsFrontendImpl(webDevToolsFrontendImpl) 73 { 74 suspendIfNeeded(); 75 } 76 77 private: 78 virtual bool canSuspend() const OVERRIDE 79 { 80 return true; 81 } 82 83 virtual void resume() OVERRIDE 84 { 85 m_webDevToolsFrontendImpl->resume(); 86 } 87 88 WebDevToolsFrontendImpl* m_webDevToolsFrontendImpl; 89 }; 90 91 WebDevToolsFrontend* WebDevToolsFrontend::create( 92 WebView* view, 93 WebDevToolsFrontendClient* client, 94 const WebString& applicationLocale) 95 { 96 return new WebDevToolsFrontendImpl( 97 static_cast<WebViewImpl*>(view), 98 client, 99 applicationLocale); 100 } 101 102 WebDevToolsFrontendImpl::WebDevToolsFrontendImpl( 103 WebViewImpl* webViewImpl, 104 WebDevToolsFrontendClient* client, 105 const String& applicationLocale) 106 : m_webViewImpl(webViewImpl) 107 , m_client(client) 108 , m_applicationLocale(applicationLocale) 109 , m_inspectorFrontendDispatchTimer(this, &WebDevToolsFrontendImpl::maybeDispatch) 110 { 111 InspectorController* ic = m_webViewImpl->page()->inspectorController(); 112 ic->setInspectorFrontendClient(adoptPtr(new InspectorFrontendClientImpl(m_webViewImpl->page(), m_client, this))); 113 114 // Put each DevTools frontend Page into a private group so that it's not 115 // deferred along with the inspected page. 116 m_webViewImpl->page()->setGroupType(Page::InspectorPageGroup); 117 } 118 119 WebDevToolsFrontendImpl::~WebDevToolsFrontendImpl() 120 { 121 } 122 123 void WebDevToolsFrontendImpl::dispatchOnInspectorFrontend(const WebString& message) 124 { 125 m_messages.append(message); 126 maybeDispatch(0); 127 } 128 129 void WebDevToolsFrontendImpl::resume() 130 { 131 // We should call maybeDispatch asynchronously here because we are not allowed to update activeDOMObjects list in 132 // resume (See ScriptExecutionContext::resumeActiveDOMObjects). 133 if (!m_inspectorFrontendDispatchTimer.isActive()) 134 m_inspectorFrontendDispatchTimer.startOneShot(0); 135 } 136 137 void WebDevToolsFrontendImpl::maybeDispatch(WebCore::Timer<WebDevToolsFrontendImpl>*) 138 { 139 while (!m_messages.isEmpty()) { 140 Document* document = m_webViewImpl->page()->mainFrame()->document(); 141 if (document->activeDOMObjectsAreSuspended()) { 142 m_inspectorFrontendResumeObserver = adoptPtr(new InspectorFrontendResumeObserver(this, document)); 143 return; 144 } 145 m_inspectorFrontendResumeObserver.clear(); 146 doDispatchOnInspectorFrontend(m_messages.takeFirst()); 147 } 148 } 149 150 void WebDevToolsFrontendImpl::doDispatchOnInspectorFrontend(const WebString& message) 151 { 152 WebFrameImpl* frame = m_webViewImpl->mainFrameImpl(); 153 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 154 v8::HandleScope scope; 155 v8::Handle<v8::Context> frameContext = frame->frame() ? frame->frame()->script()->currentWorldContext() : v8::Local<v8::Context>(); 156 v8::Context::Scope contextScope(frameContext); 157 v8::Handle<v8::Value> inspectorFrontendApiValue = frameContext->Global()->Get(v8::String::New("InspectorFrontendAPI")); 158 if (!inspectorFrontendApiValue->IsObject()) 159 return; 160 v8::Handle<v8::Object> inspectorFrontendApi = v8::Handle<v8::Object>::Cast(inspectorFrontendApiValue); 161 v8::Handle<v8::Value> dispatchFunction = inspectorFrontendApi->Get(v8::String::New("dispatchMessage")); 162 // The frame might have navigated away from the front-end page (which is still weird). 163 if (!dispatchFunction->IsFunction()) 164 return; 165 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(dispatchFunction); 166 Vector< v8::Handle<v8::Value> > args; 167 args.append(v8String(message, isolate)); 168 v8::TryCatch tryCatch; 169 tryCatch.SetVerbose(true); 170 ScriptController::callFunctionWithInstrumentation(frame->frame() ? frame->frame()->document() : 0, function, inspectorFrontendApi, args.size(), args.data()); 171 } 172 173 } // namespace WebKit 174