
/*
 * Copyright (C) 2012 Google, 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 GOOGLE 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 COMPUTER, 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 "core/frame/UseCounter.h"

#include "core/css/CSSStyleSheet.h"
#include "core/css/StyleSheetContents.h"
#include "core/dom/Document.h"
#include "core/dom/ExecutionContext.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/FrameHost.h"
#include "core/frame/LocalFrame.h"
#include "core/inspector/ConsoleMessage.h"
#include "public/platform/Platform.h"

namespace blink {

int UseCounter::m_muteCount = 0;

void UseCounter::muteForInspector()
{
    UseCounter::m_muteCount++;
}

void UseCounter::unmuteForInspector()
{
    UseCounter::m_muteCount--;
}

UseCounter::UseCounter()
{
    m_CSSFeatureBits.ensureSize(lastCSSProperty + 1);
    m_CSSFeatureBits.clearAll();
}

UseCounter::~UseCounter()
{
    // We always log PageDestruction so that we have a scale for the rest of the features.
    blink::Platform::current()->histogramEnumeration("WebCore.FeatureObserver", PageDestruction, NumberOfFeatures);

    updateMeasurements();
}

void UseCounter::updateMeasurements()
{
    blink::Platform::current()->histogramEnumeration("WebCore.FeatureObserver", PageVisits, NumberOfFeatures);

    if (m_countBits) {
        for (unsigned i = 0; i < NumberOfFeatures; ++i) {
            if (m_countBits->quickGet(i))
                blink::Platform::current()->histogramEnumeration("WebCore.FeatureObserver", i, NumberOfFeatures);
        }
        // Clearing count bits is timing sensitive.
        m_countBits->clearAll();
    }

    m_CSSFeatureBits.clearAll();
}

void UseCounter::didCommitLoad()
{
    updateMeasurements();
}

void UseCounter::count(const Document& document, Feature feature)
{
    FrameHost* host = document.frameHost();
    if (!host)
        return;

    ASSERT(host->useCounter().deprecationMessage(feature).isEmpty());
    host->useCounter().recordMeasurement(feature);
}

void UseCounter::count(const ExecutionContext* context, Feature feature)
{
    if (!context)
        return;
    count(*toDocument(context), feature);
}

void UseCounter::countDeprecation(ExecutionContext* context, Feature feature)
{
    if (!context)
        return;
    UseCounter::countDeprecation(*toDocument(context), feature);
}

void UseCounter::countDeprecation(const LocalDOMWindow* window, Feature feature)
{
    if (!window || !window->document())
        return;
    UseCounter::countDeprecation(*window->document(), feature);
}

void UseCounter::countDeprecation(const Document& document, Feature feature)
{
    FrameHost* host = document.frameHost();
    LocalFrame* frame = document.frame();
    if (!host || !frame)
        return;

    if (host->useCounter().recordMeasurement(feature)) {
        ASSERT(!host->useCounter().deprecationMessage(feature).isEmpty());
        frame->console().addMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, host->useCounter().deprecationMessage(feature)));
    }
}

// FIXME: Update other UseCounter::deprecationMessage() cases to use this.
static String replacedBy(const char* oldString, const char* newString)
{
    return String::format("'%s' is deprecated. Please use '%s' instead.", oldString, newString);
}

String UseCounter::deprecationMessage(Feature feature)
{
    switch (feature) {
    // Quota
    case PrefixedStorageInfo:
        return "'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.";

    // Keyboard Event (DOM Level 3)
    case KeyboardEventKeyLocation:
        return replacedBy("KeyboardEvent.keyLocation", "KeyboardEvent.location");

    case ConsoleMarkTimeline:
        return "console.markTimeline is deprecated. Please use the console.timeStamp instead.";

    case FileError:
        return "FileError is deprecated. Please use the 'name' or 'message' attributes of DOMError rather than 'code'.";

    case CSSStyleSheetInsertRuleOptionalArg:
        return "Calling CSSStyleSheet.insertRule() with one argument is deprecated. Please pass the index argument as well: insertRule(x, 0).";

    case PrefixedVideoSupportsFullscreen:
        return "'HTMLVideoElement.webkitSupportsFullscreen' is deprecated. Its value is true if the video is loaded.";

    case PrefixedVideoDisplayingFullscreen:
        return "'HTMLVideoElement.webkitDisplayingFullscreen' is deprecated. Please use the 'fullscreenchange' and 'webkitfullscreenchange' events instead.";

    case PrefixedVideoEnterFullscreen:
        return "'HTMLVideoElement.webkitEnterFullscreen()' is deprecated. Please use 'Element.requestFullscreen()' and 'Element.webkitRequestFullscreen()' instead.";

    case PrefixedVideoExitFullscreen:
        return "'HTMLVideoElement.webkitExitFullscreen()' is deprecated. Please use 'Document.exitFullscreen()' and 'Document.webkitExitFullscreen()' instead.";

    case PrefixedVideoEnterFullScreen:
        return "'HTMLVideoElement.webkitEnterFullScreen()' is deprecated. Please use 'Element.requestFullscreen()' and 'Element.webkitRequestFullscreen()' instead.";

    case PrefixedVideoExitFullScreen:
        return "'HTMLVideoElement.webkitExitFullScreen()' is deprecated. Please use 'Document.exitFullscreen()' and 'Document.webkitExitFullscreen()' instead.";

    case MediaErrorEncrypted:
        return "'MediaError.MEDIA_ERR_ENCRYPTED' is deprecated. This error code is never used.";

    case PrefixedIndexedDB:
        return replacedBy("webkitIndexedDB", "indexedDB");

    case PrefixedIDBCursorConstructor:
        return replacedBy("webkitIDBCursor", "IDBCursor");

    case PrefixedIDBDatabaseConstructor:
        return replacedBy("webkitIDBDatabase", "IDBDatabase");

    case PrefixedIDBFactoryConstructor:
        return replacedBy("webkitIDBFactory", "IDBFactory");

    case PrefixedIDBIndexConstructor:
        return replacedBy("webkitIDBIndex", "IDBIndex");

    case PrefixedIDBKeyRangeConstructor:
        return replacedBy("webkitIDBKeyRange", "IDBKeyRange");

    case PrefixedIDBObjectStoreConstructor:
        return replacedBy("webkitIDBObjectStore", "IDBObjectStore");

    case PrefixedIDBRequestConstructor:
        return replacedBy("webkitIDBRequest", "IDBRequest");

    case PrefixedIDBTransactionConstructor:
        return replacedBy("webkitIDBTransaction", "IDBTransaction");

    case PrefixedRequestAnimationFrame:
        return "'webkitRequestAnimationFrame' is vendor-specific. Please use the standard 'requestAnimationFrame' instead.";

    case PrefixedCancelAnimationFrame:
        return "'webkitCancelAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead.";

    case PrefixedCancelRequestAnimationFrame:
        return "'webkitCancelRequestAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead.";

    case DocumentCreateAttributeNS:
        return "'Document.createAttributeNS' is deprecated and has been removed from DOM4 (http://w3.org/tr/dom).";

    case AttributeOwnerElement:
        return "'Attr.ownerElement' is deprecated and has been removed from DOM4 (http://w3.org/tr/dom).";

    case AttrNodeValue:
        return replacedBy("Attr.nodeValue", "value");

    case AttrTextContent:
        return replacedBy("Attr.textContent", "value");

    case RangeDetach:
        return "'Range.detach' is now a no-op, as per DOM (http://dom.spec.whatwg.org/#dom-range-detach).";

    case OverflowChangedEvent:
        return "The 'overflowchanged' event is deprecated and may be removed. Please do not use it.";

    case HTMLHeadElementProfile:
        return "'HTMLHeadElement.profile' is deprecated. The reflected attribute has no effect.";

    case ElementSetPrefix:
        return "Setting 'Element.prefix' is deprecated, as it is read-only per DOM (http://dom.spec.whatwg.org/#element).";

    case OpenWebDatabaseInWorker:
        return "'openDatabase' in Workers is deprecated. Please switch to Indexed Database API.";

    case OpenWebDatabaseSyncInWorker:
        return "'openDatabaseSync' is deprecated. Please switch to Indexed Database API.";

    case WebSocketURL:
        return "'WebSocket.URL' is deprecated. Please use 'WebSocket.url' instead.";

    case PictureSourceSrc:
        return "<source src> with a <picture> parent is invalid and therefore ignored. Please use <source srcset> instead.";

    // Features that aren't deprecated don't have a deprecation message.
    default:
        return String();
    }
}

void UseCounter::count(CSSParserContext context, CSSPropertyID feature)
{
    ASSERT(feature >= firstCSSProperty);
    ASSERT(feature <= lastCSSProperty);
    ASSERT(!isInternalProperty(feature));

    m_CSSFeatureBits.quickSet(feature);
}

void UseCounter::count(Feature feature)
{
    ASSERT(deprecationMessage(feature).isEmpty());
    recordMeasurement(feature);
}

UseCounter* UseCounter::getFrom(const Document* document)
{
    if (document && document->frameHost())
        return &document->frameHost()->useCounter();
    return 0;
}

UseCounter* UseCounter::getFrom(const CSSStyleSheet* sheet)
{
    if (sheet)
        return getFrom(sheet->contents());
    return 0;
}

UseCounter* UseCounter::getFrom(const StyleSheetContents* sheetContents)
{
    // FIXME: We may want to handle stylesheets that have multiple owners
    //        http://crbug.com/242125
    if (sheetContents && sheetContents->hasSingleOwnerNode())
        return getFrom(sheetContents->singleOwnerDocument());
    return 0;
}

} // namespace blink
