Hi,

I've still been tracking memory leaks in our application, and I think I have a 
good test scenario to share.

In our application we found that a lot of memory would be held onto when 
visiting this particular site:
http://answers.ea.com
In a loop we visit this site, and a simple html page that consists of a list of 
test urls found on the local hard drive.
Our in built memory tools suggest a leak is coming largely from  
CSSParser::parseFontFaceSrc(), though admittedly I've changed my top suspects 
from time to time.  I think this item is showing as a large leak due to the 
inclusion of the font in the css on the answers.ea.com page, but perhaps there 
are more smaller items being leaked which is just less obvious (the font is 
large).

I've reproduce the scenario in the WinCairo test application, based on 188436.  
I built in a quick and hacky soak mechanism to conduct the test, perhaps there 
are better tools I'm not aware of.  I've attached the source changes to this 
mail:
Source/WebKit/win/WebKitMessageLoop.cpp
Tools/WinLauncher/Common.cpp

I can see the memory of the WinLauncher process grow over time, here is an 
example of the memory usage as seen from the windows task manager over time:
Duration    Memory (reported by windows)
0m                          155MB
13m                       178MB
23m                       199MB
36m                       219MB
53m                       247MB
1h4m                     259MB
1h23m                  277MB
After about an 1h30m, WinLauncher crashes, at the end of the mail is the basic 
debug data that was available.

I'm not sure if the crash is related to the memory leak I'm experiencing, or if 
it's an unrelated issue.  Since we're a few months older from tip I'm wondering 
if anyone has any recent insights to share on this memory leak scenario? I 
haven't identified anything in the change logs, but perhaps there is there 
something already addressing this?  Does the same issue occur at tip?

Any feedback is appreciated,

Thanks

Chris Vienneau




+                             this         0x00000000784be130 
{m_fontMetrics={m_unitsPerEm=1000 m_ascent=0.000000000 m_descent=0.000000000 
...} ...} WebCore::Font *
                                ascent   0.000000000       float
                                dc           Variable is optimized away and not 
