<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists for the convenience
// of other Qt classes.  This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//

#include <windows.h>
#include <mmsystem.h>
#include "qaudiodeviceinfo_win32_p.h"
#include <dshow.h>

#if defined(Q_CC_MINGW)

extern GUID CLSID_AudioInputDeviceCategory;

#ifndef __IErrorLog_INTERFACE_DEFINED__
#define __IErrorLog_INTERFACE_DEFINED__

DECLARE_INTERFACE_(IErrorLog, IUnknown)
{
    STDMETHOD(AddError)(THIS_ LPCOLESTR, EXCEPINFO *) PURE;
};

#endif /* __IErrorLog_INTERFACE_DEFINED__ */

#ifndef __IPropertyBag_INTERFACE_DEFINED__
#define __IPropertyBag_INTERFACE_DEFINED__

const GUID IID_IPropertyBag = {0x55272A00, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};

DECLARE_INTERFACE_(IPropertyBag, IUnknown)
{
    STDMETHOD(Read)(THIS_ LPCOLESTR, VARIANT *, IErrorLog *) PURE;
    STDMETHOD(Write)(THIS_ LPCOLESTR, VARIANT *) PURE;
};

#endif /* __IPropertyBag_INTERFACE_DEFINED__ */

#endif//Q_CC_MINGW

QT_BEGIN_NAMESPACE

// For mingw toolchain mmsystem.h only defines half the defines, so add if needed.
#ifndef WAVE_FORMAT_44M08
#define WAVE_FORMAT_44M08 0x00000100
#define WAVE_FORMAT_44S08 0x00000200
#define WAVE_FORMAT_44M16 0x00000400
#define WAVE_FORMAT_44S16 0x00000800
#define WAVE_FORMAT_48M08 0x00001000
#define WAVE_FORMAT_48S08 0x00002000
#define WAVE_FORMAT_48M16 0x00004000
#define WAVE_FORMAT_48S16 0x00008000
#define WAVE_FORMAT_96M08 0x00010000
#define WAVE_FORMAT_96S08 0x00020000
#define WAVE_FORMAT_96M16 0x00040000
#define WAVE_FORMAT_96S16 0x00080000
#endif

QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray dev, QAudio::Mode mode)
{
    QDataStream ds(&dev, QIODevice::ReadOnly);
    ds >> devId >> device;
    this->mode = mode;

    updateLists();
}

QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal()
{
    close();
}

bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
{
    return testSettings(format);
}

QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
    QAudioFormat nearest;
    if(mode == QAudio::AudioOutput) {
        nearest.setFrequency(44100);
        nearest.setChannelCount(2);
        nearest.setByteOrder(QAudioFormat::LittleEndian);
        nearest.setSampleType(QAudioFormat::SignedInt);
        nearest.setSampleSize(16);
        nearest.setCodec(QLatin1String("audio/pcm"));
    } else {
        nearest.setFrequency(11025);
        nearest.setChannelCount(1);
        nearest.setByteOrder(QAudioFormat::LittleEndian);
        nearest.setSampleType(QAudioFormat::SignedInt);
        nearest.setSampleSize(8);
        nearest.setCodec(QLatin1String("audio/pcm"));
    }
    return nearest;
}

QString QAudioDeviceInfoInternal::deviceName() const
{
    return device;
}

QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
    updateLists();
    return codecz;
}

QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
    updateLists();
    return freqz;
}

QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
    updateLists();
    return channelz;
}

QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
    updateLists();
    return sizez;
}

QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
    updateLists();
    return byteOrderz;
}

QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
    updateLists();
    return typez;
}

bool QAudioDeviceInfoInternal::open()
{
    return true;
}

void QAudioDeviceInfoInternal::close()
{
}

bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
{
    // Set nearest to closest settings that do work.
    // See if what is in settings will work (return value).

    bool failed = false;
    bool match = false;

    // check codec
    for( int i = 0; i < codecz.count(); i++) {
        if (format.codec() == codecz.at(i))
            match = true;
    }
    if (!match) failed = true;

    // check channel
    match = false;
    if (!failed) {
        for( int i = 0; i < channelz.count(); i++) {
            if (format.channels() == channelz.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check frequency
    match = false;
    if (!failed) {
        for( int i = 0; i < freqz.count(); i++) {
            if (format.frequency() == freqz.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check sample size
    match = false;
    if (!failed) {
        for( int i = 0; i < sizez.count(); i++) {
            if (format.sampleSize() == sizez.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check byte order
    match = false;
    if (!failed) {
        for( int i = 0; i < byteOrderz.count(); i++) {
            if (format.byteOrder() == byteOrderz.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check sample type
    match = false;
    if (!failed) {
        for( int i = 0; i < typez.count(); i++) {
            if (format.sampleType() == typez.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    if(!failed) {
        // settings work
        return true;
    }
    return false;
}

void QAudioDeviceInfoInternal::updateLists()
{
    // redo all lists based on current settings
    bool match = false;
    DWORD fmt = NULL;

    if(mode == QAudio::AudioOutput) {
        WAVEOUTCAPS woc;
        if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) {
            match = true;
            fmt = woc.dwFormats;
        }
    } else {
        WAVEINCAPS woc;
        if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) {
            match = true;
            fmt = woc.dwFormats;
        }
    }
    sizez.clear();
    freqz.clear();
    channelz.clear();
    byteOrderz.clear();
    typez.clear();
    codecz.clear();

    if(match) {
        if((fmt && WAVE_FORMAT_1M08)
           || (fmt && WAVE_FORMAT_1S08)
	   || (fmt && WAVE_FORMAT_2M08)
	   || (fmt && WAVE_FORMAT_2S08)
	   || (fmt && WAVE_FORMAT_4M08)
	   || (fmt && WAVE_FORMAT_4S08)
#ifndef Q_OS_WINCE
	   || (fmt && WAVE_FORMAT_48M08)
	   || (fmt && WAVE_FORMAT_48S08)
	   || (fmt && WAVE_FORMAT_96M08)
	   || (fmt && WAVE_FORMAT_96S08)
#endif
       ) {
            sizez.append(8);
	}
        if((fmt && WAVE_FORMAT_1M16)
           || (fmt && WAVE_FORMAT_1S16)
	   || (fmt && WAVE_FORMAT_2M16)
	   || (fmt && WAVE_FORMAT_2S16)
	   || (fmt && WAVE_FORMAT_4M16)
	   || (fmt && WAVE_FORMAT_4S16)
#ifndef Q_OS_WINCE
	   || (fmt && WAVE_FORMAT_48M16)
	   || (fmt && WAVE_FORMAT_48S16)
	   || (fmt && WAVE_FORMAT_96M16)
	   || (fmt && WAVE_FORMAT_96S16)
#endif
       ) {
            sizez.append(16);
	}
        if((fmt && WAVE_FORMAT_1M08)
           || (fmt && WAVE_FORMAT_1S08)
	   || (fmt && WAVE_FORMAT_1M16)
	   || (fmt && WAVE_FORMAT_1S16)) {
            freqz.append(11025);
	}
        if((fmt && WAVE_FORMAT_2M08)
           || (fmt && WAVE_FORMAT_2S08)
	   || (fmt && WAVE_FORMAT_2M16)
	   || (fmt && WAVE_FORMAT_2S16)) {
            freqz.append(22050);
	}
        if((fmt && WAVE_FORMAT_4M08)
           || (fmt && WAVE_FORMAT_4S08)
	   || (fmt && WAVE_FORMAT_4M16)
	   || (fmt && WAVE_FORMAT_4S16)) {
            freqz.append(44100);
	}
#ifndef Q_OS_WINCE
        if((fmt && WAVE_FORMAT_48M08)
           || (fmt && WAVE_FORMAT_48S08)
	   || (fmt && WAVE_FORMAT_48M16)
	   || (fmt && WAVE_FORMAT_48S16)) {
            freqz.append(48000);
	}
        if((fmt && WAVE_FORMAT_96M08)
           || (fmt && WAVE_FORMAT_96S08)
	   || (fmt && WAVE_FORMAT_96M16)
	   || (fmt && WAVE_FORMAT_96S16)) {
            freqz.append(96000);
        }
#endif
	channelz.append(1);
	channelz.append(2);
        if (mode == QAudio::AudioOutput) {
            channelz.append(4);
            channelz.append(6);
            channelz.append(8);
        }

	byteOrderz.append(QAudioFormat::LittleEndian);

	typez.append(QAudioFormat::SignedInt);
	typez.append(QAudioFormat::UnSignedInt);

	codecz.append(QLatin1String("audio/pcm"));
    }
    if (freqz.count() > 0)
        freqz.prepend(8000);
}

QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
{
    Q_UNUSED(mode)

    QList<QByteArray> devices;
    //enumerate device fullnames through directshow api
    CoInitialize(NULL);
    ICreateDevEnum *pDevEnum = NULL;
    IEnumMoniker *pEnum = NULL;
    // Create the System device enumerator
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
                 CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
                 reinterpret_cast<void **>(&pDevEnum));

    unsigned long iNumDevs = mode == QAudio::AudioOutput ? waveOutGetNumDevs() : waveInGetNumDevs();
    if (SUCCEEDED(hr)) {
        // Create the enumerator for the video capture category
        hr = pDevEnum->CreateClassEnumerator(
             mode == QAudio::AudioOutput ? CLSID_AudioRendererCategory : CLSID_AudioInputDeviceCategory,
             &pEnum, 0);
        pEnum->Reset();
        // go through and find all video capture devices
        IMoniker *pMoniker = NULL;
        while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
            IPropertyBag *pPropBag;
            hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,
                 reinterpret_cast<void **>(&pPropBag));
            if (FAILED(hr)) {
                pMoniker->Release();
                continue; // skip this one
            }
            // Find if it is a wave device
            VARIANT var;
            VariantInit(&var);
            hr = pPropBag->Read(mode == QAudio::AudioOutput ? L"WaveOutID" : L"WaveInID", &var, 0);
            if (SUCCEEDED(hr)) {
                LONG waveID = var.lVal;
                if (waveID >= 0 && waveID < LONG(iNumDevs)) {
                    VariantClear(&var);
                    // Find the description
                    hr = pPropBag->Read(L"FriendlyName", &var, 0);
                    if (SUCCEEDED(hr)) {
                        QByteArray  device;
                        QDataStream ds(&device, QIODevice::WriteOnly);
                        ds << quint32(waveID) << QString::fromWCharArray(var.bstrVal);
                        devices.append(device);
                    }
                }
            }

            pPropBag->Release();
            pMoniker->Release();
        }
    }
    CoUninitialize();

    return devices;
}

QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
    QList<QByteArray> list = availableDevices(QAudio::AudioOutput);
    if (list.size() > 0)
        return list.at(0);
    else
        return QByteArray();
}

QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
    QList<QByteArray> list = availableDevices(QAudio::AudioInput);
    if (list.size() > 0)
        return list.at(0);
    else
        return QByteArray();
}

QT_END_NAMESPACE
<commit_msg>Fix a potential crash in audio device enumeration under Windows<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists for the convenience
// of other Qt classes.  This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//

#include <windows.h>
#include <mmsystem.h>
#include "qaudiodeviceinfo_win32_p.h"
#include <dshow.h>

#if defined(Q_CC_MINGW)

extern GUID CLSID_AudioInputDeviceCategory;

#ifndef __IErrorLog_INTERFACE_DEFINED__
#define __IErrorLog_INTERFACE_DEFINED__

DECLARE_INTERFACE_(IErrorLog, IUnknown)
{
    STDMETHOD(AddError)(THIS_ LPCOLESTR, EXCEPINFO *) PURE;
};

#endif /* __IErrorLog_INTERFACE_DEFINED__ */

#ifndef __IPropertyBag_INTERFACE_DEFINED__
#define __IPropertyBag_INTERFACE_DEFINED__

const GUID IID_IPropertyBag = {0x55272A00, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};

DECLARE_INTERFACE_(IPropertyBag, IUnknown)
{
    STDMETHOD(Read)(THIS_ LPCOLESTR, VARIANT *, IErrorLog *) PURE;
    STDMETHOD(Write)(THIS_ LPCOLESTR, VARIANT *) PURE;
};

#endif /* __IPropertyBag_INTERFACE_DEFINED__ */

#endif//Q_CC_MINGW

QT_BEGIN_NAMESPACE

// For mingw toolchain mmsystem.h only defines half the defines, so add if needed.
#ifndef WAVE_FORMAT_44M08
#define WAVE_FORMAT_44M08 0x00000100
#define WAVE_FORMAT_44S08 0x00000200
#define WAVE_FORMAT_44M16 0x00000400
#define WAVE_FORMAT_44S16 0x00000800
#define WAVE_FORMAT_48M08 0x00001000
#define WAVE_FORMAT_48S08 0x00002000
#define WAVE_FORMAT_48M16 0x00004000
#define WAVE_FORMAT_48S16 0x00008000
#define WAVE_FORMAT_96M08 0x00010000
#define WAVE_FORMAT_96S08 0x00020000
#define WAVE_FORMAT_96M16 0x00040000
#define WAVE_FORMAT_96S16 0x00080000
#endif

QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray dev, QAudio::Mode mode)
{
    QDataStream ds(&dev, QIODevice::ReadOnly);
    ds >> devId >> device;
    this->mode = mode;

    updateLists();
}

QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal()
{
    close();
}

bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
{
    return testSettings(format);
}

QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
    QAudioFormat nearest;
    if(mode == QAudio::AudioOutput) {
        nearest.setFrequency(44100);
        nearest.setChannelCount(2);
        nearest.setByteOrder(QAudioFormat::LittleEndian);
        nearest.setSampleType(QAudioFormat::SignedInt);
        nearest.setSampleSize(16);
        nearest.setCodec(QLatin1String("audio/pcm"));
    } else {
        nearest.setFrequency(11025);
        nearest.setChannelCount(1);
        nearest.setByteOrder(QAudioFormat::LittleEndian);
        nearest.setSampleType(QAudioFormat::SignedInt);
        nearest.setSampleSize(8);
        nearest.setCodec(QLatin1String("audio/pcm"));
    }
    return nearest;
}

QString QAudioDeviceInfoInternal::deviceName() const
{
    return device;
}

QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
    updateLists();
    return codecz;
}

QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
    updateLists();
    return freqz;
}

QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
    updateLists();
    return channelz;
}

QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
    updateLists();
    return sizez;
}

QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
    updateLists();
    return byteOrderz;
}

QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
    updateLists();
    return typez;
}

bool QAudioDeviceInfoInternal::open()
{
    return true;
}

void QAudioDeviceInfoInternal::close()
{
}

bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
{
    // Set nearest to closest settings that do work.
    // See if what is in settings will work (return value).

    bool failed = false;
    bool match = false;

    // check codec
    for( int i = 0; i < codecz.count(); i++) {
        if (format.codec() == codecz.at(i))
            match = true;
    }
    if (!match) failed = true;

    // check channel
    match = false;
    if (!failed) {
        for( int i = 0; i < channelz.count(); i++) {
            if (format.channels() == channelz.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check frequency
    match = false;
    if (!failed) {
        for( int i = 0; i < freqz.count(); i++) {
            if (format.frequency() == freqz.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check sample size
    match = false;
    if (!failed) {
        for( int i = 0; i < sizez.count(); i++) {
            if (format.sampleSize() == sizez.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check byte order
    match = false;
    if (!failed) {
        for( int i = 0; i < byteOrderz.count(); i++) {
            if (format.byteOrder() == byteOrderz.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    // check sample type
    match = false;
    if (!failed) {
        for( int i = 0; i < typez.count(); i++) {
            if (format.sampleType() == typez.at(i)) {
                match = true;
                break;
            }
        }
        if (!match)
            failed = true;
    }

    if(!failed) {
        // settings work
        return true;
    }
    return false;
}

void QAudioDeviceInfoInternal::updateLists()
{
    // redo all lists based on current settings
    bool match = false;
    DWORD fmt = NULL;

    if(mode == QAudio::AudioOutput) {
        WAVEOUTCAPS woc;
        if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) {
            match = true;
            fmt = woc.dwFormats;
        }
    } else {
        WAVEINCAPS woc;
        if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) {
            match = true;
            fmt = woc.dwFormats;
        }
    }
    sizez.clear();
    freqz.clear();
    channelz.clear();
    byteOrderz.clear();
    typez.clear();
    codecz.clear();

    if(match) {
        if((fmt && WAVE_FORMAT_1M08)
           || (fmt && WAVE_FORMAT_1S08)
	   || (fmt && WAVE_FORMAT_2M08)
	   || (fmt && WAVE_FORMAT_2S08)
	   || (fmt && WAVE_FORMAT_4M08)
	   || (fmt && WAVE_FORMAT_4S08)
#ifndef Q_OS_WINCE
	   || (fmt && WAVE_FORMAT_48M08)
	   || (fmt && WAVE_FORMAT_48S08)
	   || (fmt && WAVE_FORMAT_96M08)
	   || (fmt && WAVE_FORMAT_96S08)
#endif
       ) {
            sizez.append(8);
	}
        if((fmt && WAVE_FORMAT_1M16)
           || (fmt && WAVE_FORMAT_1S16)
	   || (fmt && WAVE_FORMAT_2M16)
	   || (fmt && WAVE_FORMAT_2S16)
	   || (fmt && WAVE_FORMAT_4M16)
	   || (fmt && WAVE_FORMAT_4S16)
#ifndef Q_OS_WINCE
	   || (fmt && WAVE_FORMAT_48M16)
	   || (fmt && WAVE_FORMAT_48S16)
	   || (fmt && WAVE_FORMAT_96M16)
	   || (fmt && WAVE_FORMAT_96S16)
#endif
       ) {
            sizez.append(16);
	}
        if((fmt && WAVE_FORMAT_1M08)
           || (fmt && WAVE_FORMAT_1S08)
	   || (fmt && WAVE_FORMAT_1M16)
	   || (fmt && WAVE_FORMAT_1S16)) {
            freqz.append(11025);
	}
        if((fmt && WAVE_FORMAT_2M08)
           || (fmt && WAVE_FORMAT_2S08)
	   || (fmt && WAVE_FORMAT_2M16)
	   || (fmt && WAVE_FORMAT_2S16)) {
            freqz.append(22050);
	}
        if((fmt && WAVE_FORMAT_4M08)
           || (fmt && WAVE_FORMAT_4S08)
	   || (fmt && WAVE_FORMAT_4M16)
	   || (fmt && WAVE_FORMAT_4S16)) {
            freqz.append(44100);
	}
#ifndef Q_OS_WINCE
        if((fmt && WAVE_FORMAT_48M08)
           || (fmt && WAVE_FORMAT_48S08)
	   || (fmt && WAVE_FORMAT_48M16)
	   || (fmt && WAVE_FORMAT_48S16)) {
            freqz.append(48000);
	}
        if((fmt && WAVE_FORMAT_96M08)
           || (fmt && WAVE_FORMAT_96S08)
	   || (fmt && WAVE_FORMAT_96M16)
	   || (fmt && WAVE_FORMAT_96S16)) {
            freqz.append(96000);
        }
#endif
	channelz.append(1);
	channelz.append(2);
        if (mode == QAudio::AudioOutput) {
            channelz.append(4);
            channelz.append(6);
            channelz.append(8);
        }

	byteOrderz.append(QAudioFormat::LittleEndian);

	typez.append(QAudioFormat::SignedInt);
	typez.append(QAudioFormat::UnSignedInt);

	codecz.append(QLatin1String("audio/pcm"));
    }
    if (freqz.count() > 0)
        freqz.prepend(8000);
}

QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
{
    Q_UNUSED(mode)

    QList<QByteArray> devices;
    //enumerate device fullnames through directshow api
    CoInitialize(NULL);
    ICreateDevEnum *pDevEnum = NULL;
    IEnumMoniker *pEnum = NULL;
    // Create the System device enumerator
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
                 CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
                 reinterpret_cast<void **>(&pDevEnum));

    unsigned long iNumDevs = mode == QAudio::AudioOutput ? waveOutGetNumDevs() : waveInGetNumDevs();
    if (SUCCEEDED(hr)) {
        // Create the enumerator for the audio input/output category
        if (pDevEnum->CreateClassEnumerator(
             mode == QAudio::AudioOutput ? CLSID_AudioRendererCategory : CLSID_AudioInputDeviceCategory,
             &pEnum, 0) == S_OK) {
            pEnum->Reset();
            // go through and find all audio devices
            IMoniker *pMoniker = NULL;
            while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
                IPropertyBag *pPropBag;
                hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,
                     reinterpret_cast<void **>(&pPropBag));
                if (FAILED(hr)) {
                    pMoniker->Release();
                    continue; // skip this one
                }
                // Find if it is a wave device
                VARIANT var;
                VariantInit(&var);
                hr = pPropBag->Read(mode == QAudio::AudioOutput ? L"WaveOutID" : L"WaveInID", &var, 0);
                if (SUCCEEDED(hr)) {
                    LONG waveID = var.lVal;
                    if (waveID >= 0 && waveID < LONG(iNumDevs)) {
                        VariantClear(&var);
                        // Find the description
                        hr = pPropBag->Read(L"FriendlyName", &var, 0);
                        if (SUCCEEDED(hr)) {
                            QByteArray  device;
                            QDataStream ds(&device, QIODevice::WriteOnly);
                            ds << quint32(waveID) << QString::fromWCharArray(var.bstrVal);
                            devices.append(device);
                        }
                    }
                }

                pPropBag->Release();
                pMoniker->Release();
            }
        }
    }
    CoUninitialize();

    return devices;
}

QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
    QList<QByteArray> list = availableDevices(QAudio::AudioOutput);
    if (list.size() > 0)
        return list.at(0);
    else
        return QByteArray();
}

QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
    QList<QByteArray> list = availableDevices(QAudio::AudioInput);
    if (list.size() > 0)
        return list.at(0);
    else
        return QByteArray();
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before><commit_msg>ChromeOS: Create new tab after fullscreen is really canceled when search key is pressed.   ToggleFullscreenMode is asynchronous, so we need to wait for   next event cycle before creating new tab and set focus to omni box.<commit_after><|endoftext|>


<commit_before><commit_msg>Once again for a mysterious reason all sites are crashing in  the distributed test at this location:<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This code glues the RLZ library DLL with Chrome. It allows Chrome to work
// with or without the DLL being present. If the DLL is not present the
// functions do nothing and just return false.

#include "chrome/browser/rlz/rlz.h"

#include <process.h>
#include <windows.h>

#include <algorithm>

#include "base/file_path.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/synchronization/lock.h"
#include "base/task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/google_update_settings.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"

namespace {

// The maximum length of an access points RLZ in wide chars.
const DWORD kMaxRlzLength = 64;

enum {
  ACCESS_VALUES_STALE,      // Possibly new values available.
  ACCESS_VALUES_FRESH       // The cached values are current.
};

// Tracks if we have tried and succeeded sending the ping. This helps us
// decide if we need to refresh the some cached strings.
volatile int access_values_state = ACCESS_VALUES_STALE;
base::Lock rlz_lock;

bool SendFinancialPing(const std::wstring& brand, const std::wstring& lang,
                       const std::wstring& referral, bool exclude_id) {
  rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX,
                                   rlz_lib::CHROME_HOME_PAGE,
                                   rlz_lib::NO_ACCESS_POINT};
  std::string brand_ascii(WideToASCII(brand));
  std::string lang_ascii(WideToASCII(lang));
  std::string referral_ascii(WideToASCII(referral));

  return rlz_lib::SendFinancialPing(rlz_lib::CHROME, points, "chrome",
                                    brand_ascii.c_str(), referral_ascii.c_str(),
                                    lang_ascii.c_str(), exclude_id, NULL, true);
}

// This class leverages the AutocompleteEditModel notification to know when
// the user first interacted with the omnibox and set a global accordingly.
class OmniBoxUsageObserver : public NotificationObserver {
 public:
  OmniBoxUsageObserver() {
    registrar_.Add(this, NotificationType::OMNIBOX_OPENED_URL,
                   NotificationService::AllSources());
    // If instant is enabled we'll start searching as soon as the user starts
    // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED).
    registrar_.Add(this, NotificationType::INSTANT_CONTROLLER_UPDATED,
                   NotificationService::AllSources());
    omnibox_used_ = false;
    DCHECK(!instance_);
    instance_ = this;
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    // Needs to be evaluated. See http://crbug.com/62328.
    base::ThreadRestrictions::ScopedAllowIO allow_io;

    // Try to record event now, else set the flag to try later when we
    // attempt the ping.
    if (!RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                        rlz_lib::CHROME_OMNIBOX,
                                        rlz_lib::FIRST_SEARCH))
      omnibox_used_ = true;
    delete this;
  }

  static bool used() {
    return omnibox_used_;
  }

  // Deletes the single instance of OmniBoxUsageObserver.
  static void DeleteInstance() {
    delete instance_;
  }

 private:
  // Dtor is private so the object cannot be created on the stack.
  ~OmniBoxUsageObserver() {
    instance_ = NULL;
  }

  static bool omnibox_used_;

  // There should only be one instance created at a time, and instance_ points
  // to that instance.
  // NOTE: this is only non-null for the amount of time it is needed. Once the
  // instance_ is no longer needed (or Chrome is exiting), this is null.
  static OmniBoxUsageObserver* instance_;

  NotificationRegistrar registrar_;
};

bool OmniBoxUsageObserver::omnibox_used_ = false;
OmniBoxUsageObserver* OmniBoxUsageObserver::instance_ = NULL;

// This task is run in the file thread, so to not block it for a long time
// we use a throwaway thread to do the blocking url request.
class DailyPingTask : public Task {
 public:
  virtual ~DailyPingTask() {
  }
  virtual void Run() {
    // We use a transient thread because we have no guarantees about
    // how long the RLZ lib can block us.
    _beginthread(PingNow, 0, NULL);
  }

 private:
  // Causes a ping to the server using WinInet.
  static void _cdecl PingNow(void*) {
    // Needs to be evaluated. See http://crbug.com/62328.
    base::ThreadRestrictions::ScopedAllowIO allow_io;

    std::wstring lang;
    GoogleUpdateSettings::GetLanguage(&lang);
    if (lang.empty())
      lang = L"en";
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    std::wstring referral;
    GoogleUpdateSettings::GetReferral(&referral);
    if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
      base::AutoLock lock(rlz_lock);
      access_values_state = ACCESS_VALUES_STALE;
      GoogleUpdateSettings::ClearReferral();
    }
  }

  // Organic brands all start with GG, such as GGCM.
  static bool is_organic(const std::wstring& brand) {
    return (brand.size() < 2) ? false : (brand.substr(0, 2) == L"GG");
  }
};

// Performs late RLZ initialization and RLZ event recording for chrome.
// This task needs to run on the UI thread.
class DelayedInitTask : public Task {
 public:
  explicit DelayedInitTask(bool first_run)
      : first_run_(first_run) {
  }
  virtual ~DelayedInitTask() {
  }
  virtual void Run() {
    // For non-interactive tests we don't do the rest of the initialization
    // because sometimes the very act of loading the dll causes QEMU to crash.
    if (::GetEnvironmentVariableW(ASCIIToWide(env_vars::kHeadless).c_str(),
                                  NULL, 0)) {
      return;
    }
    // For organic brandcodes do not use rlz at all. Empty brandcode usually
    // means a chromium install. This is ok.
    std::wstring brand;
    if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() ||
        GoogleUpdateSettings::IsOrganic(brand))
      return;

    // Do the initial event recording if is the first run or if we have an
    // empty rlz which means we haven't got a chance to do it.
    std::wstring omnibox_rlz;
    RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &omnibox_rlz);

    if (first_run_ || omnibox_rlz.empty()) {
      // Record the installation of chrome.
      RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                     rlz_lib::CHROME_OMNIBOX,
                                     rlz_lib::INSTALL);
      RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                     rlz_lib::CHROME_HOME_PAGE,
                                     rlz_lib::INSTALL);
      // Record if google is the initial search provider.
      if (IsGoogleDefaultSearch()) {
        RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                       rlz_lib::CHROME_OMNIBOX,
                                       rlz_lib::SET_TO_GOOGLE);
      }
    }
    // Record first user interaction with the omnibox. We call this all the
    // time but the rlz lib should ingore all but the first one.
    if (OmniBoxUsageObserver::used()) {
      RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                     rlz_lib::CHROME_OMNIBOX,
                                     rlz_lib::FIRST_SEARCH);
    }
    // Schedule the daily RLZ ping.
    MessageLoop::current()->PostTask(FROM_HERE, new DailyPingTask());
  }

 private:
  bool IsGoogleDefaultSearch() {
    if (!g_browser_process)
      return false;
    FilePath user_data_dir;
    if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
      return false;
    ProfileManager* profile_manager = g_browser_process->profile_manager();
    Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
    if (!profile)
      return false;
    const TemplateURL* url_template =
        profile->GetTemplateURLModel()->GetDefaultSearchProvider();
    if (!url_template)
      return false;
    const TemplateURLRef* urlref = url_template->url();
    if (!urlref)
      return false;
    return urlref->HasGoogleBaseURLs();
  }

  bool first_run_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask);
};

}  // namespace

bool RLZTracker::InitRlzDelayed(bool first_run, int delay) {
  // Maximum and minimum delay we would allow to be set through master
  // preferences. Somewhat arbitrary, may need to be adjusted in future.
  const int kMaxDelay = 200 * 1000;
  const int kMinDelay = 20 * 1000;

  delay *= 1000;
  delay = (delay < kMinDelay) ? kMinDelay : delay;
  delay = (delay > kMaxDelay) ? kMaxDelay : delay;

  if (!OmniBoxUsageObserver::used())
    new OmniBoxUsageObserver();

  // Schedule the delayed init items.
  BrowserThread::PostDelayedTask(
      BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run), delay);
  return true;
}

bool RLZTracker::RecordProductEvent(rlz_lib::Product product,
                                    rlz_lib::AccessPoint point,
                                    rlz_lib::Event event_id) {
  return rlz_lib::RecordProductEvent(product, point, event_id);
}

bool RLZTracker::ClearAllProductEvents(rlz_lib::Product product) {
  return rlz_lib::ClearAllProductEvents(product);
}

// We implement caching of the answer of get_access_point() if the request
// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
// cached value.

bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
                                   std::wstring* rlz) {
  static std::wstring cached_ommibox_rlz;
  if (rlz_lib::CHROME_OMNIBOX == point) {
    base::AutoLock lock(rlz_lock);
    if (access_values_state == ACCESS_VALUES_FRESH) {
      *rlz = cached_ommibox_rlz;
      return true;
    }
  }

  // Make sure we don't access disk outside of the file context.
  // In such case we repost the task on the right thread and return error.
  if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
    // Caching of access points is now only implemented for the CHROME_OMNIBOX.
    // Thus it is not possible to call this function on another thread for
    // other access points until proper caching for these has been implemented
    // and the code that calls this function can handle synchronous fetching
    // of the access point.
    DCHECK_EQ(rlz_lib::CHROME_OMNIBOX, point);

    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE,
        NewRunnableFunction(&RLZTracker::GetAccessPointRlz,
                            point, &cached_ommibox_rlz));
      rlz->erase();
      return false;
  }

  char str_rlz[kMaxRlzLength + 1];
  if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL))
    return false;
  *rlz = ASCIIToWide(std::string(str_rlz));
  if (rlz_lib::CHROME_OMNIBOX == point) {
    base::AutoLock lock(rlz_lock);
    cached_ommibox_rlz.assign(*rlz);
    access_values_state = ACCESS_VALUES_FRESH;
  }
  return true;
}

// static
void RLZTracker::CleanupRlz() {
  OmniBoxUsageObserver::DeleteInstance();
}
<commit_msg>Allows distributions to send a finanacial ping immediately after a first search is performed, even if a financial ping has already been sent for the install event.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This code glues the RLZ library DLL with Chrome. It allows Chrome to work
// with or without the DLL being present. If the DLL is not present the
// functions do nothing and just return false.

#include "chrome/browser/rlz/rlz.h"

#include <process.h>
#include <windows.h>

#include <algorithm>

#include "base/file_path.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/synchronization/lock.h"
#include "base/task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/google_update_settings.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"

namespace {

// The maximum length of an access points RLZ in wide chars.
const DWORD kMaxRlzLength = 64;

enum {
  ACCESS_VALUES_STALE,      // Possibly new values available.
  ACCESS_VALUES_FRESH       // The cached values are current.
};

// Tracks if we have tried and succeeded sending the ping. This helps us
// decide if we need to refresh the some cached strings.
volatile int access_values_state = ACCESS_VALUES_STALE;
base::Lock rlz_lock;

bool SendFinancialPing(const std::wstring& brand, const std::wstring& lang,
                       const std::wstring& referral, bool exclude_id) {
  rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX,
                                   rlz_lib::CHROME_HOME_PAGE,
                                   rlz_lib::NO_ACCESS_POINT};
  std::string brand_ascii(WideToASCII(brand));
  std::string lang_ascii(WideToASCII(lang));
  std::string referral_ascii(WideToASCII(referral));

  return rlz_lib::SendFinancialPing(rlz_lib::CHROME, points, "chrome",
                                    brand_ascii.c_str(), referral_ascii.c_str(),
                                    lang_ascii.c_str(), exclude_id, NULL, true);
}

// This class leverages the AutocompleteEditModel notification to know when
// the user first interacted with the omnibox and set a global accordingly.
class OmniBoxUsageObserver : public NotificationObserver {
 public:
  OmniBoxUsageObserver(bool first_run, bool send_ping_immediately)
    : first_run_(first_run),
      send_ping_immediately_(send_ping_immediately) {
    registrar_.Add(this, NotificationType::OMNIBOX_OPENED_URL,
                   NotificationService::AllSources());
    // If instant is enabled we'll start searching as soon as the user starts
    // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED).
    registrar_.Add(this, NotificationType::INSTANT_CONTROLLER_UPDATED,
                   NotificationService::AllSources());
    omnibox_used_ = false;
    DCHECK(!instance_);
    instance_ = this;
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  static bool used() {
    return omnibox_used_;
  }

  // Deletes the single instance of OmniBoxUsageObserver.
  static void DeleteInstance() {
    delete instance_;
  }

 private:
  // Dtor is private so the object cannot be created on the stack.
  ~OmniBoxUsageObserver() {
    instance_ = NULL;
  }

  static bool omnibox_used_;

  // There should only be one instance created at a time, and instance_ points
  // to that instance.
  // NOTE: this is only non-null for the amount of time it is needed. Once the
  // instance_ is no longer needed (or Chrome is exiting), this is null.
  static OmniBoxUsageObserver* instance_;

  NotificationRegistrar registrar_;
  bool first_run_;
  bool send_ping_immediately_;
};

bool OmniBoxUsageObserver::omnibox_used_ = false;
OmniBoxUsageObserver* OmniBoxUsageObserver::instance_ = NULL;

// This task is run in the file thread, so to not block it for a long time
// we use a throwaway thread to do the blocking url request.
class DailyPingTask : public Task {
 public:
  virtual ~DailyPingTask() {
  }
  virtual void Run() {
    // We use a transient thread because we have no guarantees about
    // how long the RLZ lib can block us.
    _beginthread(PingNow, 0, NULL);
  }

 private:
  // Causes a ping to the server using WinInet.
  static void _cdecl PingNow(void*) {
    // Needs to be evaluated. See http://crbug.com/62328.
    base::ThreadRestrictions::ScopedAllowIO allow_io;

    std::wstring lang;
    GoogleUpdateSettings::GetLanguage(&lang);
    if (lang.empty())
      lang = L"en";
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    std::wstring referral;
    GoogleUpdateSettings::GetReferral(&referral);
    if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
      base::AutoLock lock(rlz_lock);
      access_values_state = ACCESS_VALUES_STALE;
      GoogleUpdateSettings::ClearReferral();
    }
  }

  // Organic brands all start with GG, such as GGCM.
  static bool is_organic(const std::wstring& brand) {
    return (brand.size() < 2) ? false : (brand.substr(0, 2) == L"GG");
  }
};

// Performs late RLZ initialization and RLZ event recording for chrome.
// This task needs to run on the UI thread.
class DelayedInitTask : public Task {
 public:
  explicit DelayedInitTask(bool first_run)
      : first_run_(first_run) {
  }
  virtual ~DelayedInitTask() {
  }
  virtual void Run() {
    // For non-interactive tests we don't do the rest of the initialization
    // because sometimes the very act of loading the dll causes QEMU to crash.
    if (::GetEnvironmentVariableW(ASCIIToWide(env_vars::kHeadless).c_str(),
                                  NULL, 0)) {
      return;
    }
    // For organic brandcodes do not use rlz at all. Empty brandcode usually
    // means a chromium install. This is ok.
    std::wstring brand;
    if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() ||
        GoogleUpdateSettings::IsOrganic(brand))
      return;

    // Do the initial event recording if is the first run or if we have an
    // empty rlz which means we haven't got a chance to do it.
    std::wstring omnibox_rlz;
    RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &omnibox_rlz);

    if ((first_run_ || omnibox_rlz.empty()) && !already_ran_) {
      already_ran_ = true;

      // Record the installation of chrome.
      RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                     rlz_lib::CHROME_OMNIBOX,
                                     rlz_lib::INSTALL);
      RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                     rlz_lib::CHROME_HOME_PAGE,
                                     rlz_lib::INSTALL);
      // Record if google is the initial search provider.
      if (IsGoogleDefaultSearch()) {
        RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                       rlz_lib::CHROME_OMNIBOX,
                                       rlz_lib::SET_TO_GOOGLE);
      }
    }
    // Record first user interaction with the omnibox. We call this all the
    // time but the rlz lib should ingore all but the first one.
    if (OmniBoxUsageObserver::used()) {
      RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                     rlz_lib::CHROME_OMNIBOX,
                                     rlz_lib::FIRST_SEARCH);
    }
    // Schedule the daily RLZ ping.
    MessageLoop::current()->PostTask(FROM_HERE, new DailyPingTask());
  }

 private:
  bool IsGoogleDefaultSearch() {
    if (!g_browser_process)
      return false;
    FilePath user_data_dir;
    if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
      return false;
    ProfileManager* profile_manager = g_browser_process->profile_manager();
    Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
    if (!profile)
      return false;
    const TemplateURL* url_template =
        profile->GetTemplateURLModel()->GetDefaultSearchProvider();
    if (!url_template)
      return false;
    const TemplateURLRef* urlref = url_template->url();
    if (!urlref)
      return false;
    return urlref->HasGoogleBaseURLs();
  }

  // Flag that remembers if the delayed task already ran or not.  This is
  // needed only in the first_run case, since we don't want to record the
  // set-to-google event more than once.  We need to worry about this event
  // (and not the others) because it is not a stateful RLZ event.
  static bool already_ran_;

  bool first_run_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask);
};

bool DelayedInitTask::already_ran_ = false;

void OmniBoxUsageObserver::Observe(NotificationType type,
                                   const NotificationSource& source,
                                   const NotificationDetails& details) {
  // Needs to be evaluated. See http://crbug.com/62328.
  base::ThreadRestrictions::ScopedAllowIO allow_io;

  // Try to record event now, else set the flag to try later when we
  // attempt the ping.
  if (!RLZTracker::RecordProductEvent(rlz_lib::CHROME,
                                      rlz_lib::CHROME_OMNIBOX,
                                      rlz_lib::FIRST_SEARCH))
    omnibox_used_ = true;
  else if (send_ping_immediately_) {
    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run_));
  }

  delete this;
}

}  // namespace

bool RLZTracker::InitRlzDelayed(bool first_run, int delay) {
  // A negative delay means that a financial ping should be sent immediately
  // after a first search is recorded, without waiting for the next restart
  // of chrome.  However, we only want this behaviour on first run.
  bool send_ping_immediately = false;
  if (delay < 0) {
    send_ping_immediately = true;
    delay = -delay;
  }

  // Maximum and minimum delay we would allow to be set through master
  // preferences. Somewhat arbitrary, may need to be adjusted in future.
  const int kMaxDelay = 200 * 1000;
  const int kMinDelay = 20 * 1000;

  delay *= 1000;
  delay = (delay < kMinDelay) ? kMinDelay : delay;
  delay = (delay > kMaxDelay) ? kMaxDelay : delay;

  if (!OmniBoxUsageObserver::used())
    new OmniBoxUsageObserver(first_run, send_ping_immediately);

  // Schedule the delayed init items.
  BrowserThread::PostDelayedTask(
      BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run), delay);
  return true;
}

bool RLZTracker::RecordProductEvent(rlz_lib::Product product,
                                    rlz_lib::AccessPoint point,
                                    rlz_lib::Event event_id) {
  return rlz_lib::RecordProductEvent(product, point, event_id);
}

bool RLZTracker::ClearAllProductEvents(rlz_lib::Product product) {
  return rlz_lib::ClearAllProductEvents(product);
}

// We implement caching of the answer of get_access_point() if the request
// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
// cached value.

bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
                                   std::wstring* rlz) {
  static std::wstring cached_ommibox_rlz;
  if (rlz_lib::CHROME_OMNIBOX == point) {
    base::AutoLock lock(rlz_lock);
    if (access_values_state == ACCESS_VALUES_FRESH) {
      *rlz = cached_ommibox_rlz;
      return true;
    }
  }

  // Make sure we don't access disk outside of the file context.
  // In such case we repost the task on the right thread and return error.
  if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
    // Caching of access points is now only implemented for the CHROME_OMNIBOX.
    // Thus it is not possible to call this function on another thread for
    // other access points until proper caching for these has been implemented
    // and the code that calls this function can handle synchronous fetching
    // of the access point.
    DCHECK_EQ(rlz_lib::CHROME_OMNIBOX, point);

    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE,
        NewRunnableFunction(&RLZTracker::GetAccessPointRlz,
                            point, &cached_ommibox_rlz));
      rlz->erase();
      return false;
  }

  char str_rlz[kMaxRlzLength + 1];
  if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL))
    return false;
  *rlz = ASCIIToWide(std::string(str_rlz));
  if (rlz_lib::CHROME_OMNIBOX == point) {
    base::AutoLock lock(rlz_lock);
    cached_ommibox_rlz.assign(*rlz);
    access_values_state = ACCESS_VALUES_FRESH;
  }
  return true;
}

// static
void RLZTracker::CleanupRlz() {
  OmniBoxUsageObserver::DeleteInstance();
}
<|endoftext|>


<commit_before><commit_msg>Turn off preconnect for UI tests as well.<commit_after><|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright 2019 MINRES Technologies GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/

#include "sysc/communication/sc_communication_ids.h"
#include "sysc/kernel/sc_wait.h"
#include "scc/report.h"
#include <scc/ordered_semaphore.h>
#include <util/strprintf.h>

namespace scc {

using namespace sc_core;

// ----------------------------------------------------------------------------
//  CLASS : sc_semaphore
//
//  The sc_semaphore primitive channel class.
// ----------------------------------------------------------------------------

// error reporting
namespace {
std::string gen_unique_event_name(const char* modifier) {
    auto str = std::string("$$$$kernel_event$$$$_") + "_" + modifier;
    return std::string(sc_core::sc_gen_unique_name(str.c_str(), false));
}
} // namespace

void ordered_semaphore::set_capacity(unsigned c) {
    if(typeid(*this)==typeid(ordered_semaphore)){
        auto diff = static_cast<int>(capacity) - static_cast<int>(c);
        capacity=c;
        value-=diff;
        if(value>0) free_evt.notify();
    } else {
        SCCWARN(SCMOD) << "cannot resize fixed size ordered semaphore";
    }
}

void ordered_semaphore::report_error(const char* id, const char* add_msg) const {
    auto msg = add_msg? util::strprintf("semaphore '%s'", name()):util::strprintf("%s: semaphore '%s'", add_msg, name());
    SC_REPORT_ERROR(id, msg.c_str());
}

// constructors

ordered_semaphore::ordered_semaphore(unsigned init_value_)
: sc_core::sc_object(sc_core::sc_gen_unique_name("semaphore"))
, free_evt(gen_unique_event_name("free_event").c_str())
, value(init_value_)
, capacity(init_value_) {
    if(value < 0) {
        report_error(sc_core::SC_ID_INVALID_SEMAPHORE_VALUE_);
    }
}

ordered_semaphore::ordered_semaphore(const char* name_, unsigned init_value_)
: sc_object(name_)
, free_evt(gen_unique_event_name("free_event").c_str())
, value(init_value_)
, capacity(init_value_){
}

// interface methods

// lock (take) the semaphore, block if not available

int ordered_semaphore::wait() {
    queue.push_back(sc_core::sc_get_current_process_handle());
    while(in_use()) {
        sc_core::wait(free_evt);
    }
    --value;
    return 0;
}

// lock (take) the semaphore, return -1 if not available

int ordered_semaphore::trywait() {
    if(in_use()) {
        return -1;
    }
    --value;
    return 0;
}

// unlock (give) the semaphore

int ordered_semaphore::post() {
    ++value;
    if(value>0) free_evt.notify();
    return 0;
}

} // namespace scc
<commit_msg>add semaphore check<commit_after>/*******************************************************************************
 * Copyright 2019 MINRES Technologies GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/

#include "sysc/communication/sc_communication_ids.h"
#include "sysc/kernel/sc_wait.h"
#include "scc/report.h"
#include <scc/ordered_semaphore.h>
#include <util/strprintf.h>

namespace scc {

using namespace sc_core;

// ----------------------------------------------------------------------------
//  CLASS : sc_semaphore
//
//  The sc_semaphore primitive channel class.
// ----------------------------------------------------------------------------

// error reporting
namespace {
std::string gen_unique_event_name(const char* modifier) {
    auto str = std::string("$$$$kernel_event$$$$_") + "_" + modifier;
    return std::string(sc_core::sc_gen_unique_name(str.c_str(), false));
}
} // namespace

void ordered_semaphore::set_capacity(unsigned c) {
    if(typeid(*this)==typeid(ordered_semaphore)){
        auto diff = static_cast<int>(capacity) - static_cast<int>(c);
        capacity=c;
        value-=diff;
        if(value>0) free_evt.notify();
    } else {
        SCCWARN(SCMOD) << "cannot resize fixed size ordered semaphore";
    }
}

void ordered_semaphore::report_error(const char* id, const char* add_msg) const {
    auto msg = add_msg? util::strprintf("semaphore '%s'", name()):util::strprintf("%s: semaphore '%s'", add_msg, name());
    SC_REPORT_ERROR(id, msg.c_str());
}

// constructors

ordered_semaphore::ordered_semaphore(unsigned init_value_)
: sc_core::sc_object(sc_core::sc_gen_unique_name("semaphore"))
, free_evt(gen_unique_event_name("free_event").c_str())
, value(init_value_)
, capacity(init_value_) {
    if(value < 0) {
        report_error(sc_core::SC_ID_INVALID_SEMAPHORE_VALUE_);
    }
}

ordered_semaphore::ordered_semaphore(const char* name_, unsigned init_value_)
: sc_object(name_)
, free_evt(gen_unique_event_name("free_event").c_str())
, value(init_value_)
, capacity(init_value_){
}

// interface methods

// lock (take) the semaphore, block if not available

int ordered_semaphore::wait() {
    queue.push_back(sc_core::sc_get_current_process_handle());
    while(in_use()) {
        sc_core::wait(free_evt);
    }
    --value;
    return 0;
}

// lock (take) the semaphore, return -1 if not available

int ordered_semaphore::trywait() {
    if(in_use()) {
        return -1;
    }
    --value;
    return 0;
}

// unlock (give) the semaphore

int ordered_semaphore::post() {
    if(value==capacity)
        SCCWARN(SCMOD)<<"post() called on entirely free semaphore!";
    else
        ++value;
    if(value>0) free_evt.notify();
    return 0;
}

} // namespace scc
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *  Copyright (C) 2019 PX4 Development Team. 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.
 * 3. Neither the name PX4 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 THE COPYRIGHT HOLDERS AND 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 THE
 * COPYRIGHT OWNER 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 <unit_test.h>
#include <containers/IntrusiveQueue.hpp>
#include <float.h>
#include <math.h>

class testContainer : public IntrusiveQueueNode<testContainer *>
{
public:
	int i{0};
};

class IntrusiveQueueTest : public UnitTest
{
public:
	virtual bool run_tests();

	bool test_push();
	bool test_pop();
	bool test_push_duplicate();
	bool test_remove();

};

bool IntrusiveQueueTest::run_tests()
{
	ut_run_test(test_push);
	ut_run_test(test_pop);
	ut_run_test(test_push_duplicate);
	ut_run_test(test_remove);

	return (_tests_failed == 0);
}

bool IntrusiveQueueTest::test_push()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;

		ut_compare("size increasing with i", q1.size(), i);
		q1.push(t);
		ut_compare("size increasing with i", q1.size(), i + 1);

		ut_assert_true(!q1.empty());
	}

	// verify full size (100)
	ut_compare("size 100", q1.size(), 100);

	// pop all elements
	for (int i = 0; i < 100; i++) {
		auto node = q1.front();
		q1.pop();
		delete node;
	}

	// verify list has been cleared
	ut_compare("size 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	return true;
}

bool IntrusiveQueueTest::test_pop()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;
		q1.push(t);
	}

	// verify full size (100)
	ut_assert_true(q1.size() == 100);

	for (int i = 0; i < 100; i++) {
		auto node = q1.front();
		ut_compare("stored i", i, node->i);

		ut_compare("size check", q1.size(), 100 - i);
		q1.pop();
		ut_compare("size check", q1.size(), 100 - i - 1);

		delete node;

		ut_compare("size check", q1.size(), 100 - i - 1);
	}

	// verify list has been cleared
	ut_assert_true(q1.empty());
	ut_compare("size check", q1.size(), 0);

	// pop an empty queue
	auto T = q1.pop();
	ut_assert_true(T == nullptr);
	ut_assert_true(q1.empty());
	ut_compare("size check", q1.size(), 0);

	return true;
}

bool IntrusiveQueueTest::test_push_duplicate()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;

		ut_compare("size increasing with i", q1.size(), i);
		q1.push(t);
		ut_compare("size increasing with i", q1.size(), i + 1);

		ut_assert_true(!q1.empty());
	}

	// verify full size (100)
	ut_compare("size 100", q1.size(), 100);

	// attempt to insert front again
	const auto q1_front = q1.front();
	const auto q1_front_i = q1_front->i; // copy i value

	const auto q1_back = q1.back();
	const auto q1_back_i = q1_back->i; // copy i value

	// push front and back aagain
	q1.push(q1_front);
	q1.push(q1_back);

	// verify no change
	ut_compare("size 100", q1.size(), 100);
	ut_compare("q front not reinserted", q1.front()->i, q1_front->i);
	ut_compare("q back not reinserted", q1.back()->i, q1_back->i);

	// pop the head
	const auto q1_head = q1.pop();

	// verfify size should now be 99
	ut_compare("size 99", q1.size(), 99);

	// push back on
	q1.push(q1_head);

	// verify size now 100 again
	ut_compare("size 100", q1.size(), 100);

	// pop all elements
	for (int i = 0; i < 100; i++) {
		auto node = q1.front();
		q1.pop();
		delete node;
	}

	// verify list has been cleared
	ut_compare("size 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	return true;
}

bool IntrusiveQueueTest::test_remove()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;
		q1.push(t);

		ut_compare("size increasing with i", q1.size(), i + 1);
		ut_assert_true(!q1.empty());
	}

	// verify full size (100)
	ut_assert_true(q1.size() == 100);

	// test removing elements
	for (int remove_i = 0; remove_i < 100; remove_i++) {

		// find node with i == remove_i
		testContainer *removed = nullptr;

		for (auto t : q1) {
			if (t->i == remove_i) {
				ut_assert_true(q1.remove(t));
				removed = t;
			}
		}

		delete removed;

		// iterate list again to verify removal
		for (auto t : q1) {
			ut_assert_true(t->i != remove_i);
		}

		ut_assert_true(q1.size() == 100 - remove_i - 1);
	}

	// list should now be empty
	ut_assert_true(q1.empty());
	ut_compare("size 0", q1.size(), 0);

	// delete all elements (should be safe on empty list)
	while (!q1.empty()) {
		q1.pop();
	}

	// verify list has been cleared
	ut_assert_true(q1.empty());
	ut_compare("size 0", q1.size(), 0);

	return true;
}

ut_declare_test_c(test_IntrusiveQueue, IntrusiveQueueTest)
<commit_msg>tests: IntrusiveQueue test re-insert case<commit_after>/****************************************************************************
 *
 *  Copyright (C) 2019 PX4 Development Team. 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.
 * 3. Neither the name PX4 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 THE COPYRIGHT HOLDERS AND 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 THE
 * COPYRIGHT OWNER 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 <unit_test.h>
#include <containers/IntrusiveQueue.hpp>
#include <float.h>
#include <math.h>

class testContainer : public IntrusiveQueueNode<testContainer *>
{
public:
	int i{0};
};

class IntrusiveQueueTest : public UnitTest
{
public:
	virtual bool run_tests();

	bool test_push();
	bool test_pop();
	bool test_push_duplicate();
	bool test_remove();
	bool test_reinsert();

};

bool IntrusiveQueueTest::run_tests()
{
	ut_run_test(test_push);
	ut_run_test(test_pop);
	ut_run_test(test_push_duplicate);
	ut_run_test(test_remove);
	ut_run_test(test_reinsert);

	return (_tests_failed == 0);
}

bool IntrusiveQueueTest::test_push()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;

		ut_compare("size increasing with i", q1.size(), i);
		q1.push(t);
		ut_compare("size increasing with i", q1.size(), i + 1);

		ut_assert_false(q1.empty());
	}

	// verify full size (100)
	ut_compare("size 100", q1.size(), 100);

	// pop all elements
	for (int i = 0; i < 100; i++) {
		auto node = q1.front();

		ut_assert_false(q1.empty());

		ut_assert_true(q1.pop() == node);
		delete node;

		bool expect_empty = (i == 100 - 1);
		ut_compare("empty", q1.empty(), expect_empty);
	}

	// verify list has been cleared
	ut_compare("size 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	return true;
}

bool IntrusiveQueueTest::test_pop()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;
		q1.push(t);
	}

	// verify full size (100)
	ut_assert_true(q1.size() == 100);
	ut_assert_false(q1.empty());

	for (int i = 0; i < 100; i++) {
		if (i < 100 - 1) {
			ut_assert_false(q1.empty());
		}

		auto node = q1.front();
		ut_compare("stored i", i, node->i);

		ut_compare("size check", q1.size(), 100 - i);
		q1.pop();

		if (i < 100 - 1) {
			ut_assert_false(q1.empty());

		} else {
			ut_assert_true(q1.empty());
		}

		ut_compare("size check", q1.size(), 100 - i - 1);

		delete node;

		ut_compare("size check", q1.size(), 100 - i - 1);
	}

	// verify list has been cleared
	ut_assert_true(q1.empty());
	ut_compare("size check", q1.size(), 0);

	// pop an empty queue
	auto T = q1.pop();
	ut_assert_true(T == nullptr);
	ut_assert_true(q1.empty());
	ut_compare("size check", q1.size(), 0);

	return true;
}

bool IntrusiveQueueTest::test_push_duplicate()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;

		ut_compare("size increasing with i", q1.size(), i);
		q1.push(t);
		ut_compare("size increasing with i", q1.size(), i + 1);

		ut_assert_true(!q1.empty());
	}

	// verify full size (100)
	ut_compare("size 100", q1.size(), 100);

	// attempt to insert front again
	const auto q1_front = q1.front();
	const auto q1_front_i = q1_front->i; // copy i value

	const auto q1_back = q1.back();
	const auto q1_back_i = q1_back->i; // copy i value

	// push front and back aagain
	q1.push(q1_front);
	q1.push(q1_back);

	// verify no change
	ut_compare("size 100", q1.size(), 100);
	ut_compare("q front not reinserted", q1.front()->i, q1_front->i);
	ut_compare("q back not reinserted", q1.back()->i, q1_back->i);

	// pop the head
	const auto q1_head = q1.pop();

	// verfify size should now be 99
	ut_compare("size 99", q1.size(), 99);

	// push back on
	q1.push(q1_head);

	// verify size now 100 again
	ut_compare("size 100", q1.size(), 100);

	// pop all elements
	for (int i = 0; i < 100; i++) {
		auto node = q1.front();
		q1.pop();
		delete node;
	}

	// verify list has been cleared
	ut_compare("size 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	return true;
}

bool IntrusiveQueueTest::test_remove()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;
		q1.push(t);

		ut_compare("size increasing with i", q1.size(), i + 1);
		ut_assert_true(!q1.empty());
	}

	// verify full size (100)
	ut_assert_true(q1.size() == 100);
	ut_assert_false(q1.empty());

	// test removing elements
	for (int remove_i = 0; remove_i < 100; remove_i++) {

		ut_assert_false(q1.empty());

		// find node with i == remove_i
		testContainer *removed = nullptr;

		for (auto t : q1) {
			if (t->i == remove_i) {
				ut_assert_true(q1.remove(t));
				removed = t;
			}
		}

		// q1 shouldn't be empty until the very last iteration
		if (remove_i < 100 - 1) {
			ut_assert_false(q1.empty());

		} else {
			ut_assert_true(q1.empty());
		}

		delete removed;

		// iterate list again to verify removal
		for (auto t : q1) {
			ut_assert_true(t->i != remove_i);
		}

		ut_assert_true(q1.size() == 100 - remove_i - 1);
	}

	// list should now be empty
	ut_assert_true(q1.empty());
	ut_compare("size 0", q1.size(), 0);

	// delete all elements (should be safe on empty list)
	while (!q1.empty()) {
		q1.pop();
	}

	// verify list has been cleared
	ut_assert_true(q1.empty());
	ut_compare("size 0", q1.size(), 0);

	return true;
}

bool IntrusiveQueueTest::test_reinsert()
{
	IntrusiveQueue<testContainer *> q1;

	// size should be 0 initially
	ut_compare("size initially 0", q1.size(), 0);
	ut_assert_true(q1.empty());

	// insert 100
	for (int i = 0; i < 100; i++) {
		testContainer *t = new testContainer();
		t->i = i;
		q1.push(t);

		ut_compare("size increasing with i", q1.size(), i + 1);
		ut_assert_true(!q1.empty());
	}

	// verify full size (100)
	ut_assert_true(q1.size() == 100);
	ut_assert_false(q1.empty());

	// test removing elements
	for (int remove_i = 0; remove_i < 100; remove_i++) {

		ut_assert_false(q1.empty());

		// find node with i == remove_i
		testContainer *removed = nullptr;

		for (auto t : q1) {
			if (t->i == remove_i) {
				ut_assert_true(q1.remove(t));
				removed = t;
			}
		}

		// q1 shouldn't be empty until the very last iteration
		ut_assert_false(q1.empty());

		// iterate list again to verify removal
		for (auto t : q1) {
			ut_assert_true(t->i != remove_i);
		}

		// size temporarily reduced by 1
		ut_assert_true(q1.size() == 100 - 1);

		// now re-insert the removed node
		const size_t sz1 = q1.size();
		q1.push(removed);
		const size_t sz2 = q1.size();

		// verify the size increase
		ut_assert_true(sz2 > sz1);

		// size restored to 100
		ut_assert_true(q1.size() == 100);
	}

	// queue shouldn't be empty
	ut_assert_false(q1.empty());
	ut_compare("size still 100", q1.size(), 100);

	// delete all elements
	while (!q1.empty()) {
		auto t = q1.pop();
		delete t;
	}

	// verify list has been cleared
	ut_assert_true(q1.empty());
	ut_compare("size 0", q1.size(), 0);

	return true;
}

ut_declare_test_c(test_IntrusiveQueue, IntrusiveQueueTest)
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsystemalignedtimer.h"
#include "qsystemalignedtimer_meego_p.h"
#include <QDebug>

#include <errno.h>
#include <stdio.h>

QTM_BEGIN_NAMESPACE

QSystemAlignedTimerPrivate::QSystemAlignedTimerPrivate(QObject *parent)
    : QObject(parent)
    , m_lastError(QSystemAlignedTimer::NoError)
    , m_minimumInterval(0)
    , m_maximumInterval(0)
    , m_running(false)
    , m_singleShot(false)
    , m_iphbdHandler(0)
    , m_notifier(0)
{
    m_iphbdHandler = iphb_open(0);

    if (!m_iphbdHandler) {
        m_lastError = QSystemAlignedTimer::InternalError;
        qDebug() << "iphb_open error" << m_iphbdHandler<< errno <<strerror(errno);
        return;
    }

    int sockfd = iphb_get_fd(m_iphbdHandler);
    if (!(sockfd > -1)) {
        m_lastError = QSystemAlignedTimer::InternalError;
        qDebug() << "socket failure"<<strerror(errno);
        return;
    }

    m_notifier = new QSocketNotifier(sockfd, QSocketNotifier::Read, this);
    if (!QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(heartbeatReceived(int)))) {
        delete m_notifier, m_notifier = 0;
        m_lastError = QSystemAlignedTimer::TimerFailed;
        qDebug() << "timer failure";
        return;
    }
    m_notifier->setEnabled(false);
}

QSystemAlignedTimerPrivate::~QSystemAlignedTimerPrivate()
{
    if (m_iphbdHandler)
        (void)iphb_close(m_iphbdHandler);

    if (m_notifier)
        delete m_notifier;
}

void QSystemAlignedTimerPrivate::wokeUp()
{
    if (m_singleShot) {
        stop();
        return;
    }

    int st = iphb_I_woke_up(m_iphbdHandler);
    if (!(st >= 0)) {
        m_lastError = QSystemAlignedTimer::TimerFailed;
        emit error(m_lastError);
        stop();
    }
}

int QSystemAlignedTimerPrivate::minimumInterval() const
{
    return m_minimumInterval;
}

void QSystemAlignedTimerPrivate::setMinimumInterval(int seconds)
{
    m_minimumInterval = seconds;
}

int QSystemAlignedTimerPrivate::maximumInterval() const
{
    return m_maximumInterval;
}

void QSystemAlignedTimerPrivate::setMaximumInterval(int seconds)
{
    m_maximumInterval = seconds;
}

void QSystemAlignedTimerPrivate::setSingleShot(bool singleShot)
{
    m_singleShot = singleShot;
}

bool QSystemAlignedTimerPrivate::isSingleShot() const
{
    return m_singleShot;
}

void QSystemAlignedTimerPrivate::singleShot(int minimumTime, int maximumTime, QObject *receiver, const char *member)
{
    if (receiver && member) {
        QSystemAlignedTimerPrivate *alignedTimer = new QSystemAlignedTimerPrivate(receiver);

        alignedTimer->m_singleShot = true;

        connect(alignedTimer, SIGNAL(timeout()), receiver, member);
        alignedTimer->start(minimumTime, maximumTime);
    }
}

QSystemAlignedTimer::AlignedTimerError QSystemAlignedTimerPrivate::lastError() const
{
    return m_lastError;
}

void QSystemAlignedTimerPrivate::start(int minimumTime, int maximumTime)
{
    m_minimumInterval = minimumTime;
    m_maximumInterval = maximumTime;

    start();
}

void QSystemAlignedTimerPrivate::start()
{
    if (m_running)
        return;

    if (!(m_iphbdHandler && m_notifier)) {
        m_lastError = QSystemAlignedTimer::InternalError;
        emit error(m_lastError);
        return;
    }

    int mustWait = 0;
    time_t unixTime = iphb_wait(m_iphbdHandler, m_minimumInterval, m_maximumInterval, mustWait);

    if (unixTime == (time_t)-1) {
        m_lastError = QSystemAlignedTimer::TimerFailed;
        emit error(m_lastError);
        return;
    }

    m_notifier->setEnabled(true);
    m_running = true;
    m_lastError = QSystemAlignedTimer::NoError;
}

void QSystemAlignedTimerPrivate::stop()
{
    if (!m_running)
        return;

    if (!(m_iphbdHandler && m_notifier)) {
        m_lastError = QSystemAlignedTimer::InternalError;
        emit error(m_lastError);
        return;
    }

    (void)iphb_discard_wakeups(m_iphbdHandler);

    m_notifier->setEnabled(false);
    m_running = false;
    m_lastError = QSystemAlignedTimer::NoError;
}

void QSystemAlignedTimerPrivate::heartbeatReceived(int sock) {
    Q_UNUSED(sock);

    stop();
    emit timeout();

    if (!m_singleShot)
        start();
}

bool QSystemAlignedTimerPrivate::isActive() const
{
    return m_running;
}

#include "moc_qsystemalignedtimer_meego_p.cpp"

QTM_END_NAMESPACE
<commit_msg>Fix a double free in m_notifier<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsystemalignedtimer.h"
#include "qsystemalignedtimer_meego_p.h"
#include <QDebug>

#include <errno.h>
#include <stdio.h>

QTM_BEGIN_NAMESPACE

QSystemAlignedTimerPrivate::QSystemAlignedTimerPrivate(QObject *parent)
    : QObject(parent)
    , m_lastError(QSystemAlignedTimer::NoError)
    , m_minimumInterval(0)
    , m_maximumInterval(0)
    , m_running(false)
    , m_singleShot(false)
    , m_iphbdHandler(0)
    , m_notifier(0)
{
    m_iphbdHandler = iphb_open(0);

    if (!m_iphbdHandler) {
        m_lastError = QSystemAlignedTimer::InternalError;
        qDebug() << "iphb_open error" << m_iphbdHandler<< errno <<strerror(errno);
        return;
    }

    int sockfd = iphb_get_fd(m_iphbdHandler);
    if (!(sockfd > -1)) {
        m_lastError = QSystemAlignedTimer::InternalError;
        qDebug() << "socket failure"<<strerror(errno);
        return;
    }

    m_notifier = new QSocketNotifier(sockfd, QSocketNotifier::Read);
    if (!QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(heartbeatReceived(int)))) {
        delete m_notifier, m_notifier = 0;
        m_lastError = QSystemAlignedTimer::TimerFailed;
        qDebug() << "timer failure";
        return;
    }
    m_notifier->setEnabled(false);
}

QSystemAlignedTimerPrivate::~QSystemAlignedTimerPrivate()
{
    if (m_iphbdHandler)
        (void)iphb_close(m_iphbdHandler);

    if (m_notifier)
        delete m_notifier;
}

void QSystemAlignedTimerPrivate::wokeUp()
{
    if (m_singleShot) {
        stop();
        return;
    }

    int st = iphb_I_woke_up(m_iphbdHandler);
    if (!(st >= 0)) {
        m_lastError = QSystemAlignedTimer::TimerFailed;
        emit error(m_lastError);
        stop();
    }
}

int QSystemAlignedTimerPrivate::minimumInterval() const
{
    return m_minimumInterval;
}

void QSystemAlignedTimerPrivate::setMinimumInterval(int seconds)
{
    m_minimumInterval = seconds;
}

int QSystemAlignedTimerPrivate::maximumInterval() const
{
    return m_maximumInterval;
}

void QSystemAlignedTimerPrivate::setMaximumInterval(int seconds)
{
    m_maximumInterval = seconds;
}

void QSystemAlignedTimerPrivate::setSingleShot(bool singleShot)
{
    m_singleShot = singleShot;
}

bool QSystemAlignedTimerPrivate::isSingleShot() const
{
    return m_singleShot;
}

void QSystemAlignedTimerPrivate::singleShot(int minimumTime, int maximumTime, QObject *receiver, const char *member)
{
    if (receiver && member) {
        QSystemAlignedTimerPrivate *alignedTimer = new QSystemAlignedTimerPrivate(receiver);

        alignedTimer->m_singleShot = true;

        connect(alignedTimer, SIGNAL(timeout()), receiver, member);
        alignedTimer->start(minimumTime, maximumTime);
    }
}

QSystemAlignedTimer::AlignedTimerError QSystemAlignedTimerPrivate::lastError() const
{
    return m_lastError;
}

void QSystemAlignedTimerPrivate::start(int minimumTime, int maximumTime)
{
    m_minimumInterval = minimumTime;
    m_maximumInterval = maximumTime;

    start();
}

void QSystemAlignedTimerPrivate::start()
{
    if (m_running)
        return;

    if (!(m_iphbdHandler && m_notifier)) {
        m_lastError = QSystemAlignedTimer::InternalError;
        emit error(m_lastError);
        return;
    }

    int mustWait = 0;
    time_t unixTime = iphb_wait(m_iphbdHandler, m_minimumInterval, m_maximumInterval, mustWait);

    if (unixTime == (time_t)-1) {
        m_lastError = QSystemAlignedTimer::TimerFailed;
        emit error(m_lastError);
        return;
    }

    m_notifier->setEnabled(true);
    m_running = true;
    m_lastError = QSystemAlignedTimer::NoError;
}

void QSystemAlignedTimerPrivate::stop()
{
    if (!m_running)
        return;

    if (!(m_iphbdHandler && m_notifier)) {
        m_lastError = QSystemAlignedTimer::InternalError;
        emit error(m_lastError);
        return;
    }

    (void)iphb_discard_wakeups(m_iphbdHandler);

    m_notifier->setEnabled(false);
    m_running = false;
    m_lastError = QSystemAlignedTimer::NoError;
}

void QSystemAlignedTimerPrivate::heartbeatReceived(int sock) {
    Q_UNUSED(sock);

    stop();
    emit timeout();

    if (!m_singleShot)
        start();
}

bool QSystemAlignedTimerPrivate::isActive() const
{
    return m_running;
}

#include "moc_qsystemalignedtimer_meego_p.cpp"

QTM_END_NAMESPACE
<|endoftext|>