📄 inspectorcontroller.cpp
字号:
/* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "InspectorController.h"#include "CString.h"#include "CachedResource.h"#include "Console.h"#include "ConsoleMessage.h"#include "DOMWindow.h"#include "DocLoader.h"#include "Document.h"#include "DocumentLoader.h"#include "Element.h"#include "FloatConversion.h"#include "FloatQuad.h"#include "FloatRect.h"#include "Frame.h"#include "FrameLoader.h"#include "FrameTree.h"#include "FrameView.h"#include "GraphicsContext.h"#include "HTMLFrameOwnerElement.h"#include "HitTestResult.h"#include "InspectorClient.h"#include "InspectorDatabaseResource.h"#include "InspectorDOMStorageResource.h"#include "InspectorResource.h"#include "JSDOMWindow.h"#include "JSInspectedObjectWrapper.h"#include "JSInspectorCallbackWrapper.h"#include "JSInspectorController.h"#include "JSNode.h"#include "JSRange.h"#include "JavaScriptProfile.h"#include "Page.h"#include "Range.h"#include "RenderInline.h"#include "ResourceRequest.h"#include "ResourceResponse.h"#include "ScriptCallStack.h"#include "ScriptController.h"#include "SecurityOrigin.h"#include "Settings.h"#include "SharedBuffer.h"#include "TextEncoding.h"#include "TextIterator.h"#include <JavaScriptCore/APICast.h>#include <JavaScriptCore/JSRetainPtr.h>#include <JavaScriptCore/JSStringRef.h>#include <JavaScriptCore/OpaqueJSString.h>#include <profiler/Profile.h>#include <profiler/Profiler.h>#include <runtime/CollectorHeapIterator.h>#include <runtime/JSLock.h>#include <runtime/UString.h>#include <wtf/CurrentTime.h>#include <wtf/RefCounted.h>#include <wtf/StdLibExtras.h>#if ENABLE(DATABASE)#include "Database.h"#include "JSDatabase.h"#endif#if ENABLE(DOM_STORAGE)#include "Storage.h"#include "StorageArea.h"#include "JSStorage.h"#endif#if ENABLE(JAVASCRIPT_DEBUGGER)#include "JavaScriptCallFrame.h"#include "JavaScriptDebugServer.h"#include "JSJavaScriptCallFrame.h"#endifusing namespace JSC;using namespace std;namespace WebCore {static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";static JSRetainPtr<JSStringRef> jsStringRef(const char* str){ return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(str));}static JSRetainPtr<JSStringRef> jsStringRef(const SourceCode& str){ return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithCharacters(str.data(), str.length()));}static JSRetainPtr<JSStringRef> jsStringRef(const String& str){ return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithCharacters(str.characters(), str.length()));}static JSRetainPtr<JSStringRef> jsStringRef(const UString& str){ return JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(str).releaseRef());}static String toString(JSContextRef context, JSValueRef value, JSValueRef* exception){ ASSERT_ARG(value, value); if (!value) return String(); JSRetainPtr<JSStringRef> scriptString(Adopt, JSValueToStringCopy(context, value, exception)); if (exception && *exception) return String(); return String(JSStringGetCharactersPtr(scriptString.get()), JSStringGetLength(scriptString.get()));}#define HANDLE_EXCEPTION(context, exception) handleException((context), (exception), __LINE__)JSValueRef InspectorController::callSimpleFunction(JSContextRef context, JSObjectRef thisObject, const char* functionName) const{ JSValueRef exception = 0; return callFunction(context, thisObject, functionName, 0, 0, exception);}JSValueRef InspectorController::callFunction(JSContextRef context, JSObjectRef thisObject, const char* functionName, size_t argumentCount, const JSValueRef arguments[], JSValueRef& exception) const{ ASSERT_ARG(context, context); ASSERT_ARG(thisObject, thisObject); if (exception) return JSValueMakeUndefined(context); JSValueRef functionProperty = JSObjectGetProperty(context, thisObject, jsStringRef(functionName).get(), &exception); if (HANDLE_EXCEPTION(context, exception)) return JSValueMakeUndefined(context); JSObjectRef function = JSValueToObject(context, functionProperty, &exception); if (HANDLE_EXCEPTION(context, exception)) return JSValueMakeUndefined(context); JSValueRef result = JSObjectCallAsFunction(context, function, thisObject, argumentCount, arguments, &exception); if (HANDLE_EXCEPTION(context, exception)) return JSValueMakeUndefined(context); return result;}bool InspectorController::addSourceToFrame(const String& mimeType, const String& source, Node* frameNode){ ASSERT_ARG(frameNode, frameNode); if (!frameNode) return false; if (!frameNode->attached()) { ASSERT_NOT_REACHED(); return false; } ASSERT(frameNode->isElementNode()); if (!frameNode->isElementNode()) return false; Element* element = static_cast<Element*>(frameNode); ASSERT(element->isFrameOwnerElement()); if (!element->isFrameOwnerElement()) return false; HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element); ASSERT(frameOwner->contentFrame()); if (!frameOwner->contentFrame()) return false; FrameLoader* loader = frameOwner->contentFrame()->loader(); loader->setResponseMIMEType(mimeType); loader->begin(); loader->write(source); loader->end(); return true;}const String& InspectorController::platform() const{#if PLATFORM(MAC)#ifdef BUILDING_ON_TIGER DEFINE_STATIC_LOCAL(const String, platform, ("mac-tiger"));#else DEFINE_STATIC_LOCAL(const String, platform, ("mac-leopard"));#endif#elif PLATFORM(WIN_OS) DEFINE_STATIC_LOCAL(const String, platform, ("windows"));#elif PLATFORM(QT) DEFINE_STATIC_LOCAL(const String, platform, ("qt"));#elif PLATFORM(GTK) DEFINE_STATIC_LOCAL(const String, platform, ("gtk"));#elif PLATFORM(WX) DEFINE_STATIC_LOCAL(const String, platform, ("wx"));#else DEFINE_STATIC_LOCAL(const String, platform, ("unknown"));#endif return platform;}static unsigned s_inspectorControllerCount;static HashMap<String, InspectorController::Setting*>* s_settingCache;InspectorController::InspectorController(Page* page, InspectorClient* client) : m_inspectedPage(page) , m_client(client) , m_page(0) , m_scriptObject(0) , m_controllerScriptObject(0) , m_scriptContext(0) , m_windowVisible(false)#if ENABLE(JAVASCRIPT_DEBUGGER) , m_debuggerEnabled(false) , m_attachDebuggerWhenShown(false)#endif , m_profilerEnabled(false) , m_recordingUserInitiatedProfile(false) , m_showAfterVisible(ElementsPanel) , m_nextIdentifier(-2) , m_groupLevel(0) , m_searchingForNode(false) , m_currentUserInitiatedProfileNumber(-1) , m_nextUserInitiatedProfileNumber(1) , m_previousMessage(0) , m_startProfiling(this, &InspectorController::startUserInitiatedProfiling){ ASSERT_ARG(page, page); ASSERT_ARG(client, client); ++s_inspectorControllerCount;}InspectorController::~InspectorController(){ m_client->inspectorDestroyed(); if (m_scriptContext) { JSValueRef exception = 0; JSObjectRef global = JSContextGetGlobalObject(m_scriptContext); JSValueRef controllerProperty = JSObjectGetProperty(m_scriptContext, global, jsStringRef("InspectorController").get(), &exception); if (!HANDLE_EXCEPTION(m_scriptContext, exception)) { if (JSObjectRef controller = JSValueToObject(m_scriptContext, controllerProperty, &exception)) { if (!HANDLE_EXCEPTION(m_scriptContext, exception)) JSObjectSetPrivate(controller, 0); } } } if (m_page) m_page->setParentInspectorController(0); // m_inspectedPage should have been cleared in inspectedPageDestroyed(). ASSERT(!m_inspectedPage); deleteAllValues(m_frameResources); deleteAllValues(m_consoleMessages); ASSERT(s_inspectorControllerCount); --s_inspectorControllerCount; if (!s_inspectorControllerCount && s_settingCache) { deleteAllValues(*s_settingCache); delete s_settingCache; s_settingCache = 0; }}void InspectorController::inspectedPageDestroyed(){ ASSERT(m_inspectedPage); m_inspectedPage = 0; close();}bool InspectorController::enabled() const{ if (!m_inspectedPage) return false; return m_inspectedPage->settings()->developerExtrasEnabled();}const InspectorController::Setting& InspectorController::setting(const String& key) const{ if (!s_settingCache) s_settingCache = new HashMap<String, Setting*>; if (Setting* cachedSetting = s_settingCache->get(key)) return *cachedSetting; Setting* newSetting = new Setting; s_settingCache->set(key, newSetting); m_client->populateSetting(key, *newSetting); return *newSetting;}void InspectorController::setSetting(const String& key, const Setting& setting){ if (setting.type() == Setting::NoType) { if (s_settingCache) { Setting* cachedSetting = s_settingCache->get(key); if (cachedSetting) { s_settingCache->remove(key); delete cachedSetting; } } m_client->removeSetting(key); return; } if (!s_settingCache) s_settingCache = new HashMap<String, Setting*>; if (Setting* cachedSetting = s_settingCache->get(key)) *cachedSetting = setting; else s_settingCache->set(key, new Setting(setting)); m_client->storeSetting(key, setting);}String InspectorController::localizedStringsURL(){ if (!enabled()) return String(); return m_client->localizedStringsURL();}String InspectorController::hiddenPanels(){ if (!enabled()) return String(); return m_client->hiddenPanels();}// Trying to inspect something in a frame with JavaScript disabled would later lead to// crashes trying to create JavaScript wrappers. Some day we could fix this issue, but// for now prevent crashes here by never targeting a node in such a frame.static bool canPassNodeToJavaScript(Node* node){ if (!node) return false; Frame* frame = node->document()->frame(); return frame && frame->script()->isEnabled();}void InspectorController::inspect(Node* node){ if (!canPassNodeToJavaScript(node) || !enabled()) return; show(); if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE) node = node->parentNode(); m_nodeToFocus = node; if (!m_scriptObject) { m_showAfterVisible = ElementsPanel; return; } if (windowVisible()) focusNode();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -