page.cpp

来自「linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自Web」· C++ 代码 · 共 653 行 · 第 1/2 页

CPP
653
字号
/* * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */#include "config.h"#include "Page.h"#include "Chrome.h"#include "ChromeClient.h"#include "ContextMenuClient.h"#include "ContextMenuController.h"#include "CSSStyleSelector.h"#include "EditorClient.h"#include "DOMWindow.h"#include "DragController.h"#include "EventNames.h"#include "FileSystem.h"#include "FocusController.h"#include "Frame.h"#include "FrameLoader.h"#include "FrameTree.h"#include "FrameView.h"#include "HistoryItem.h"#include "InspectorController.h"#include "Logging.h"#include "NetworkStateNotifier.h"#include "Navigator.h"#include "PageGroup.h"#include "PluginData.h"#include "ProgressTracker.h"#include "RenderWidget.h"#include "SelectionController.h"#include "Settings.h"#include "StringHash.h"#include "TextResourceDecoder.h"#include "Widget.h"#include "ScriptController.h"#include <wtf/HashMap.h>#include <wtf/RefCountedLeakCounter.h>#include <wtf/StdLibExtras.h>#if ENABLE(DOM_STORAGE)#include "LocalStorage.h"#include "SessionStorage.h"#include "StorageArea.h"#endif#if ENABLE(JAVASCRIPT_DEBUGGER)#include "JavaScriptDebugServer.h"#endif#if ENABLE(WML)#include "WMLPageState.h"#endifnamespace WebCore {static HashSet<Page*>* allPages;#ifndef NDEBUGstatic WTF::RefCountedLeakCounter pageCounter("Page");#endifstatic void networkStateChanged(){    Vector<RefPtr<Frame> > frames;        // Get all the frames of all the pages in all the page groups    HashSet<Page*>::iterator end = allPages->end();    for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {        for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())            frames.append(frame);    }    AtomicString eventName = networkStateNotifier().onLine() ? eventNames().onlineEvent : eventNames().offlineEvent;        for (unsigned i = 0; i < frames.size(); i++) {        Document* document = frames[i]->document();                // If the document does not have a body the event should be dispatched to the document        Node* eventTarget = document->body();        if (!eventTarget)            eventTarget = document;                eventTarget->dispatchEventForType(eventName, false, false);    }}Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient)    : m_chrome(new Chrome(this, chromeClient))    , m_dragCaretController(new SelectionController(0, true))    , m_dragController(new DragController(this, dragClient))    , m_focusController(new FocusController(this))    , m_contextMenuController(new ContextMenuController(this, contextMenuClient))    , m_inspectorController(InspectorController::create(this, inspectorClient))    , m_settings(new Settings(this))    , m_progress(new ProgressTracker)    , m_backForwardList(BackForwardList::create(this))    , m_editorClient(editorClient)    , m_frameCount(0)    , m_tabKeyCyclesThroughElements(true)    , m_defersLoading(false)    , m_inLowQualityInterpolationMode(false)    , m_cookieEnabled(true)    , m_areMemoryCacheClientCallsEnabled(true)    , m_mediaVolume(1)    , m_javaScriptURLsAreAllowed(true)    , m_parentInspectorController(0)    , m_didLoadUserStyleSheet(false)    , m_userStyleSheetModificationTime(0)    , m_group(0)    , m_debugger(0)    , m_pendingUnloadEventCount(0)    , m_pendingBeforeUnloadEventCount(0)    , m_customHTMLTokenizerTimeDelay(-1)    , m_customHTMLTokenizerChunkSize(-1){    if (!allPages) {        allPages = new HashSet<Page*>;                networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged);    }    ASSERT(!allPages->contains(this));    allPages->add(this);#if ENABLE(JAVASCRIPT_DEBUGGER)    JavaScriptDebugServer::shared().pageCreated(this);#endif#ifndef NDEBUG    pageCounter.increment();#endif}Page::~Page(){    m_mainFrame->setView(0);    setGroupName(String());    allPages->remove(this);        for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())        frame->pageDestroyed();    m_editorClient->pageDestroyed();    if (m_parentInspectorController)        m_parentInspectorController->pageDestroyed();    m_inspectorController->inspectedPageDestroyed();    m_backForwardList->close();#ifndef NDEBUG    pageCounter.decrement();    // Cancel keepAlive timers, to ensure we release all Frames before exiting.    // It's safe to do this because we prohibit closing a Page while JavaScript    // is executing.    Frame::cancelAllKeepAlive();#endif}void Page::setMainFrame(PassRefPtr<Frame> mainFrame){    ASSERT(!m_mainFrame); // Should only be called during initialization    m_mainFrame = mainFrame;}BackForwardList* Page::backForwardList(){    return m_backForwardList.get();}bool Page::goBack(){    HistoryItem* item = m_backForwardList->backItem();        if (item) {        goToItem(item, FrameLoadTypeBack);        return true;    }    return false;}bool Page::goForward(){    HistoryItem* item = m_backForwardList->forwardItem();        if (item) {        goToItem(item, FrameLoadTypeForward);        return true;    }    return false;}void Page::goToItem(HistoryItem* item, FrameLoadType type){    // Abort any current load if we're going to a history item    m_mainFrame->loader()->stopAllLoaders();    m_mainFrame->loader()->goToItem(item, type);}void Page::setGlobalHistoryItem(HistoryItem* item){    m_globalHistoryItem = item;}void Page::setGroupName(const String& name){    if (m_group && !m_group->name().isEmpty()) {        ASSERT(m_group != m_singlePageGroup.get());        ASSERT(!m_singlePageGroup);        m_group->removePage(this);    }    if (name.isEmpty())        m_group = m_singlePageGroup.get();    else {        m_singlePageGroup.clear();        m_group = PageGroup::pageGroup(name);        m_group->addPage(this);    }}const String& Page::groupName() const{    DEFINE_STATIC_LOCAL(String, nullString, ());    return m_group ? m_group->name() : nullString;}void Page::initGroup(){    ASSERT(!m_singlePageGroup);    ASSERT(!m_group);    m_singlePageGroup.set(new PageGroup(this));    m_group = m_singlePageGroup.get();}void Page::setNeedsReapplyStyles(){    if (!allPages)        return;    HashSet<Page*>::iterator end = allPages->end();    for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)        for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())            frame->setNeedsReapplyStyles();}void Page::refreshPlugins(bool reload){    if (!allPages)        return;    PluginData::refresh();    Vector<RefPtr<Frame> > framesNeedingReload;    HashSet<Page*>::iterator end = allPages->end();    for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {        (*it)->m_pluginData = 0;        if (reload) {            for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) {                if (frame->loader()->containsPlugins())                    framesNeedingReload.append(frame);            }        }    }    for (size_t i = 0; i < framesNeedingReload.size(); ++i)        framesNeedingReload[i]->loader()->reload();}PluginData* Page::pluginData() const{    if (!settings()->arePluginsEnabled())        return 0;    if (!m_pluginData)        m_pluginData = PluginData::create(this);    return m_pluginData.get();}static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag){    return forward        ? curr->tree()->traverseNextWithWrap(wrapFlag)        : curr->tree()->traversePreviousWithWrap(wrapFlag);}bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity, FindDirection direction, bool shouldWrap){    if (target.isEmpty() || !mainFrame())        return false;    Frame* frame = focusController()->focusedOrMainFrame();    Frame* startFrame = frame;    do {        if (frame->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, false, true)) {            if (frame != startFrame)                startFrame->selection()->clear();            focusController()->setFocusedFrame(frame);            return true;        }        frame = incrementFrame(frame, direction == FindDirectionForward, shouldWrap);    } while (frame && frame != startFrame);    // Search contents of startFrame, on the other side of the selection that we did earlier.    // We cheat a bit and just research with wrap on    if (shouldWrap && !startFrame->selection()->isNone()) {        bool found = startFrame->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, true, true);        focusController()->setFocusedFrame(frame);        return found;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?