available.
+                             extents {x_bearing=0.00000000000000000 
y_bearing=2.840573810841e-316#DEN width=1.197610077640e-309#DEN ...}     
cairo_text_extents_t
                                metricsMultiplier             
0.031250000000000000  const double
                                faceName           Variable is optimized away 
and not available.
                                descent                52852716.0          float
                                xHeight Variable is optimized away and not 
available.
+                             textMetrics        {tmHeight=0 tmAscent=0 
tmDescent=1691286912 ...}     tagTEXTMETRICW
                                lineGap 63069964.0          float
                                scaledFont          0x000000006477fc00 {...}    
           _cairo_scaled_font *
                                faceLength         0              int


>             WebKit.dll!WebCore::Font::platformInit() Line 82             C++
               WebKit.dll!WebCore::Font::Font(const WebCore::FontPlatformData & 
platformData, bool isCustomFont, bool isLoading, bool 
isTextOrientationFallback) Line 80   C++
               WebKit.dll!WebCore::CachedFont::createFont(const 
WebCore::FontDescription & fontDescription, const WTF::AtomicString & __formal, 
bool syntheticBold, bool syntheticItalic, bool __formal) Line 126               
 C++
               WebKit.dll!WebCore::CSSFontFaceSource::font(const 
WebCore::FontDescription & fontDescription, bool syntheticBold, bool 
syntheticItalic, WebCore::CSSFontSelector * fontSelector) Line 138 C++
               WebKit.dll!WebCore::CSSFontFace::font(const 
WebCore::FontDescription & fontDescription, bool syntheticBold, bool 
syntheticItalic) Line 127         C++
               WebKit.dll!WebCore::CSSSegmentedFontFace::fontRanges(const 
WebCore::FontDescription & fontDescription) Line 130             C++
               WebKit.dll!WebCore::CSSFontSelector::fontRangesForFamily(const 
WebCore::FontDescription & fontDescription, const WTF::AtomicString & 
familyName) Line 474           C++
               WebKit.dll!WebCore::realizeNextFallback(const 
WebCore::FontDescription & description, unsigned int & index, 
WebCore::FontSelector * fontSelector) Line 90    C++
               
WebKit.dll!WebCore::FontCascadeFonts::realizeFallbackRangesAt(const 
WebCore::FontDescription & description, unsigned int index) Line 114            
   C++
               WebKit.dll!WebCore::FontCascadeFonts::determinePitch(const 
WebCore::FontDescription & description) Line 64  C++
                
WebKit.dll!WebCore::BreakingContext::handleText(WTF::Vector<WebCore::WordMeasurement,64,WTF::CrashOnOverflow,16>
 & wordMeasurements, bool & hyphenated, unsigned int & 
consecutiveHyphenatedLines) Line 731        C++
                
WebKit.dll!WebCore::LineBreaker::nextLineBreak(WebCore::BidiResolver<WebCore::InlineIterator,WebCore::BidiRun>
 & resolver, WebCore::LineInfo & lineInfo, WebCore::RenderTextInfo & 
renderTextInfo, WebCore::FloatingObject * lastFloatFromPreviousLine, unsigned 
int consecutiveHyphenatedLines, 
WTF::Vector<WebCore::WordMeasurement,64,WTF::CrashOnOverflow,16> & 
wordMeasurements) Line 110   C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange(WebCore::LineLayoutState
 & layoutState, WebCore::BidiResolver<WebCore::InlineIterator,WebCore::BidiRun> 
& resolver, const WebCore::InlineIterator & cleanLineStart, const 
WebCore::BidiStatus & cleanLineBidiStatus, unsigned int 
consecutiveHyphenatedLines) Line 1260               C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutRunsAndFloats(WebCore::LineLayoutState
 & layoutState, bool hasInlineChild) Line 1214    C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutLineBoxes(bool 
relayoutChildren, WebCore::LayoutUnit & repaintLogicalTop, WebCore::LayoutUnit 
& repaintLogicalBottom) Line 1624        C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 484        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::insertFloatingObject(WebCore::RenderBox & 
floatBox) Line 2247                C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 627         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               
WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox & 
child, WebCore::RenderBlockFlow::MarginInfo & marginInfo, WebCore::LayoutUnit & 
previousFloatLogicalBottom, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 
712            C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlockChildren(bool 
relayoutChildren, WebCore::LayoutUnit & maxFloatLogicalBottom) Line 632         
     C++
               WebKit.dll!WebCore::RenderBlockFlow::layoutBlock(bool 
relayoutChildren, WebCore::LayoutUnit pageLogicalHeight) Line 485        C++
               WebKit.dll!WebCore::RenderBlock::layout() Line 930      C++
               WebKit.dll!WebCore::RenderView::layoutContent(const 
WebCore::LayoutState & state) Line 256           C++
               WebKit.dll!WebCore::RenderView::layout() Line 382      C++
               WebKit.dll!WebCore::FrameView::layout(bool allowSubtree) Line 
1429 C++
               WebKit.dll!WebCore::Document::updateLayout() Line 1889        C++
                
WebKit.dll!WebCore::Document::updateLayoutIgnorePendingStylesheets(WebCore::Document::RunPostLayoutTasks
 runPostLayoutTasks) Line 1922  C++
               WebKit.dll!WebCore::Element::getBoundingClientRect() Line 1071   
       C++
               
WebKit.dll!WebCore::jsElementPrototypeFunctionGetBoundingClientRect(JSC::ExecState
 * exec) Line 5165                C++
               [External Code]
               JavaScriptCore.dll!llint_entry() Line 8217               Unknown
               [External Code]
               JavaScriptCore.dll!llint_entry() Line 8217               Unknown


From: Vienneau, Christopher
Sent: Friday, November 20, 2015 5:20 PM
To: 'WebKit Development' <webkit-dev@lists.webkit.org>
Subject: RE: Memory leak tracking in WebKit

To add some more information to this, the allocation that seems to have the 
largest delta amount of allocations between test iterations is:
\wtf\local\wtf\hashtable.h(1248): 
WTF::HashTable<WTF::RefPtr<WTF::UniquedStringImpl>,WTF::KeyValuePair<WTF::RefPtr<WTF::UniquedStringImpl>,JSC::VariableEnvironmentEntry>,WTF::KeyValuePairKeyExtractor<WTF::KeyValuePair<WTF::RefPtr<WTF::UniquedStringImpl>,JSC::VariableEnvironmentEntry>
 
>,JSC::IdentifierRepHash,WTF::HashMap<WTF::RefPtr<WTF::UniquedStringImpl>,JSC::VariableEnvironmentEntry,JSC::IdentifierRepHash,WTF::HashTraits<WTF::RefPtr<WTF::UniquedStringImpl>
 
>,JSC::VariableEnvironmentEntryHashTraits>::KeyValuePairTraits,WTF::HashTraits<WTF::RefPtr<WTF::UniquedStringImpl>
 > 
>::HashTable<WTF::RefPtr<WTF::UniquedStringImpl>,WTF::KeyValuePair<WTF::RefPtr<WTF::UniquedStringImpl>,JSC::VariableEnvironmentEntry>,WTF::KeyValuePairKeyExtractor<WTF::KeyValuePair<WTF::RefPtr<WTF::UniquedStringImpl>,JSC::VariableEnvironmentEntry>
 
>,JSC::IdentifierRepHash,WTF::HashMap<WTF::RefPtr<WTF::UniquedStringImpl>,JSC::VariableEnvironmentEntry,JSC::IdentifierRepHash,WTF::HashTraits<WTF::RefPtr<WTF::UniquedStringImpl>
 
>,JSC::VariableEnvironmentEntryHashTraits>::KeyValuePairTraits,WTF::HashTraits<WTF::RefPtr<WTF::UniquedStringImpl>
 > > + 153
\javascriptcore\local\javascriptcore\parser\parser.cpp(1347): 
JSC::Parser<JSC::Lexer<unsigned char> >::parseTryStatement<JSC::ASTBuilder> + 
1984
\javascriptcore\local\javascriptcore\parser\parser.cpp(1480): 
JSC::Parser<JSC::Lexer<unsigned char> >::parseStatement<JSC::ASTBuilder> + 671
\javascriptcore\local\javascriptcore\parser\parser.cpp(497): 
JSC::Parser<JSC::Lexer<unsigned char> 
>::parseStatementListItem<JSC::ASTBuilder> + 100
\javascriptcore\local\javascriptcore\parser\parser.cpp(379): 
JSC::Parser<JSC::Lexer<unsigned char> >::parseSourceElements<JSC::ASTBuilder> + 
745
\javascriptcore\local\javascriptcore\parser\parser.cpp(1406): 
JSC::Parser<JSC::Lexer<unsigned char> >::parseBlockStatement<JSC::ASTBuilder> + 
741
\javascriptcore\local\javascriptcore\parser\parser.cpp(1433): 
JSC::Parser<JSC::Lexer<unsigned char> >::parseStatement<JSC::ASTBuilder> + 179
\javascriptcore\local\javascriptcore\parser\parser.cpp(497): 
JSC::Parser<JSC::Lexer<unsigned char> 
>::parseStatementListItem<JSC::ASTBuilder> + 100
\javascriptcore\local\javascriptcore\parser\parser.cpp(379): 
JSC::Parser<JSC::Lexer<unsigned char> >::parseSourceElements<JSC::ASTBuilder> + 
171
\javascriptcore\local\javascriptcore\parser\parser.cpp(277): 
JSC::Parser<JSC::Lexer<unsigned char> >::parseInner + 654

To me this likely indicates this is what is leaking, does this bring up any 
ideas for anyone?

Chris

From: Vienneau, Christopher
Sent: Thursday, November 19, 2015 10:25 PM
To: WebKit Development 
<webkit-dev@lists.webkit.org<mailto:webkit-dev@lists.webkit.org>>
Subject: Memory leak tracking in WebKit

Hi,

I'm currently trying to track a leak in our port of WebKit.  If left to soak in 
an automated test, looping over 100 websites, visiting each for 10 seconds, for 
an evening, I'm finding that memory usage goes up to well over a gigabyte 
(eventually crashing).  I know that a lot of things could remain cached but I'm 
calling code very similar to 
MemoryPressureHandler::releaseMemory(Critical::Yes, Synchronous::Yes) before 
checking the memory counters built into our application.  Manually trying to 
reproduce the leak, I find that many pages don't seem to exhibit any 
identifiable increase in memory when; starting from a simple page, clearing the 
cache, visiting the test page, returning to the simple page and finally 
clearing the cache.  I have identified some pages which seem to be causing a 
problem such as cnn.com, when visiting this page it appears I can expect to 
lose 100-500k.

Our current code is based off of 188436:
-Are there any known memory leaks that I should pick up a fix for? (I searched 
but nothing seemed relevant to the current code I have).
-Are there any tools or techniques that can be recommended for identifying a 
leak?  I've been improving our debug features of our memory system, but I've 
been unable to solidly identify where the memory is going.
-I have the WinCairo sample built at the same revision, are there any memory 
tools that can be used with it to identify if the leak exists there too?

Thanks for any suggestions

Chris Vienneau
/*
* Copyright (C) 2015 Apple Inc.  All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
* 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 "WebKitMessageLoop.h"

#include "WebKitDLL.h"

#if USE(GLIB)
#include <glib.h>
#endif

WebKitMessageLoop::WebKitMessageLoop()
    : m_refCount(0)
{
    gClassCount++;
    gClassNameCount().add("WebKitMessageLoop");
}

WebKitMessageLoop::~WebKitMessageLoop()
{
    gClassCount--;
    gClassNameCount().remove("WebKitMessageLoop");
}

WebKitMessageLoop* WebKitMessageLoop::createInstance()
{
    WebKitMessageLoop* instance = new WebKitMessageLoop();
    instance->AddRef();
    return instance;
}

HRESULT WebKitMessageLoop::QueryInterface(REFIID riid, void** ppvObject)
{
    *ppvObject = 0;
    if (IsEqualGUID(riid, IID_IUnknown))
        *ppvObject = static_cast<IWebKitMessageLoop*>(this);
    else if (IsEqualGUID(riid, CLSID_WebKitMessageLoop))
        *ppvObject = static_cast<WebKitMessageLoop*>(this);
    else if (IsEqualGUID(riid, IID_IWebKitMessageLoop))
        *ppvObject = static_cast<IWebKitMessageLoop*>(this);
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

ULONG WebKitMessageLoop::AddRef()
{
    return ++m_refCount;
}

ULONG WebKitMessageLoop::Release()
{
    ULONG newRef = --m_refCount;
    if (!newRef)
        delete(this);

    return newRef;
}

HRESULT WebKitMessageLoop::run(HACCEL hAccelTable)
{
    MSG msg = { 0 };

    while (GetMessage(&msg, 0, 0, 0)) {
        performMessageLoopTasks();

        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return S_OK;
}

HRESULT WebKitMessageLoop::performMessageLoopTasks()
{
#if USE(CF)
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
#endif
#if USE(GLIB)
    g_main_context_iteration(0, false);
#endif

        //sneak my own message for our soak code to do what it wants 
periodically
        static DWORD lastTime = 0;
        const UINT messageId = WM_USER + 0xEA;

        if (GetCurrentTime() > (lastTime + 100))        // don't spam it too 
much
        {
                lastTime = GetCurrentTime();
                HWND windowHandle = FindWindow(NULL, TEXT("WinLauncher"));
                PostMessage(windowHandle, messageId, 0, GetCurrentTime());
        }

    return S_OK;
}

/*
 * Copyright (C) 2006, 2008, 2013-2015 Apple Inc.  All rights reserved.
 * Copyright (C) 2009, 2011 Brent Fulgham.  All rights reserved.
 * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
 * Copyright (C) 2013 Alex Christensen. All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
 * 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 "AccessibilityDelegate.h"
#include "DOMDefaultImpl.h"
#include "PrintWebUIDelegate.h"
#include "ResourceLoadDelegate.h"
#include "WebDownloadDelegate.h"
#include "WinLauncher.h"
#include "WinLauncherReplace.h"
#include <WebKit/WebKitCOMAPI.h>
#include <wtf/ExportMacros.h>
#include <wtf/Platform.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>

#if USE(CF)
#include <CoreFoundation/CFRunLoop.h>
#include <WebKit/CFDictionaryPropertyBag.h>
#endif

#include <cassert>
#include <comip.h>
#include <commctrl.h>
#include <commdlg.h>
#include <comutil.h>
#include <dbghelp.h>
#include <memory>
#include <objbase.h>
#include <shellapi.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <string>
#include <vector>
#include <wininet.h>

#define MAX_LOADSTRING 100
#define URLBAR_HEIGHT  24
#define CONTROLBUTTON_WIDTH 24

static const int maxHistorySize = 10;

#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0
#endif

typedef _com_ptr_t<_com_IIID<IWebFrame, &__uuidof(IWebFrame)>> IWebFramePtr;
typedef _com_ptr_t<_com_IIID<IWebMutableURLRequest, 
&__uuidof(IWebMutableURLRequest)>> IWebMutableURLRequestPtr;

// Global Variables:
HINSTANCE hInst;
HWND hMainWnd;
HWND hURLBarWnd;
HGDIOBJ hURLFont;
HWND hBackButtonWnd;
HWND hForwardButtonWnd;
HWND hCacheWnd;
WNDPROC DefEditProc = nullptr;
WNDPROC DefButtonProc = nullptr;
WNDPROC DefWebKitProc = nullptr;
HWND gViewWindow = 0;
WinLauncher* gWinLauncher = nullptr;
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

// Support moving the transparent window
POINT s_windowPosition = { 100, 100 };
SIZE s_windowSize = { 800, 400 };

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK CustomUserAgent(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK EditProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK BackButtonProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ForwardButtonProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ReloadButtonProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK Caches(HWND, UINT, WPARAM, LPARAM);

static void loadURL(BSTR urlBStr);
static void updateStatistics(HWND hDlg);

namespace WebCore {
float deviceScaleFactorForWindow(HWND);
}

static void resizeSubViews()
{
    if (gWinLauncher->usesLayeredWebView() || !gViewWindow)
        return;

    float scaleFactor = WebCore::deviceScaleFactorForWindow(gViewWindow);

    RECT rcClient;
    GetClientRect(hMainWnd, &rcClient);

    int height = scaleFactor * URLBAR_HEIGHT;
    int width = scaleFactor * CONTROLBUTTON_WIDTH;

    MoveWindow(hBackButtonWnd, 0, 0, width, height, TRUE);
    MoveWindow(hForwardButtonWnd, width, 0, width, height, TRUE);
    MoveWindow(hURLBarWnd, width * 2, 0, rcClient.right, height, TRUE);
    MoveWindow(gViewWindow, 0, height, rcClient.right, rcClient.bottom - 
height, TRUE);

    ::SendMessage(hURLBarWnd, static_cast<UINT>(WM_SETFONT), 
reinterpret_cast<WPARAM>(gWinLauncher->urlBarFont()), TRUE);
}

static void subclassForLayeredWindow()
{
    hMainWnd = gViewWindow;
#if defined _M_AMD64 || defined _WIN64
    DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hMainWnd, 
GWLP_WNDPROC));
    ::SetWindowLongPtr(hMainWnd, GWLP_WNDPROC, 
reinterpret_cast<LONG_PTR>(WndProc));
#else
    DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLong(hMainWnd, 
GWL_WNDPROC));
    ::SetWindowLong(hMainWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc));
#endif
}

static void computeFullDesktopFrame()
{
    RECT desktop;
    if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, 
static_cast<void*>(&desktop), 0))
        return;

    float scaleFactor = WebCore::deviceScaleFactorForWindow(nullptr);

    s_windowPosition.x = 0;
    s_windowPosition.y = 0;
    s_windowSize.cx = scaleFactor * (desktop.right - desktop.left);
    s_windowSize.cy = scaleFactor * (desktop.bottom - desktop.top);
}

BOOL WINAPI DllMain(HINSTANCE dllInstance, DWORD reason, LPVOID)
{
    if (reason == DLL_PROCESS_ATTACH) {
#if defined(_M_X64) || defined(__x86_64__)
        // The VS2013 runtime has a bug where it mis-detects AVX-capable 
processors
        // if the feature has been disabled in firmware. This causes us to crash
        // in some of the math functions. For now, we disable those 
optimizations
        // because Microsoft is not going to fix the problem in VS2013.
        // FIXME: http://webkit.org/b/141449: Remove this workaround when we 
switch to VS2015+.
        _set_FMA3_enable(0);
#endif
        hInst = dllInstance;
    }

    return TRUE;
}

static bool getAppDataFolder(_bstr_t& directory)
{
    wchar_t appDataDirectory[MAX_PATH];
    if (FAILED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, 0, 
0, appDataDirectory)))
        return false;

    wchar_t executablePath[MAX_PATH];
    if (!::GetModuleFileNameW(0, executablePath, MAX_PATH))
        return false;

    ::PathRemoveExtensionW(executablePath);

    directory = _bstr_t(appDataDirectory) + L"\\" + 
::PathFindFileNameW(executablePath);

    return true;
}

static bool setCacheFolder()
{
    IWebCachePtr webCache = gWinLauncher->webCache();
    if (!webCache)
        return false;

    _bstr_t appDataFolder;
    if (!getAppDataFolder(appDataFolder))
        return false;

    appDataFolder += L"\\cache";
    webCache->setCacheFolder(appDataFolder);

    return true;
}

void createCrashReport(EXCEPTION_POINTERS* exceptionPointers)
{
    _bstr_t directory;

    if (!getAppDataFolder(directory))
        return;

    if (::SHCreateDirectoryEx(0, directory, 0) != ERROR_SUCCESS
        && ::GetLastError() != ERROR_FILE_EXISTS
        && ::GetLastError() != ERROR_ALREADY_EXISTS)
        return;

    std::wstring fileName = directory + L"\\CrashReport.dmp";
    HANDLE miniDumpFile = ::CreateFile(fileName.c_str(), GENERIC_WRITE, 0, 0, 
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

    if (miniDumpFile && miniDumpFile != INVALID_HANDLE_VALUE) {

        MINIDUMP_EXCEPTION_INFORMATION mdei;
        mdei.ThreadId = ::GetCurrentThreadId();
        mdei.ExceptionPointers  = exceptionPointers;
        mdei.ClientPointers = 0;

#ifdef _DEBUG
        MINIDUMP_TYPE dumpType = MiniDumpWithFullMemory;
#else
        MINIDUMP_TYPE dumpType = MiniDumpNormal;
#endif

        ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), 
miniDumpFile, dumpType, &mdei, 0, 0);
        ::CloseHandle(miniDumpFile);
        processCrashReport(fileName.c_str());
    }
}

static BOOL CALLBACK AbortProc(HDC hDC, int Error)
{
    MSG msg;
    while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    return TRUE;
}

static HDC getPrinterDC()
{
    PRINTDLG pdlg;
    memset(&pdlg, 0, sizeof(PRINTDLG));
    pdlg.lStructSize = sizeof(PRINTDLG);
    pdlg.Flags = PD_PRINTSETUP | PD_RETURNDC;

    ::PrintDlg(&pdlg);

    return pdlg.hDC;
}

static void initDocStruct(DOCINFO* di, TCHAR* docname)
{
    memset(di, 0, sizeof(DOCINFO));
    di->cbSize = sizeof(DOCINFO);
    di->lpszDocName = docname;
}

typedef _com_ptr_t<_com_IIID<IWebFramePrivate, &__uuidof(IWebFramePrivate)>> 
IWebFramePrivatePtr;

void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC printDC = getPrinterDC();
    if (!printDC) {
        ::MessageBoxW(0, L"Error creating printing DC", L"Error", MB_APPLMODAL 
| MB_OK);
        return;
    }

    if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) {
        ::MessageBoxW(0, L"Error setting up AbortProc", L"Error", MB_APPLMODAL 
| MB_OK);
        return;
    }

    IWebFramePtr frame = gWinLauncher->mainFrame();
    if (!frame)
        return;

    IWebFramePrivatePtr framePrivate;
    if (FAILED(frame->QueryInterface(&framePrivate.GetInterfacePtr())))
        return;

    framePrivate->setInPrintingMode(TRUE, printDC);

    UINT pageCount = 0;
    framePrivate->getPrintedPageCount(printDC, &pageCount);

    DOCINFO di;
    initDocStruct(&di, L"WebKit Doc");
    ::StartDoc(printDC, &di);

    // FIXME: Need CoreGraphics implementation
    void* graphicsContext = 0;
    for (size_t page = 1; page <= pageCount; ++page) {
        ::StartPage(printDC);
        framePrivate->spoolPages(printDC, page, page, graphicsContext);
        ::EndPage(printDC);
    }

    framePrivate->setInPrintingMode(FALSE, printDC);

    ::EndDoc(printDC);
    ::DeleteDC(printDC);
}

static void ToggleMenuFlag(HWND hWnd, UINT menuID)
{
    HMENU menu = ::GetMenu(hWnd);

    MENUITEMINFO info;
    ::memset(&info, 0x00, sizeof(info));
    info.cbSize = sizeof(info);
    info.fMask = MIIM_STATE;

    if (!::GetMenuItemInfo(menu, menuID, FALSE, &info))
        return;

    BOOL newState = !(info.fState & MFS_CHECKED);
    info.fState = (newState) ? MFS_CHECKED : MFS_UNCHECKED;

    ::SetMenuItemInfo(menu, menuID, FALSE, &info);
}

static bool menuItemIsChecked(const MENUITEMINFO& info)
{
    return info.fState & MFS_CHECKED;
}

static void turnOffOtherUserAgents(HMENU menu)
{
    MENUITEMINFO info;
    ::memset(&info, 0x00, sizeof(info));
    info.cbSize = sizeof(info);
    info.fMask = MIIM_STATE;

    // Must unset the other menu items:
    for (UINT menuToClear = IDM_UA_DEFAULT; menuToClear <= IDM_UA_OTHER; 
++menuToClear) {
        if (!::GetMenuItemInfo(menu, menuToClear, FALSE, &info))
            continue;
        if (!menuItemIsChecked(info))
            continue;

        info.fState = MFS_UNCHECKED;
        ::SetMenuItemInfo(menu, menuToClear, FALSE, &info);
    }
}

static void ToggleMenuItem(HWND hWnd, UINT menuID)
{
    HMENU menu = ::GetMenu(hWnd);

    MENUITEMINFO info;
    ::memset(&info, 0x00, sizeof(info));
    info.cbSize = sizeof(info);
    info.fMask = MIIM_STATE;

    if (!::GetMenuItemInfo(menu, menuID, FALSE, &info))
        return;

    BOOL newState = !menuItemIsChecked(info);

    if (!gWinLauncher->standardPreferences() || 
!gWinLauncher->privatePreferences())
        return;

    switch (menuID) {
    case IDM_AVFOUNDATION:
        gWinLauncher->standardPreferences()->setAVFoundationEnabled(newState);
        break;
    case IDM_ACC_COMPOSITING:
        
gWinLauncher->privatePreferences()->setAcceleratedCompositingEnabled(newState);
        break;
    case IDM_WK_FULLSCREEN:
        gWinLauncher->privatePreferences()->setFullScreenEnabled(newState);
        break;
    case IDM_COMPOSITING_BORDERS:
        gWinLauncher->privatePreferences()->setShowDebugBorders(newState);
        gWinLauncher->privatePreferences()->setShowRepaintCounter(newState);
        break;
    case IDM_DISABLE_IMAGES:
        
gWinLauncher->standardPreferences()->setLoadsImagesAutomatically(!newState);
        break;
    case IDM_DISABLE_STYLES:
        
gWinLauncher->privatePreferences()->setAuthorAndUserStylesEnabled(!newState);
        break;
    case IDM_DISABLE_JAVASCRIPT:
        gWinLauncher->standardPreferences()->setJavaScriptEnabled(!newState);
        break;
    case IDM_DISABLE_LOCAL_FILE_RESTRICTIONS:
        
gWinLauncher->privatePreferences()->setAllowUniversalAccessFromFileURLs(newState);
        
gWinLauncher->privatePreferences()->setAllowFileAccessFromFileURLs(newState);
        break;
    case IDM_UA_DEFAULT:
    case IDM_UA_SAFARI_8_0:
    case IDM_UA_SAFARI_IOS_8_IPHONE:
    case IDM_UA_SAFARI_IOS_8_IPAD:
    case IDM_UA_IE_11:
    case IDM_UA_CHROME_MAC:
    case IDM_UA_CHROME_WIN:
    case IDM_UA_FIREFOX_MAC:
    case IDM_UA_FIREFOX_WIN:
        gWinLauncher->setUserAgent(menuID);
        turnOffOtherUserAgents(menu);
        break;
    case IDM_UA_OTHER:
        // The actual user agent string will be set by the custom user agent 
dialog
        turnOffOtherUserAgents(menu);
        break;
    }

    info.fState = (newState) ? MFS_CHECKED : MFS_UNCHECKED;

    ::SetMenuItemInfo(menu, menuID, FALSE, &info);
}

static const int dragBarHeight = 30;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    WNDPROC parentProc = (gWinLauncher) ? (gWinLauncher->usesLayeredWebView() ? 
DefWebKitProc : DefWindowProc) : DefWindowProc;
        const UINT messageID = WM_USER + 0xEA;

    switch (message) {
        case messageID: {
                static UINT lastTime = 0;

                if (lParam > (lastTime + 10000))        //every 10 seconds
                {
                        lastTime = lParam;

                        static UINT loadCount = 0;
                        loadCount++;
                        if ((loadCount %2) == 0)
                        { 
                                loadURL(L"http://answers.ea.com";);
                        }
                        else
                        {
                                loadURL(L"file:///C:/test_links.html");
                        }
                }
                break;
        }
    case WM_NCHITTEST:
        if (gWinLauncher && gWinLauncher->usesLayeredWebView()) {
            RECT window;
            ::GetWindowRect(hWnd, &window);
            // For testing our transparent window, we need a region to use as a 
handle for
            // dragging. The right way to do this would be to query the web 
view to see what's
            // under the mouse. However, for testing purposes we just use an 
arbitrary
            // 30 logical pixel band at the top of the view as an arbitrary 
gripping location.
            //
            // When we are within this bad, return HT_CAPTION to tell Windows 
we want to
            // treat this region as if it were the title bar on a normal window.
            int y = HIWORD(lParam);
            float scaledDragBarHeightFactor = dragBarHeight * 
gWinLauncher->deviceScaleFactor();
            if ((y > window.top) && (y < window.top + 
scaledDragBarHeightFactor))
                return HTCAPTION;
        }
        return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
    case WM_COMMAND: {
        int wmId = LOWORD(wParam);
        int wmEvent = HIWORD(wParam);
        if (wmId >= IDM_HISTORY_LINK0 && wmId <= IDM_HISTORY_LINK9) {
            if (gWinLauncher)
                gWinLauncher->navigateToHistory(hWnd, wmId);
            break;
        }
        // Parse the menu selections:
        switch (wmId) {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        case IDM_PRINT:
            PrintView(hWnd, message, wParam, lParam);
            break;
        case IDM_WEB_INSPECTOR:
            if (gWinLauncher)
                gWinLauncher->launchInspector();
            break;
        case IDM_CACHES:
            if (!::IsWindow(hCacheWnd)) {
                hCacheWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_CACHES), 
hWnd, Caches);
                ::ShowWindow(hCacheWnd, SW_SHOW);
            }
            break;
        case IDM_HISTORY_BACKWARD:
        case IDM_HISTORY_FORWARD:
            if (gWinLauncher)
                gWinLauncher->navigateForwardOrBackward(hWnd, wmId);
            break;
        case IDM_AVFOUNDATION:
        case IDM_ACC_COMPOSITING:
        case IDM_WK_FULLSCREEN:
        case IDM_COMPOSITING_BORDERS:
        case IDM_DISABLE_IMAGES:
        case IDM_DISABLE_STYLES:
        case IDM_DISABLE_JAVASCRIPT:
        case IDM_DISABLE_LOCAL_FILE_RESTRICTIONS:
        case IDM_UA_DEFAULT:
        case IDM_UA_SAFARI_8_0:
        case IDM_UA_SAFARI_IOS_8_IPHONE:
        case IDM_UA_SAFARI_IOS_8_IPAD:
        case IDM_UA_IE_11:
        case IDM_UA_CHROME_MAC:
        case IDM_UA_CHROME_WIN:
        case IDM_UA_FIREFOX_MAC:
        case IDM_UA_FIREFOX_WIN:
            ToggleMenuItem(hWnd, wmId);
            break;
        case IDM_UA_OTHER:
            if (wmEvent)
                ToggleMenuItem(hWnd, wmId);
            else
                DialogBox(hInst, MAKEINTRESOURCE(IDD_USER_AGENT), hWnd, 
CustomUserAgent);
            break;
        case IDM_ACTUAL_SIZE:
            if (gWinLauncher)
                gWinLauncher->resetZoom();
            break;
        case IDM_ZOOM_IN:
            if (gWinLauncher)
                gWinLauncher->zoomIn();
            break;
        case IDM_ZOOM_OUT:
            if (gWinLauncher)
                gWinLauncher->zoomOut();
            break;
        default:
            return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
        }
        }
        break;
    case WM_DESTROY:
#if USE(CF)
        CFRunLoopStop(CFRunLoopGetMain());
#endif
        PostQuitMessage(0);
        break;
    case WM_SIZE:
        if (!gWinLauncher || !gWinLauncher->hasWebView() || 
gWinLauncher->usesLayeredWebView())
            return CallWindowProc(parentProc, hWnd, message, wParam, lParam);

        resizeSubViews();
        break;
    case WM_DPICHANGED:
        if (gWinLauncher)
            gWinLauncher->updateDeviceScaleFactor();
        return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
    default:
        return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
    }

    return 0;
}

LRESULT CALLBACK EditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
    case WM_CHAR:
        if (wParam == 13) { // Enter Key
            wchar_t strPtr[INTERNET_MAX_URL_LENGTH];
            *((LPWORD)strPtr) = INTERNET_MAX_URL_LENGTH; 
            int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr);

            strPtr[strLen] = 0;
            _bstr_t bstr(strPtr);
            loadURL(bstr.GetBSTR());

            return 0;
        } 
    default:
        return CallWindowProc(DefEditProc, hDlg, message, wParam, lParam);
    }
}

LRESULT CALLBACK BackButtonProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM 
lParam)
{
    switch (message) {
    case WM_LBUTTONUP:
        gWinLauncher->goBack();
    default:
        return CallWindowProc(DefButtonProc, hDlg, message, wParam, lParam);
    }
}

LRESULT CALLBACK ForwardButtonProc(HWND hDlg, UINT message, WPARAM wParam, 
LPARAM lParam)
{
    switch (message) {
    case WM_LBUTTONUP:
        gWinLauncher->goForward();
    default:
        return CallWindowProc(DefButtonProc, hDlg, message, wParam, lParam);
    }
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message) {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

INT_PTR CALLBACK Caches(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message) {
    case WM_INITDIALOG:
        ::SetTimer(hDlg, IDT_UPDATE_STATS, 1000, nullptr);
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
            ::KillTimer(hDlg, IDT_UPDATE_STATS);
            ::DestroyWindow(hDlg);
            hCacheWnd = 0;
            return (INT_PTR)TRUE;
        }
        break;

    case IDT_UPDATE_STATS:
        ::InvalidateRect(hDlg, nullptr, FALSE);
        return (INT_PTR)TRUE;

    case WM_PAINT:
        updateStatistics(hDlg);
        break;
    }

    return (INT_PTR)FALSE;
}

INT_PTR CALLBACK CustomUserAgent(HWND hDlg, UINT message, WPARAM wParam, LPARAM 
lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message) {
    case WM_INITDIALOG: {
        HWND edit = ::GetDlgItem(hDlg, IDC_USER_AGENT_INPUT);
        _bstr_t userAgent;
        if (gWinLauncher)
            userAgent = gWinLauncher->userAgent();

        ::SetWindowText(edit, static_cast<LPCTSTR>(userAgent));
        return (INT_PTR)TRUE;
    }

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK) {
            HWND edit = ::GetDlgItem(hDlg, IDC_USER_AGENT_INPUT);

            TCHAR buffer[1024];
            int strLen = ::GetWindowText(edit, buffer, 1024);
            buffer[strLen] = 0;

            _bstr_t bstr(buffer);
            if (bstr.length()) {
                gWinLauncher->setUserAgent(bstr);
                ::PostMessage(hMainWnd, static_cast<UINT>(WM_COMMAND), 
MAKELPARAM(IDM_UA_OTHER, 1), 0);
            }
        }

        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
            ::EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

static void loadURL(BSTR passedURL)
{
    if (FAILED(gWinLauncher->loadURL(passedURL)))
        return;

    SetFocus(gViewWindow);
}

static void setWindowText(HWND dialog, UINT field, _bstr_t value)
{
    ::SetDlgItemText(dialog, field, value);
}

static void setWindowText(HWND dialog, UINT field, UINT value)
{
    String valueStr = WTF::String::number(value);

    setWindowText(dialog, field, _bstr_t(valueStr.utf8().data()));
}

typedef _com_ptr_t<_com_IIID<IPropertyBag, &__uuidof(IPropertyBag)>> 
IPropertyBagPtr;

static void setWindowText(HWND dialog, UINT field, IPropertyBagPtr statistics, 
const _bstr_t& key)
{
    _variant_t var;
    V_VT(&var) = VT_UI8;
    if (FAILED(statistics->Read(key, &var.GetVARIANT(), nullptr)))
        return;

    unsigned long long value = V_UI8(&var);
    String valueStr = WTF::String::number(value);

    setWindowText(dialog, field, _bstr_t(valueStr.utf8().data()));
}

static void setWindowText(HWND dialog, UINT field, CFDictionaryRef dictionary, 
CFStringRef key, UINT& total)
{
    CFNumberRef countNum = 
static_cast<CFNumberRef>(CFDictionaryGetValue(dictionary, key));
    if (!countNum)
        return;

    int count = 0;
    CFNumberGetValue(countNum, kCFNumberIntType, &count);

    setWindowText(dialog, field, static_cast<UINT>(count));
    total += count;
}

static void updateStatistics(HWND dialog)
{
    if (!gWinLauncher)
        return;

    IWebCoreStatisticsPtr webCoreStatistics = gWinLauncher->statistics();
    if (!webCoreStatistics)
        return;

    IPropertyBagPtr statistics;
    HRESULT hr = 
webCoreStatistics->memoryStatistics(&statistics.GetInterfacePtr());
    if (FAILED(hr))
        return;

    // FastMalloc.
    setWindowText(dialog, IDC_RESERVED_VM, statistics, 
"FastMallocReservedVMBytes");
    setWindowText(dialog, IDC_COMMITTED_VM, statistics, 
"FastMallocCommittedVMBytes");
    setWindowText(dialog, IDC_FREE_LIST_BYTES, statistics, 
"FastMallocFreeListBytes");

    // WebCore Cache.
#if USE(CF)
    IWebCachePtr webCache = gWinLauncher->webCache();

    int dictCount = 6;
    IPropertyBag* cacheDict[6] = { 0 };
    if (FAILED(webCache->statistics(&dictCount, cacheDict)))
        return;

    COMPtr<CFDictionaryPropertyBag> counts, sizes, liveSizes, decodedSizes, 
purgableSizes;
    counts.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[0]));
    sizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[1]));
    
liveSizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[2]));
    
decodedSizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[3]));
    
purgableSizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[4]));

    static CFStringRef imagesKey = CFSTR("images");
    static CFStringRef stylesheetsKey = CFSTR("style sheets");
    static CFStringRef xslKey = CFSTR("xsl");
    static CFStringRef scriptsKey = CFSTR("scripts");

    if (counts) {
        UINT totalObjects = 0;
        setWindowText(dialog, IDC_IMAGES_OBJECT_COUNT, counts->dictionary(), 
imagesKey, totalObjects);
        setWindowText(dialog, IDC_CSS_OBJECT_COUNT, counts->dictionary(), 
stylesheetsKey, totalObjects);
        setWindowText(dialog, IDC_XSL_OBJECT_COUNT, counts->dictionary(), 
xslKey, totalObjects);
        setWindowText(dialog, IDC_JSC_OBJECT_COUNT, counts->dictionary(), 
scriptsKey, totalObjects);
        setWindowText(dialog, IDC_TOTAL_OBJECT_COUNT, totalObjects);
    }

    if (sizes) {
        UINT totalBytes = 0;
        setWindowText(dialog, IDC_IMAGES_BYTES, sizes->dictionary(), imagesKey, 
totalBytes);
        setWindowText(dialog, IDC_CSS_BYTES, sizes->dictionary(), 
stylesheetsKey, totalBytes);
        setWindowText(dialog, IDC_XSL_BYTES, sizes->dictionary(), xslKey, 
totalBytes);
        setWindowText(dialog, IDC_JSC_BYTES, sizes->dictionary(), scriptsKey, 
totalBytes);
        setWindowText(dialog, IDC_TOTAL_BYTES, totalBytes);
    }

    if (liveSizes) {
        UINT totalLiveBytes = 0;
        setWindowText(dialog, IDC_IMAGES_LIVE_COUNT, liveSizes->dictionary(), 
imagesKey, totalLiveBytes);
        setWindowText(dialog, IDC_CSS_LIVE_COUNT, liveSizes->dictionary(), 
stylesheetsKey, totalLiveBytes);
        setWindowText(dialog, IDC_XSL_LIVE_COUNT, liveSizes->dictionary(), 
xslKey, totalLiveBytes);
        setWindowText(dialog, IDC_JSC_LIVE_COUNT, liveSizes->dictionary(), 
scriptsKey, totalLiveBytes);
        setWindowText(dialog, IDC_TOTAL_LIVE_COUNT, totalLiveBytes);
    }

    if (decodedSizes) {
        UINT totalDecoded = 0;
        setWindowText(dialog, IDC_IMAGES_DECODED_COUNT, 
decodedSizes->dictionary(), imagesKey, totalDecoded);
        setWindowText(dialog, IDC_CSS_DECODED_COUNT, 
decodedSizes->dictionary(), stylesheetsKey, totalDecoded);
        setWindowText(dialog, IDC_XSL_DECODED_COUNT, 
decodedSizes->dictionary(), xslKey, totalDecoded);
        setWindowText(dialog, IDC_JSC_DECODED_COUNT, 
decodedSizes->dictionary(), scriptsKey, totalDecoded);
        setWindowText(dialog, IDC_TOTAL_DECODED, totalDecoded);
    }

    if (purgableSizes) {
        UINT totalPurgable = 0;
        setWindowText(dialog, IDC_IMAGES_PURGEABLE_COUNT, 
purgableSizes->dictionary(), imagesKey, totalPurgable);
        setWindowText(dialog, IDC_CSS_PURGEABLE_COUNT, 
purgableSizes->dictionary(), stylesheetsKey, totalPurgable);
        setWindowText(dialog, IDC_XSL_PURGEABLE_COUNT, 
purgableSizes->dictionary(), xslKey, totalPurgable);
        setWindowText(dialog, IDC_JSC_PURGEABLE_COUNT, 
purgableSizes->dictionary(), scriptsKey, totalPurgable);
        setWindowText(dialog, IDC_TOTAL_PURGEABLE, totalPurgable);
    }
#endif

    // JavaScript Heap.
    setWindowText(dialog, IDC_JSC_HEAP_SIZE, statistics, "JavaScriptHeapSize");
    setWindowText(dialog, IDC_JSC_HEAP_FREE, statistics, "JavaScriptFreeSize");

    UINT count;
    if (SUCCEEDED(webCoreStatistics->javaScriptObjectsCount(&count)))
        setWindowText(dialog, IDC_TOTAL_JSC_HEAP_OBJECTS, count);
    if (SUCCEEDED(webCoreStatistics->javaScriptGlobalObjectsCount(&count)))
        setWindowText(dialog, IDC_GLOBAL_JSC_HEAP_OBJECTS, count);
    if (SUCCEEDED(webCoreStatistics->javaScriptProtectedObjectsCount(&count)))
        setWindowText(dialog, IDC_PROTECTED_JSC_HEAP_OBJECTS, count);

    // Font and Glyph Caches.
    if (SUCCEEDED(webCoreStatistics->cachedFontDataCount(&count)))
        setWindowText(dialog, IDC_TOTAL_FONT_OBJECTS, count);
    if (SUCCEEDED(webCoreStatistics->cachedFontDataInactiveCount(&count)))
        setWindowText(dialog, IDC_INACTIVE_FONT_OBJECTS, count);
    if (SUCCEEDED(webCoreStatistics->glyphPageCount(&count)))
        setWindowText(dialog, IDC_GLYPH_PAGES, count);

    // Site Icon Database.
    if (SUCCEEDED(webCoreStatistics->iconPageURLMappingCount(&count)))
        setWindowText(dialog, IDC_PAGE_URL_MAPPINGS, count);
    if (SUCCEEDED(webCoreStatistics->iconRetainedPageURLCount(&count)))
        setWindowText(dialog, IDC_RETAINED_PAGE_URLS, count);
    if (SUCCEEDED(webCoreStatistics->iconRecordCount(&count)))
        setWindowText(dialog, IDC_SITE_ICON_RECORDS, count);
    if (SUCCEEDED(webCoreStatistics->iconsWithDataCount(&count)))
        setWindowText(dialog, IDC_SITE_ICONS_WITH_DATA, count);
}

static void parseCommandLine(bool& usesLayeredWebView, bool& useFullDesktop, 
bool& pageLoadTesting, _bstr_t& requestedURL)
{
    usesLayeredWebView = false;
    useFullDesktop = false;
    pageLoadTesting = false;

    int argc = 0;
    WCHAR** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
    for (int i = 1; i < argc; ++i) {
        if (!wcsicmp(argv[i], L"--transparent"))
            usesLayeredWebView = true;
        else if (!wcsicmp(argv[i], L"--desktop"))
            useFullDesktop = true;
        else if (!requestedURL)
            requestedURL = argv[i];
        else if (!wcsicmp(argv[i], L"--performance"))
            pageLoadTesting = true;
    }
}

extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(HINSTANCE 
hInstance, HINSTANCE hPrevInstance, LPWSTR lpstrCmdLine, int nCmdShow)
{
    return wWinMain(hInstance, hPrevInstance, lpstrCmdLine, nCmdShow);
}
_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-dev

Reply via email to