<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the config.tests of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandintegration.h"

#include "qwaylanddisplay.h"
#include "qwaylandinputcontext.h"
#include "qwaylandshmbackingstore.h"
#include "qwaylandshmwindow.h"
#include "qwaylandnativeinterface.h"
#include "qwaylandclipboard.h"
#include "qwaylanddnd.h"
#include "qwaylandwindowmanagerintegration.h"

#include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h"
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtPlatformSupport/private/qgenericunixthemes_p.h>

#include <QtGui/private/qguiapplication_p.h>

#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformcursor.h>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>

#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h>
#include <qpa/qplatforminputcontext.h>

#ifdef QT_WAYLAND_GL_SUPPORT
#include "qwaylandglintegration.h"
#endif

QT_BEGIN_NAMESPACE

class GenericWaylandTheme: public QGenericUnixTheme
{
public:
    static QStringList themeNames()
    {
        QStringList result;

        if (QGuiApplication::desktopSettingsAware()) {
            const QByteArray desktopEnvironment = QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment();

            // Ignore X11 desktop environments
            if (!desktopEnvironment.isEmpty() &&
                desktopEnvironment != QByteArrayLiteral("UNKNOWN") &&
                desktopEnvironment != QByteArrayLiteral("KDE") &&
                desktopEnvironment != QByteArrayLiteral("GNOME") &&
                desktopEnvironment != QByteArrayLiteral("UNITY") &&
                desktopEnvironment != QByteArrayLiteral("MATE") &&
                desktopEnvironment != QByteArrayLiteral("XFCE") &&
                desktopEnvironment != QByteArrayLiteral("LXDE"))
                result.push_back(desktopEnvironment.toLower());
        }

        if (result.isEmpty())
            result.push_back(QLatin1String(QGenericUnixTheme::name));

        return result;
    }
};

QWaylandIntegration::QWaylandIntegration()
    : mFontDb(new QGenericUnixFontDatabase())
    , mNativeInterface(new QWaylandNativeInterface(this))
#ifndef QT_NO_ACCESSIBILITY
    , mAccessibility(new QPlatformAccessibility())
#else
    , mAccessibility(0)
#endif
{
    mDisplay = new QWaylandDisplay();
    mClipboard = new QWaylandClipboard(mDisplay);
    mDrag = new QWaylandDrag(mDisplay);

    foreach (QPlatformScreen *screen, mDisplay->screens())
        screenAdded(screen);

    mInputContext.reset(new QWaylandInputContext(mDisplay));
}

QWaylandIntegration::~QWaylandIntegration()
{
    delete mDrag;
    delete mClipboard;
#ifndef QT_NO_ACCESSIBILITY
    delete mAccessibility;
#endif
    delete mNativeInterface;
    delete mDisplay;
}

QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const
{
    return mNativeInterface;
}

bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
    switch (cap) {
    case ThreadedPixmaps: return true;
    case OpenGL:
#ifdef QT_WAYLAND_GL_SUPPORT
        return true;
#else
        return false;
#endif
    case ThreadedOpenGL:
#ifdef QT_WAYLAND_GL_SUPPORT
        return mDisplay->eglIntegration()->supportsThreadedOpenGL();
#else
        return false;
#endif
    case BufferQueueingOpenGL:
        return true;
    default: return QPlatformIntegration::hasCapability(cap);
    }
}

QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    if (window->surfaceType() == QWindow::OpenGLSurface)
        return mDisplay->eglIntegration()->createEglWindow(window);
#endif
    return new QWaylandShmWindow(window);
}

QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    return mDisplay->eglIntegration()->createPlatformOpenGLContext(context->format(), context->shareHandle());
#else
    Q_UNUSED(context);
    return 0;
#endif
}

QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
{
    return new QWaylandShmBackingStore(window);
}

QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
{
    return createUnixEventDispatcher();
}

void QWaylandIntegration::initialize()
{
    QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
    QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay, SLOT(flushRequests()));
}

QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
{
    return mFontDb;
}

QPlatformClipboard *QWaylandIntegration::clipboard() const
{
    return mClipboard;
}

QPlatformDrag *QWaylandIntegration::drag() const
{
    return mDrag;
}

QPlatformInputContext *QWaylandIntegration::inputContext() const
{
    return mInputContext.data();
}

QVariant QWaylandIntegration::styleHint(StyleHint hint) const
{
    if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration())
        return mDisplay->windowManagerIntegration()->showIsFullScreen();

    return QPlatformIntegration::styleHint(hint);
}

QPlatformAccessibility *QWaylandIntegration::accessibility() const
{
    return mAccessibility;
}

QPlatformServices *QWaylandIntegration::services() const
{
    return mDisplay->windowManagerIntegration();
}

QWaylandDisplay *QWaylandIntegration::display() const
{
    return mDisplay;
}

QStringList QWaylandIntegration::themeNames() const
{
    return GenericWaylandTheme::themeNames();
}

QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) const
{
    return GenericWaylandTheme::createUnixTheme(name);
}

QT_END_NAMESPACE
<commit_msg>Wayland supports multiple windows.<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the config.tests of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandintegration.h"

#include "qwaylanddisplay.h"
#include "qwaylandinputcontext.h"
#include "qwaylandshmbackingstore.h"
#include "qwaylandshmwindow.h"
#include "qwaylandnativeinterface.h"
#include "qwaylandclipboard.h"
#include "qwaylanddnd.h"
#include "qwaylandwindowmanagerintegration.h"

#include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h"
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtPlatformSupport/private/qgenericunixthemes_p.h>

#include <QtGui/private/qguiapplication_p.h>

#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformcursor.h>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>

#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h>
#include <qpa/qplatforminputcontext.h>

#ifdef QT_WAYLAND_GL_SUPPORT
#include "qwaylandglintegration.h"
#endif

QT_BEGIN_NAMESPACE

class GenericWaylandTheme: public QGenericUnixTheme
{
public:
    static QStringList themeNames()
    {
        QStringList result;

        if (QGuiApplication::desktopSettingsAware()) {
            const QByteArray desktopEnvironment = QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment();

            // Ignore X11 desktop environments
            if (!desktopEnvironment.isEmpty() &&
                desktopEnvironment != QByteArrayLiteral("UNKNOWN") &&
                desktopEnvironment != QByteArrayLiteral("KDE") &&
                desktopEnvironment != QByteArrayLiteral("GNOME") &&
                desktopEnvironment != QByteArrayLiteral("UNITY") &&
                desktopEnvironment != QByteArrayLiteral("MATE") &&
                desktopEnvironment != QByteArrayLiteral("XFCE") &&
                desktopEnvironment != QByteArrayLiteral("LXDE"))
                result.push_back(desktopEnvironment.toLower());
        }

        if (result.isEmpty())
            result.push_back(QLatin1String(QGenericUnixTheme::name));

        return result;
    }
};

QWaylandIntegration::QWaylandIntegration()
    : mFontDb(new QGenericUnixFontDatabase())
    , mNativeInterface(new QWaylandNativeInterface(this))
#ifndef QT_NO_ACCESSIBILITY
    , mAccessibility(new QPlatformAccessibility())
#else
    , mAccessibility(0)
#endif
{
    mDisplay = new QWaylandDisplay();
    mClipboard = new QWaylandClipboard(mDisplay);
    mDrag = new QWaylandDrag(mDisplay);

    foreach (QPlatformScreen *screen, mDisplay->screens())
        screenAdded(screen);

    mInputContext.reset(new QWaylandInputContext(mDisplay));
}

QWaylandIntegration::~QWaylandIntegration()
{
    delete mDrag;
    delete mClipboard;
#ifndef QT_NO_ACCESSIBILITY
    delete mAccessibility;
#endif
    delete mNativeInterface;
    delete mDisplay;
}

QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const
{
    return mNativeInterface;
}

bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
    switch (cap) {
    case ThreadedPixmaps: return true;
    case OpenGL:
#ifdef QT_WAYLAND_GL_SUPPORT
        return true;
#else
        return false;
#endif
    case ThreadedOpenGL:
#ifdef QT_WAYLAND_GL_SUPPORT
        return mDisplay->eglIntegration()->supportsThreadedOpenGL();
#else
        return false;
#endif
    case BufferQueueingOpenGL:
        return true;
    case MultipleWindows:
    case NonFullScreenWindows:
        return true;
    default: return QPlatformIntegration::hasCapability(cap);
    }
}

QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    if (window->surfaceType() == QWindow::OpenGLSurface)
        return mDisplay->eglIntegration()->createEglWindow(window);
#endif
    return new QWaylandShmWindow(window);
}

QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    return mDisplay->eglIntegration()->createPlatformOpenGLContext(context->format(), context->shareHandle());
#else
    Q_UNUSED(context);
    return 0;
#endif
}

QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
{
    return new QWaylandShmBackingStore(window);
}

QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
{
    return createUnixEventDispatcher();
}

void QWaylandIntegration::initialize()
{
    QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
    QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay, SLOT(flushRequests()));
}

QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
{
    return mFontDb;
}

QPlatformClipboard *QWaylandIntegration::clipboard() const
{
    return mClipboard;
}

QPlatformDrag *QWaylandIntegration::drag() const
{
    return mDrag;
}

QPlatformInputContext *QWaylandIntegration::inputContext() const
{
    return mInputContext.data();
}

QVariant QWaylandIntegration::styleHint(StyleHint hint) const
{
    if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration())
        return mDisplay->windowManagerIntegration()->showIsFullScreen();

    return QPlatformIntegration::styleHint(hint);
}

QPlatformAccessibility *QWaylandIntegration::accessibility() const
{
    return mAccessibility;
}

QPlatformServices *QWaylandIntegration::services() const
{
    return mDisplay->windowManagerIntegration();
}

QWaylandDisplay *QWaylandIntegration::display() const
{
    return mDisplay;
}

QStringList QWaylandIntegration::themeNames() const
{
    return GenericWaylandTheme::themeNames();
}

QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) const
{
    return GenericWaylandTheme::createUnixTheme(name);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>// Copyright (c) 2012 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.

#include "chrome/browser/autofill/autofill_popup_view.h"

#include "base/memory/scoped_ptr.h"
#include "chrome/browser/autofill/test_autofill_external_delegate.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "content/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::AtLeast;
using testing::_;

namespace {

class MockAutofillExternalDelegate : public TestAutofillExternalDelegate {
 public:
  MockAutofillExternalDelegate() : TestAutofillExternalDelegate(NULL, NULL) {}
  ~MockAutofillExternalDelegate() {}

  virtual void SelectAutofillSuggestionAtIndex(int unique_id, int list_index)
      OVERRIDE {}
};

class TestAutofillPopupView : public AutofillPopupView {
 public:
  explicit TestAutofillPopupView(
      content::WebContents* web_contents,
      AutofillExternalDelegate* autofill_external_delegate)
      : AutofillPopupView(web_contents, autofill_external_delegate) {}
  virtual ~TestAutofillPopupView() {}

  MOCK_METHOD0(Hide, void());

  MOCK_METHOD1(InvalidateRow, void(size_t));

  void SetSelectedLine(size_t selected_line) {
    AutofillPopupView::SetSelectedLine(selected_line);
  }

 protected:
  virtual void ShowInternal() OVERRIDE {}

  virtual void HideInternal() OVERRIDE {}
};

}  // namespace

class AutofillPopupViewBrowserTest : public InProcessBrowserTest {
 public:
  AutofillPopupViewBrowserTest() {}
  virtual ~AutofillPopupViewBrowserTest() {}

  virtual void SetUpOnMainThread() OVERRIDE {
    web_contents_ = browser()->GetSelectedWebContents();
    ASSERT_TRUE(web_contents_ != NULL);

    autofill_popup_view_.reset(new TestAutofillPopupView(
        web_contents_,
        &autofill_external_delegate_));
  }

 protected:
  content::WebContents* web_contents_;
  scoped_ptr<TestAutofillPopupView> autofill_popup_view_;
  MockAutofillExternalDelegate autofill_external_delegate_;
};

IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
                       SwitchTabAndHideAutofillPopup) {
  EXPECT_CALL(*autofill_popup_view_, Hide()).Times(AtLeast(1));

  ui_test_utils::WindowedNotificationObserver observer(
      content::NOTIFICATION_WEB_CONTENTS_HIDDEN,
      content::Source<content::WebContents>(web_contents_));
  browser()->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
                                   content::PAGE_TRANSITION_START_PAGE);
  observer.Wait();

  // The mock verifies that the call was made.
}

IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
                       FLAKY_TestPageNavigationHidingAutofillPopup) {
  EXPECT_CALL(*autofill_popup_view_, Hide()).Times(AtLeast(1));

  ui_test_utils::WindowedNotificationObserver observer(
      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
      content::Source<content::NavigationController>(
          &(web_contents_->GetController())));
  browser()->OpenURL(content::OpenURLParams(
      GURL(chrome::kAboutBlankURL), content::Referrer(),
      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
  browser()->OpenURL(content::OpenURLParams(
      GURL(chrome::kChromeUICrashURL), content::Referrer(),
      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
  observer.Wait();

  // The mock verifies that the call was made.
}

IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
                       SetSelectedAutofillLineAndCallInvalidate) {
  std::vector<string16> autofill_values;
  autofill_values.push_back(string16());
  std::vector<int> autofill_ids;
  autofill_ids.push_back(0);
  autofill_popup_view_->Show(
      autofill_values, autofill_values, autofill_values, autofill_ids, 0);

  // Make sure that when a new line is selected, it is invalidated so it can
  // be updated to show it is selected.
  int selected_line = 0;
  EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line));
  autofill_popup_view_->SetSelectedLine(selected_line);

  // Ensure that the row isn't invalidated if it didn't change.
  EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line)).Times(0);
  autofill_popup_view_->SetSelectedLine(selected_line);

  // Change back to no selection.
  EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line));
  autofill_popup_view_->SetSelectedLine(-1);
}
<commit_msg>Fix Flaky TestPageNavigateHidingAutofillPopup<commit_after>// Copyright (c) 2012 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.

#include "chrome/browser/autofill/autofill_popup_view.h"

#include "base/memory/scoped_ptr.h"
#include "chrome/browser/autofill/test_autofill_external_delegate.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "content/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::AtLeast;
using testing::_;

namespace {

class MockAutofillExternalDelegate : public TestAutofillExternalDelegate {
 public:
  MockAutofillExternalDelegate() : TestAutofillExternalDelegate(NULL, NULL) {}
  ~MockAutofillExternalDelegate() {}

  virtual void SelectAutofillSuggestionAtIndex(int unique_id, int list_index)
      OVERRIDE {}
};

class TestAutofillPopupView : public AutofillPopupView {
 public:
  explicit TestAutofillPopupView(
      content::WebContents* web_contents,
      AutofillExternalDelegate* autofill_external_delegate)
      : AutofillPopupView(web_contents, autofill_external_delegate) {}
  virtual ~TestAutofillPopupView() {}

  MOCK_METHOD0(Hide, void());

  MOCK_METHOD1(InvalidateRow, void(size_t));

  void SetSelectedLine(size_t selected_line) {
    AutofillPopupView::SetSelectedLine(selected_line);
  }

 protected:
  virtual void ShowInternal() OVERRIDE {}

  virtual void HideInternal() OVERRIDE {}
};

}  // namespace

class AutofillPopupViewBrowserTest : public InProcessBrowserTest {
 public:
  AutofillPopupViewBrowserTest() {}
  virtual ~AutofillPopupViewBrowserTest() {}

  virtual void SetUpOnMainThread() OVERRIDE {
    web_contents_ = browser()->GetSelectedWebContents();
    ASSERT_TRUE(web_contents_ != NULL);

    autofill_popup_view_.reset(new TestAutofillPopupView(
        web_contents_,
        &autofill_external_delegate_));
  }

 protected:
  content::WebContents* web_contents_;
  scoped_ptr<TestAutofillPopupView> autofill_popup_view_;
  MockAutofillExternalDelegate autofill_external_delegate_;
};

IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
                       SwitchTabAndHideAutofillPopup) {
  EXPECT_CALL(*autofill_popup_view_, Hide()).Times(AtLeast(1));

  ui_test_utils::WindowedNotificationObserver observer(
      content::NOTIFICATION_WEB_CONTENTS_HIDDEN,
      content::Source<content::WebContents>(web_contents_));
  browser()->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
                                   content::PAGE_TRANSITION_START_PAGE);
  observer.Wait();

  // The mock verifies that the call was made.
}

IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
                       FLAKY_TestPageNavigationHidingAutofillPopup) {
  EXPECT_CALL(*autofill_popup_view_, Hide()).Times(AtLeast(1));

  ui_test_utils::WindowedNotificationObserver observer(
      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
      content::Source<content::NavigationController>(
          &(web_contents_->GetController())));
  browser()->OpenURL(content::OpenURLParams(
      GURL(chrome::kAboutBlankURL), content::Referrer(),
      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
  browser()->OpenURL(content::OpenURLParams(
      GURL(chrome::kChromeUIAboutURL), content::Referrer(),
      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
  observer.Wait();

  // The mock verifies that the call was made.
}

IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
                       SetSelectedAutofillLineAndCallInvalidate) {
  std::vector<string16> autofill_values;
  autofill_values.push_back(string16());
  std::vector<int> autofill_ids;
  autofill_ids.push_back(0);
  autofill_popup_view_->Show(
      autofill_values, autofill_values, autofill_values, autofill_ids, 0);

  // Make sure that when a new line is selected, it is invalidated so it can
  // be updated to show it is selected.
  int selected_line = 0;
  EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line));
  autofill_popup_view_->SetSelectedLine(selected_line);

  // Ensure that the row isn't invalidated if it didn't change.
  EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line)).Times(0);
  autofill_popup_view_->SetSelectedLine(selected_line);

  // Change back to no selection.
  EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line));
  autofill_popup_view_->SetSelectedLine(-1);
}
<|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.

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/protector/base_setting_change.h"
#include "chrome/browser/protector/histograms.h"
#include "chrome/browser/protector/protector.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/search_engines/template_url_service_observer.h"
#include "chrome/browser/webdata/keyword_table.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "googleurl/src/gurl.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace protector {

namespace {

// Maximum length of the search engine name to be displayed.
const size_t kMaxDisplayedNameLength = 10;

// Matches TemplateURL with all fields set from the prepopulated data equal
// to fields in another TemplateURL.
class TemplateURLIsSame {
 public:
  // Creates a matcher based on |other|.
  explicit TemplateURLIsSame(const TemplateURL* other) : other_(other) {
  }

  // Returns true if both |other| and |url| are NULL or have same field values.
  bool operator()(const TemplateURL* url) {
    if (url == other_ )
      return true;
    if (!url || !other_)
      return false;
    return url->short_name() == other_->short_name() &&
        AreKeywordsSame(url, other_) &&
        TemplateURLRef::SameUrlRefs(url->url(), other_->url()) &&
        TemplateURLRef::SameUrlRefs(url->suggestions_url(),
                                    other_->suggestions_url()) &&
        TemplateURLRef::SameUrlRefs(url->instant_url(),
                                    other_->instant_url()) &&
        url->GetFaviconURL() == other_->GetFaviconURL() &&
        url->safe_for_autoreplace() == other_->safe_for_autoreplace() &&
        url->show_in_default_list() == other_->show_in_default_list() &&
        url->input_encodings() == other_->input_encodings() &&
        url->prepopulate_id() == other_->prepopulate_id();
  }

 private:
  // Returns true if both |url1| and |url2| have autogenerated keywords
  // or if their keywords are identical.
  bool AreKeywordsSame(const TemplateURL* url1, const TemplateURL* url2) {
    return (url1->autogenerate_keyword() && url2->autogenerate_keyword()) ||
        url1->keyword() == url2->keyword();
  }

  const TemplateURL* other_;
};

}  // namespace

// Default search engine change tracked by Protector.
class DefaultSearchProviderChange : public BaseSettingChange,
                                    public TemplateURLServiceObserver,
                                    public content::NotificationObserver {
 public:
  DefaultSearchProviderChange(const TemplateURL* new_search_provider,
                              TemplateURL* backup_search_provider);

  // BaseSettingChange overrides:
  virtual bool Init(Protector* protector) OVERRIDE;
  virtual void Apply() OVERRIDE;
  virtual void Discard() OVERRIDE;
  virtual void Timeout() OVERRIDE;
  virtual void OnBeforeRemoved() OVERRIDE;
  virtual int GetBadgeIconID() const OVERRIDE;
  virtual int GetMenuItemIconID() const OVERRIDE;
  virtual int GetBubbleIconID() const OVERRIDE;
  virtual string16 GetBubbleTitle() const OVERRIDE;
  virtual string16 GetBubbleMessage() const OVERRIDE;
  virtual string16 GetApplyButtonText() const OVERRIDE;
  virtual string16 GetDiscardButtonText() const OVERRIDE;

 private:
  virtual ~DefaultSearchProviderChange();

  // TemplateURLServiceObserver overrides:
  virtual void OnTemplateURLServiceChanged() OVERRIDE;

  // content::NotificationObserver overrides:
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // Sets the default search provider to |*search_provider|. If a matching
  // TemplateURL already exists, it is reused and |*search_provider| is reset.
  // Otherwise, adds |*search_provider| to keywords and releases it.
  // In both cases, |*search_provider| is NULL after this call.
  // Returns the new default search provider (either |*search_provider| or the
  // reused TemplateURL).
  const TemplateURL* SetDefaultSearchProvider(
      scoped_ptr<TemplateURL>* search_provider);

  // Opens the Search engine settings page in a new tab.
  void OpenSearchEngineSettings();

  // Returns the TemplateURLService instance for the Profile this change is
  // related to.
  TemplateURLService* GetTemplateURLService();

  // Stops observing the TemplateURLService changes.
  void StopObservingTemplateURLService();

  // Histogram ID of the new search provider.
  int new_histogram_id_;
  // Indicates that the default search was restored to the prepopulated default
  // search engines.
  bool is_fallback_;
  // Indicates that the the prepopulated default search is the same as
  // |new_search_provider_|.
  bool fallback_is_new_;
  // ID of |new_search_provider_|.
  TemplateURLID new_id_;
  // The default search at the moment the change was detected. Will be used to
  // restore the new default search back if Apply is called. Will be set to
  // |NULL| if removed from the TemplateURLService.
  const TemplateURL* new_search_provider_;
  // Default search provider set by Init for the period until user makes a
  // choice and either Apply or Discard is performed. Never is |NULL| during
  // that period since the change will dismiss itself if this provider gets
  // deleted or stops being the default.
  const TemplateURL* default_search_provider_;
  // Stores backup of the default search until it becomes owned by the
  // TemplateURLService or deleted.
  scoped_ptr<TemplateURL> backup_search_provider_;
  content::NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(DefaultSearchProviderChange);
};

DefaultSearchProviderChange::DefaultSearchProviderChange(
    const TemplateURL* new_search_provider,
    TemplateURL* backup_search_provider)
    : new_histogram_id_(GetSearchProviderHistogramID(new_search_provider)),
      is_fallback_(false),
      fallback_is_new_(false),
      new_search_provider_(new_search_provider),
      default_search_provider_(NULL),
      backup_search_provider_(backup_search_provider) {
}

DefaultSearchProviderChange::~DefaultSearchProviderChange() {
}

bool DefaultSearchProviderChange::Init(Protector* protector) {
  if (!BaseSettingChange::Init(protector))
    return false;

  if (backup_search_provider_.get()) {
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderHijacked,
        new_histogram_id_,
        kProtectorMaxSearchProviderID);
  } else {
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderCorrupt,
        new_histogram_id_,
        kProtectorMaxSearchProviderID);
    // Fallback to a prepopulated default search provider, ignoring any
    // overrides in Prefs.
    backup_search_provider_.reset(
        TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
    is_fallback_ = true;
    VLOG(1) << "Fallback search provider: "
            << backup_search_provider_->short_name();
  }

  default_search_provider_ = SetDefaultSearchProvider(&backup_search_provider_);
  DCHECK(default_search_provider_);
  // |backup_search_provider_| should be |NULL| since now.
  DCHECK(!backup_search_provider_.get());
  if (is_fallback_ && default_search_provider_ == new_search_provider_)
    fallback_is_new_ = true;

  int restored_histogram_id =
      GetSearchProviderHistogramID(default_search_provider_);
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderRestored,
      restored_histogram_id,
      kProtectorMaxSearchProviderID);

  if (is_fallback_) {
    VLOG(1) << "Fallback to search provider: "
            << default_search_provider_->short_name();
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderFallback,
        restored_histogram_id,
        kProtectorMaxSearchProviderID);
  }

  // Listen for the default search provider changes.
  GetTemplateURLService()->AddObserver(this);

  if (new_search_provider_) {
    // Listen for removal of |new_search_provider_|.
    new_id_ = new_search_provider_->id();
    registrar_.Add(
        this, chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
        content::Source<Profile>(protector->profile()->GetOriginalProfile()));
  }

  return true;
}

void DefaultSearchProviderChange::Apply() {
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderApplied,
      new_histogram_id_,
      kProtectorMaxSearchProviderID);

  StopObservingTemplateURLService();
  if (new_search_provider_) {
    GetTemplateURLService()->SetDefaultSearchProvider(new_search_provider_);
  } else {
    // Open settings page in case the new setting is invalid.
    OpenSearchEngineSettings();
  }
}

void DefaultSearchProviderChange::Discard() {
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderDiscarded,
      new_histogram_id_,
      kProtectorMaxSearchProviderID);

  StopObservingTemplateURLService();
  if (is_fallback_) {
    // Open settings page in case the old setting is invalid.
    OpenSearchEngineSettings();
  }
  // Nothing to do otherwise since we have already set the search engine
  // to |old_id_| in |Init|.
}

void DefaultSearchProviderChange::Timeout() {
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderTimeout,
      new_histogram_id_,
      kProtectorMaxSearchProviderID);
}

void DefaultSearchProviderChange::OnBeforeRemoved() {
  StopObservingTemplateURLService();
}

int DefaultSearchProviderChange::GetBadgeIconID() const {
  return IDR_SEARCH_ENGINE_CHANGE_BADGE;
}

int DefaultSearchProviderChange::GetMenuItemIconID() const {
  return IDR_SEARCH_ENGINE_CHANGE_MENU;
}

int DefaultSearchProviderChange::GetBubbleIconID() const {
  return IDR_SEARCH_ENGINE_CHANGE_ALERT;
}

string16 DefaultSearchProviderChange::GetBubbleTitle() const {
  return l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_CHANGE_TITLE);
}

string16 DefaultSearchProviderChange::GetBubbleMessage() const {
  if (!is_fallback_) {
    return l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_CHANGE_MESSAGE);
  } else {
    return l10n_util::GetStringFUTF16(
        IDS_SEARCH_ENGINE_CHANGE_NO_BACKUP_MESSAGE,
        default_search_provider_->short_name());
  }
}

string16 DefaultSearchProviderChange::GetApplyButtonText() const {
  if (new_search_provider_) {
    // If backup search engine is lost and fallback was made to the current
    // search provider then there is no need to show this button.
    if (fallback_is_new_)
      return string16();
    string16 name = new_search_provider_->short_name();
    if (name.length() > kMaxDisplayedNameLength)
      return l10n_util::GetStringUTF16(IDS_CHANGE_SEARCH_ENGINE_NO_NAME);
    else
      return l10n_util::GetStringFUTF16(IDS_CHANGE_SEARCH_ENGINE, name);
  } else if (!is_fallback_) {
    // New setting is lost, offer to go to settings.
    return l10n_util::GetStringUTF16(IDS_SELECT_SEARCH_ENGINE);
  } else {
    // Both settings are lost: don't show this button.
    return string16();
  }
}

string16 DefaultSearchProviderChange::GetDiscardButtonText() const {
  if (!is_fallback_) {
    string16 name = default_search_provider_->short_name();
    if (name.length() > kMaxDisplayedNameLength)
      return l10n_util::GetStringUTF16(IDS_KEEP_SETTING);
    else
      return l10n_util::GetStringFUTF16(IDS_KEEP_SEARCH_ENGINE, name);
  } else {
    // Old setting is lost, offer to go to settings.
    return l10n_util::GetStringUTF16(IDS_SELECT_SEARCH_ENGINE);
  }
}

void DefaultSearchProviderChange::OnTemplateURLServiceChanged() {
  TemplateURLService* url_service = GetTemplateURLService();
  if (url_service->GetDefaultSearchProvider() != default_search_provider_) {
    VLOG(1) << "Default search provider has been changed by user";
    default_search_provider_ = NULL;
    url_service->RemoveObserver(this);
    // This will delete the Protector instance and |this|.
    protector()->DismissChange();
  }
}

void DefaultSearchProviderChange::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK(type == chrome::NOTIFICATION_TEMPLATE_URL_REMOVED);
  TemplateURLID id = *content::Details<TemplateURLID>(details).ptr();
  if (id == new_id_)
    new_search_provider_ = NULL;
  registrar_.Remove(this, type, source);
  // TODO(ivankr): should the change be dismissed as well? Probably not,
  // since this may happend due to Sync or whatever. In that case, if user
  // clicks on 'Change to...', the Search engine settings page will be opened.
}

const TemplateURL* DefaultSearchProviderChange::SetDefaultSearchProvider(
    scoped_ptr<TemplateURL>* search_provider) {
  TemplateURLService* url_service = GetTemplateURLService();
  TemplateURLService::TemplateURLVector urls = url_service->GetTemplateURLs();
  const TemplateURL* new_default_provider = NULL;

  // Check if this provider already exists and add it otherwise.
  TemplateURLService::TemplateURLVector::const_iterator i =
      find_if(urls.begin(), urls.end(),
              TemplateURLIsSame(search_provider->get()));
  if (i != urls.end()) {
    VLOG(1) << "Provider already exists";
    new_default_provider = *i;
    search_provider->reset();
  } else {
    VLOG(1) << "No match, adding new provider";
    new_default_provider = search_provider->get();
    url_service->Add(search_provider->release());
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderMissing,
        GetSearchProviderHistogramID(new_default_provider),
        kProtectorMaxSearchProviderID);
  }

  // TODO(ivankr): handle keyword conflicts with existing providers.
  DCHECK(new_default_provider);
  VLOG(1) << "Default search provider set to: "
          << new_default_provider->short_name();
  url_service->SetDefaultSearchProvider(new_default_provider);
  return new_default_provider;
}

void DefaultSearchProviderChange::OpenSearchEngineSettings() {
  protector()->OpenTab(
      GURL(std::string(chrome::kChromeUISettingsURL) +
           chrome::kSearchEnginesSubPage));
}

TemplateURLService* DefaultSearchProviderChange::GetTemplateURLService() {
  TemplateURLService* url_service =
      TemplateURLServiceFactory::GetForProfile(protector()->profile());
  DCHECK(url_service);
  return url_service;
}

void DefaultSearchProviderChange::StopObservingTemplateURLService() {
  GetTemplateURLService()->RemoveObserver(this);
}

BaseSettingChange* CreateDefaultSearchProviderChange(
    const TemplateURL* actual,
    TemplateURL* backup) {
  return new DefaultSearchProviderChange(actual, backup);
}

}  // namespace protector
<commit_msg>Add missing std namespace for find_if() in default_search_provider_change.cc<commit_after>// Copyright (c) 2012 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.

#include <algorithm>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/protector/base_setting_change.h"
#include "chrome/browser/protector/histograms.h"
#include "chrome/browser/protector/protector.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/search_engines/template_url_service_observer.h"
#include "chrome/browser/webdata/keyword_table.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "googleurl/src/gurl.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace protector {

namespace {

// Maximum length of the search engine name to be displayed.
const size_t kMaxDisplayedNameLength = 10;

// Matches TemplateURL with all fields set from the prepopulated data equal
// to fields in another TemplateURL.
class TemplateURLIsSame {
 public:
  // Creates a matcher based on |other|.
  explicit TemplateURLIsSame(const TemplateURL* other) : other_(other) {
  }

  // Returns true if both |other| and |url| are NULL or have same field values.
  bool operator()(const TemplateURL* url) {
    if (url == other_ )
      return true;
    if (!url || !other_)
      return false;
    return url->short_name() == other_->short_name() &&
        AreKeywordsSame(url, other_) &&
        TemplateURLRef::SameUrlRefs(url->url(), other_->url()) &&
        TemplateURLRef::SameUrlRefs(url->suggestions_url(),
                                    other_->suggestions_url()) &&
        TemplateURLRef::SameUrlRefs(url->instant_url(),
                                    other_->instant_url()) &&
        url->GetFaviconURL() == other_->GetFaviconURL() &&
        url->safe_for_autoreplace() == other_->safe_for_autoreplace() &&
        url->show_in_default_list() == other_->show_in_default_list() &&
        url->input_encodings() == other_->input_encodings() &&
        url->prepopulate_id() == other_->prepopulate_id();
  }

 private:
  // Returns true if both |url1| and |url2| have autogenerated keywords
  // or if their keywords are identical.
  bool AreKeywordsSame(const TemplateURL* url1, const TemplateURL* url2) {
    return (url1->autogenerate_keyword() && url2->autogenerate_keyword()) ||
        url1->keyword() == url2->keyword();
  }

  const TemplateURL* other_;
};

}  // namespace

// Default search engine change tracked by Protector.
class DefaultSearchProviderChange : public BaseSettingChange,
                                    public TemplateURLServiceObserver,
                                    public content::NotificationObserver {
 public:
  DefaultSearchProviderChange(const TemplateURL* new_search_provider,
                              TemplateURL* backup_search_provider);

  // BaseSettingChange overrides:
  virtual bool Init(Protector* protector) OVERRIDE;
  virtual void Apply() OVERRIDE;
  virtual void Discard() OVERRIDE;
  virtual void Timeout() OVERRIDE;
  virtual void OnBeforeRemoved() OVERRIDE;
  virtual int GetBadgeIconID() const OVERRIDE;
  virtual int GetMenuItemIconID() const OVERRIDE;
  virtual int GetBubbleIconID() const OVERRIDE;
  virtual string16 GetBubbleTitle() const OVERRIDE;
  virtual string16 GetBubbleMessage() const OVERRIDE;
  virtual string16 GetApplyButtonText() const OVERRIDE;
  virtual string16 GetDiscardButtonText() const OVERRIDE;

 private:
  virtual ~DefaultSearchProviderChange();

  // TemplateURLServiceObserver overrides:
  virtual void OnTemplateURLServiceChanged() OVERRIDE;

  // content::NotificationObserver overrides:
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // Sets the default search provider to |*search_provider|. If a matching
  // TemplateURL already exists, it is reused and |*search_provider| is reset.
  // Otherwise, adds |*search_provider| to keywords and releases it.
  // In both cases, |*search_provider| is NULL after this call.
  // Returns the new default search provider (either |*search_provider| or the
  // reused TemplateURL).
  const TemplateURL* SetDefaultSearchProvider(
      scoped_ptr<TemplateURL>* search_provider);

  // Opens the Search engine settings page in a new tab.
  void OpenSearchEngineSettings();

  // Returns the TemplateURLService instance for the Profile this change is
  // related to.
  TemplateURLService* GetTemplateURLService();

  // Stops observing the TemplateURLService changes.
  void StopObservingTemplateURLService();

  // Histogram ID of the new search provider.
  int new_histogram_id_;
  // Indicates that the default search was restored to the prepopulated default
  // search engines.
  bool is_fallback_;
  // Indicates that the the prepopulated default search is the same as
  // |new_search_provider_|.
  bool fallback_is_new_;
  // ID of |new_search_provider_|.
  TemplateURLID new_id_;
  // The default search at the moment the change was detected. Will be used to
  // restore the new default search back if Apply is called. Will be set to
  // |NULL| if removed from the TemplateURLService.
  const TemplateURL* new_search_provider_;
  // Default search provider set by Init for the period until user makes a
  // choice and either Apply or Discard is performed. Never is |NULL| during
  // that period since the change will dismiss itself if this provider gets
  // deleted or stops being the default.
  const TemplateURL* default_search_provider_;
  // Stores backup of the default search until it becomes owned by the
  // TemplateURLService or deleted.
  scoped_ptr<TemplateURL> backup_search_provider_;
  content::NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(DefaultSearchProviderChange);
};

DefaultSearchProviderChange::DefaultSearchProviderChange(
    const TemplateURL* new_search_provider,
    TemplateURL* backup_search_provider)
    : new_histogram_id_(GetSearchProviderHistogramID(new_search_provider)),
      is_fallback_(false),
      fallback_is_new_(false),
      new_search_provider_(new_search_provider),
      default_search_provider_(NULL),
      backup_search_provider_(backup_search_provider) {
}

DefaultSearchProviderChange::~DefaultSearchProviderChange() {
}

bool DefaultSearchProviderChange::Init(Protector* protector) {
  if (!BaseSettingChange::Init(protector))
    return false;

  if (backup_search_provider_.get()) {
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderHijacked,
        new_histogram_id_,
        kProtectorMaxSearchProviderID);
  } else {
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderCorrupt,
        new_histogram_id_,
        kProtectorMaxSearchProviderID);
    // Fallback to a prepopulated default search provider, ignoring any
    // overrides in Prefs.
    backup_search_provider_.reset(
        TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
    is_fallback_ = true;
    VLOG(1) << "Fallback search provider: "
            << backup_search_provider_->short_name();
  }

  default_search_provider_ = SetDefaultSearchProvider(&backup_search_provider_);
  DCHECK(default_search_provider_);
  // |backup_search_provider_| should be |NULL| since now.
  DCHECK(!backup_search_provider_.get());
  if (is_fallback_ && default_search_provider_ == new_search_provider_)
    fallback_is_new_ = true;

  int restored_histogram_id =
      GetSearchProviderHistogramID(default_search_provider_);
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderRestored,
      restored_histogram_id,
      kProtectorMaxSearchProviderID);

  if (is_fallback_) {
    VLOG(1) << "Fallback to search provider: "
            << default_search_provider_->short_name();
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderFallback,
        restored_histogram_id,
        kProtectorMaxSearchProviderID);
  }

  // Listen for the default search provider changes.
  GetTemplateURLService()->AddObserver(this);

  if (new_search_provider_) {
    // Listen for removal of |new_search_provider_|.
    new_id_ = new_search_provider_->id();
    registrar_.Add(
        this, chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
        content::Source<Profile>(protector->profile()->GetOriginalProfile()));
  }

  return true;
}

void DefaultSearchProviderChange::Apply() {
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderApplied,
      new_histogram_id_,
      kProtectorMaxSearchProviderID);

  StopObservingTemplateURLService();
  if (new_search_provider_) {
    GetTemplateURLService()->SetDefaultSearchProvider(new_search_provider_);
  } else {
    // Open settings page in case the new setting is invalid.
    OpenSearchEngineSettings();
  }
}

void DefaultSearchProviderChange::Discard() {
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderDiscarded,
      new_histogram_id_,
      kProtectorMaxSearchProviderID);

  StopObservingTemplateURLService();
  if (is_fallback_) {
    // Open settings page in case the old setting is invalid.
    OpenSearchEngineSettings();
  }
  // Nothing to do otherwise since we have already set the search engine
  // to |old_id_| in |Init|.
}

void DefaultSearchProviderChange::Timeout() {
  UMA_HISTOGRAM_ENUMERATION(
      kProtectorHistogramSearchProviderTimeout,
      new_histogram_id_,
      kProtectorMaxSearchProviderID);
}

void DefaultSearchProviderChange::OnBeforeRemoved() {
  StopObservingTemplateURLService();
}

int DefaultSearchProviderChange::GetBadgeIconID() const {
  return IDR_SEARCH_ENGINE_CHANGE_BADGE;
}

int DefaultSearchProviderChange::GetMenuItemIconID() const {
  return IDR_SEARCH_ENGINE_CHANGE_MENU;
}

int DefaultSearchProviderChange::GetBubbleIconID() const {
  return IDR_SEARCH_ENGINE_CHANGE_ALERT;
}

string16 DefaultSearchProviderChange::GetBubbleTitle() const {
  return l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_CHANGE_TITLE);
}

string16 DefaultSearchProviderChange::GetBubbleMessage() const {
  if (!is_fallback_) {
    return l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_CHANGE_MESSAGE);
  } else {
    return l10n_util::GetStringFUTF16(
        IDS_SEARCH_ENGINE_CHANGE_NO_BACKUP_MESSAGE,
        default_search_provider_->short_name());
  }
}

string16 DefaultSearchProviderChange::GetApplyButtonText() const {
  if (new_search_provider_) {
    // If backup search engine is lost and fallback was made to the current
    // search provider then there is no need to show this button.
    if (fallback_is_new_)
      return string16();
    string16 name = new_search_provider_->short_name();
    if (name.length() > kMaxDisplayedNameLength)
      return l10n_util::GetStringUTF16(IDS_CHANGE_SEARCH_ENGINE_NO_NAME);
    else
      return l10n_util::GetStringFUTF16(IDS_CHANGE_SEARCH_ENGINE, name);
  } else if (!is_fallback_) {
    // New setting is lost, offer to go to settings.
    return l10n_util::GetStringUTF16(IDS_SELECT_SEARCH_ENGINE);
  } else {
    // Both settings are lost: don't show this button.
    return string16();
  }
}

string16 DefaultSearchProviderChange::GetDiscardButtonText() const {
  if (!is_fallback_) {
    string16 name = default_search_provider_->short_name();
    if (name.length() > kMaxDisplayedNameLength)
      return l10n_util::GetStringUTF16(IDS_KEEP_SETTING);
    else
      return l10n_util::GetStringFUTF16(IDS_KEEP_SEARCH_ENGINE, name);
  } else {
    // Old setting is lost, offer to go to settings.
    return l10n_util::GetStringUTF16(IDS_SELECT_SEARCH_ENGINE);
  }
}

void DefaultSearchProviderChange::OnTemplateURLServiceChanged() {
  TemplateURLService* url_service = GetTemplateURLService();
  if (url_service->GetDefaultSearchProvider() != default_search_provider_) {
    VLOG(1) << "Default search provider has been changed by user";
    default_search_provider_ = NULL;
    url_service->RemoveObserver(this);
    // This will delete the Protector instance and |this|.
    protector()->DismissChange();
  }
}

void DefaultSearchProviderChange::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK(type == chrome::NOTIFICATION_TEMPLATE_URL_REMOVED);
  TemplateURLID id = *content::Details<TemplateURLID>(details).ptr();
  if (id == new_id_)
    new_search_provider_ = NULL;
  registrar_.Remove(this, type, source);
  // TODO(ivankr): should the change be dismissed as well? Probably not,
  // since this may happend due to Sync or whatever. In that case, if user
  // clicks on 'Change to...', the Search engine settings page will be opened.
}

const TemplateURL* DefaultSearchProviderChange::SetDefaultSearchProvider(
    scoped_ptr<TemplateURL>* search_provider) {
  TemplateURLService* url_service = GetTemplateURLService();
  TemplateURLService::TemplateURLVector urls = url_service->GetTemplateURLs();
  const TemplateURL* new_default_provider = NULL;

  // Check if this provider already exists and add it otherwise.
  TemplateURLService::TemplateURLVector::const_iterator i =
      std::find_if(urls.begin(), urls.end(),
                   TemplateURLIsSame(search_provider->get()));
  if (i != urls.end()) {
    VLOG(1) << "Provider already exists";
    new_default_provider = *i;
    search_provider->reset();
  } else {
    VLOG(1) << "No match, adding new provider";
    new_default_provider = search_provider->get();
    url_service->Add(search_provider->release());
    UMA_HISTOGRAM_ENUMERATION(
        kProtectorHistogramSearchProviderMissing,
        GetSearchProviderHistogramID(new_default_provider),
        kProtectorMaxSearchProviderID);
  }

  // TODO(ivankr): handle keyword conflicts with existing providers.
  DCHECK(new_default_provider);
  VLOG(1) << "Default search provider set to: "
          << new_default_provider->short_name();
  url_service->SetDefaultSearchProvider(new_default_provider);
  return new_default_provider;
}

void DefaultSearchProviderChange::OpenSearchEngineSettings() {
  protector()->OpenTab(
      GURL(std::string(chrome::kChromeUISettingsURL) +
           chrome::kSearchEnginesSubPage));
}

TemplateURLService* DefaultSearchProviderChange::GetTemplateURLService() {
  TemplateURLService* url_service =
      TemplateURLServiceFactory::GetForProfile(protector()->profile());
  DCHECK(url_service);
  return url_service;
}

void DefaultSearchProviderChange::StopObservingTemplateURLService() {
  GetTemplateURLService()->RemoveObserver(this);
}

BaseSettingChange* CreateDefaultSearchProviderChange(
    const TemplateURL* actual,
    TemplateURL* backup) {
  return new DefaultSearchProviderChange(actual, backup);
}

}  // namespace protector
<|endoftext|>


<commit_before>/*
 * Keyman is copyright (C) SIL International. MIT License.
 *
 * Keyman Core - Debugger API unit tests
 */

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include "../../../src/kmx/kmx_xstring.h"
#include "../test_assert.h"

using namespace km::kbp::kmx;
using namespace std;

void test_incxstr() {

  PKMX_WCHAR p;   // pointer input to incxstr()
  PKMX_WCHAR q;   // pointer output to incxstr()

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- NULL, SURROGATE PAIRS, NON_UC_SENTINEL, ONE CHARACTER ---------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for empty string ------------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR) u"\0";
  q = incxstr(p);
  assert(q == p);

  // --- Test for character ---------------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR) u"\U00001234";
  q = incxstr(p);
  assert(q == p+1);

  // --- Test for surrogate pair ----------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR) u"\U0001F609";
  q = incxstr(p);
  assert(q == p+2);

    // --- Test for one <control> -----------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U00000012";
  q = incxstr(p);
  assert(q == p + 1);

  // --- Test for FFFF only -------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF";
  q = incxstr(p);
  assert(q == p + 1);

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- UC_SENTINEL WITHOUT \0 ----------------------------------------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for FFFF + CODE_ANY ----------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000001\U00000001";
  q = incxstr(p);
  assert(q == p + 3);
  //
  // --- Test for FFFF +CODE_NOTANY ----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000012\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_INDEX --------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000002\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 4);

  // --- Test for FFFF +CODE_USE ----------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000005\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_DEADKEY ------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000008\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF  CODE_EXTENDED --------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\U00000010";
  q = incxstr(p);
  assert(q == p + 9);

  // --- Test for FFFF +CODE_CLEARCONTEXT ------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000E\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_CALL ----------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000F\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_CONTEXTEX ---------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000011\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_IFOPT -------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000014\U00000002\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 5);

  // --- Test for FFFF +CODE_IFSYSTEMSTORE ------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000017\U00000002\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 5);

  // --- Test for FFFF +CODE_SETOPT ----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000013\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 4);

  // --- Test for FFFF +CODE_SETSYSTEMRESTORE ---------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000018\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 4);

  // --- Test for FFFF +CODE_RESETOPT -----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000016\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_SAVEOPT -----------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000015\U00000001";
  q = incxstr(p);
  assert(q == p + 3 );

  // --- Test for FFFF +default ----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000004";
  q = incxstr(p);
  assert(q == p + 2);

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- UC_SENTINEL WITH \0 AT DIFFERENT POSITIONS --------------------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for FFFF + control (earlier p+1) with \0 after first position --------------- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\0\U00000008\U00000001";
  q = incxstr(p);
  assert(q == p+1);

  // --- Test for FFFF +control (earlier p+1) with \0 after second position --------- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000008\0\U00000001";
  q = incxstr(p);
  assert(q == p+2);

  // --- Test for FFFF +control (earlier p+1) with \0 after third position ----- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000008\U00000001\0";
  q = incxstr(p);
  assert(q == p+3)

  // --- Test for FFFF +control (earlier p+2) with \0 after fourth position ----- unit test failed with old version of incxstr() ----
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000002\U00000001\U00000001\0";
  q = incxstr(p);
  assert(q == p+4);

  // --- Test for FFFF +control (earlier p+3) with \0 after fifth  position ----- unit test failed with old version of incxstr() ---------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000014\U00000001\U00000001\U00000001\0";
  q = incxstr(p);
  assert(q == p+5);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 6.  position  ----- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\0\U00000005\U00000006\U00000007\U00000010";
  q = incxstr(p);
  assert(q == p + 6);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 7.  position  ----- unit test failed with old version of incxstr()
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\0\U00000006\U00000007\U00000010";
  q = incxstr(p);
  assert(q == p + 7);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 8.  position  ----- unit test failed with old version of incxstr() ----------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\0\U00000007\U00000010";
  q = incxstr(p);
  assert(q == p + 8);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 9.  position  ----- unit test failed with old version of incxstr() ---
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\U00000007\0\U00000010";
  q = incxstr(p);
  assert(q == p + 9);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 10.  position  ----- unit test failed with old version of incxstr() -----------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\U00000007\U00000010\0";
  q = incxstr(p);
  assert(q == p + 10);

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- UC_SENTINEL, INCOMPLETE & UNUSUAL SEQUENCES--------------------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for FFFF + \0 --------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\0";
  q = incxstr(p);
  assert(q == p + 1);

  // --- Test for FFFF +one character ------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000062";
  q = incxstr(p);
  assert(q == p + 2);

  // --- Test for FFFF +one <control> -----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000004";
  q = incxstr(p);
  assert(q == p + 2);

  // --- Test for FFFF + one <control> + character -------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000004\U00000062";
  q = incxstr(p);
  assert(q == p + 2);

}

constexpr const auto help_str = "\
debug_api [--color] <SOURCE_PATH>|--print-sizeof\n\
\n\
  --color         Force color output\n\
  --print-sizeof  Emit structure sizes for interop debug\n\
  SOURCE_PATH     Path where debug_api.cpp is found; kmx files are\n\
                  located relative to this path.\n";

int error_args() {
  std::cerr << "debug_api: Invalid arguments." << std::endl;
  std::cout << help_str;
  return 1;
}

int main(int argc, char *argv []) {
  // TODO: choose/create a keyboard which has some rules
  // Global setup
  //std::string path(argv[1]);

  auto arg_color = argc > 1 && std::string(argv[1]) == "--color";
  console_color::enabled = console_color::isaterminal() || arg_color;

  test_incxstr();

  return 0;
}
<commit_msg>Update common/core/desktop/tests/unit/kmnkbd/test_kmx_xstring.cpp<commit_after>/*
 * Keyman is copyright (C) SIL International. MIT License.
 *
 * Keyman Core - Debugger API unit tests
 */

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include "../../../src/kmx/kmx_xstring.h"
#include "../test_assert.h"

using namespace km::kbp::kmx;
using namespace std;

void test_incxstr() {

  PKMX_WCHAR p;   // pointer input to incxstr()
  PKMX_WCHAR q;   // pointer output to incxstr()

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- NULL, SURROGATE PAIRS, NON_UC_SENTINEL, ONE CHARACTER ---------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for empty string ------------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR) u"\0";
  q = incxstr(p);
  assert(q == p);

  // --- Test for character ---------------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR) u"\U00001234";
  q = incxstr(p);
  assert(q == p+1);

  // --- Test for surrogate pair ----------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR) u"\U0001F609";
  q = incxstr(p);
  assert(q == p+2);

    // --- Test for one <control> -----------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U00000012";
  q = incxstr(p);
  assert(q == p + 1);

  // --- Test for FFFF only -------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF";
  q = incxstr(p);
  assert(q == p + 1);

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- UC_SENTINEL WITHOUT \0 ----------------------------------------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for FFFF + CODE_ANY ----------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000001\U00000001";
  q = incxstr(p);
  assert(q == p + 3);
  //
  // --- Test for FFFF +CODE_NOTANY ----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000012\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_INDEX --------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000002\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 4);

  // --- Test for FFFF +CODE_USE ----------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000005\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_DEADKEY ------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000008\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF  CODE_EXTENDED --------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\U00000010";
  q = incxstr(p);
  assert(q == p + 9);

  // --- Test for FFFF +CODE_CLEARCONTEXT ------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000E\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_CALL ----------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000F\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_CONTEXTEX ---------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000011\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_IFOPT -------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000014\U00000002\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 5);

  // --- Test for FFFF +CODE_IFSYSTEMSTORE ------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000017\U00000002\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 5);

  // --- Test for FFFF +CODE_SETOPT ----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000013\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 4);

  // --- Test for FFFF +CODE_SETSYSTEMRESTORE ---------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000018\U00000002\U00000001";
  q = incxstr(p);
  assert(q == p + 4);

  // --- Test for FFFF +CODE_RESETOPT -----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000016\U00000001";
  q = incxstr(p);
  assert(q == p + 3);

  // --- Test for FFFF +CODE_SAVEOPT -----------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000015\U00000001";
  q = incxstr(p);
  assert(q == p + 3 );

  // --- Test for FFFF +default ----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000004";
  q = incxstr(p);
  assert(q == p + 2);

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- UC_SENTINEL WITH \0 AT DIFFERENT POSITIONS --------------------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for FFFF + control (earlier p+1) with \0 after first position --------------- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\0\U00000008\U00000001";
  q = incxstr(p);
  assert(q == p+1);

  // --- Test for FFFF +control (earlier p+1) with \0 after second position --------- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000008\0\U00000001";
  q = incxstr(p);
  assert(q == p+2);

  // --- Test for FFFF +control (earlier p+1) with \0 after third position ----- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000008\U00000001\0";
  q = incxstr(p);
  assert(q == p+3)

  // --- Test for FFFF +control (earlier p+2) with \0 after fourth position ----- unit test failed with old version of incxstr() ----
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000002\U00000001\U00000001\0";
  q = incxstr(p);
  assert(q == p+4);

  // --- Test for FFFF +control (earlier p+3) with \0 after fifth  position ----- unit test failed with old version of incxstr() ---------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000014\U00000001\U00000001\U00000001\0";
  q = incxstr(p);
  assert(q == p+5);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 6.  position  ----- unit test failed with old version of incxstr() -----
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\0\U00000005\U00000006\U00000007\U00000010";
  q = incxstr(p);
  assert(q == p + 6);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 7.  position  ----- unit test failed with old version of incxstr()
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\0\U00000006\U00000007\U00000010";
  q = incxstr(p);
  assert(q == p + 7);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 8.  position  ----- unit test failed with old version of incxstr() ----------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\0\U00000007\U00000010";
  q = incxstr(p);
  assert(q == p + 8);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 9.  position  ----- unit test failed with old version of incxstr() ---
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\U00000007\0\U00000010";
  q = incxstr(p);
  assert(q == p + 9);

  // --- Test for FFFF +control CODE_EXTENDED ----- (earlier p+n) with \0 after 10.  position  ----- unit test failed with old version of incxstr() -----------
  p = (PKMX_WCHAR)u"\U0000FFFF\U0000000A\U00000001\U00000002\U00000003\U00000004\U00000005\U00000006\U00000007\U00000010\0";
  q = incxstr(p);
  assert(q == p + 10);

  // --------------------------------------------------------------------------------------------------------------------------------------------------
  // ---- UC_SENTINEL, INCOMPLETE & UNUSUAL SEQUENCES--------------------------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------------------------------------------------------------------------

  // --- Test for FFFF + \0 --------------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\0";
  q = incxstr(p);
  assert(q == p + 1);

  // --- Test for FFFF +one character ------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000062";
  q = incxstr(p);
  assert(q == p + 2);

  // --- Test for FFFF +one <control> -----------------------------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000004";
  q = incxstr(p);
  assert(q == p + 2);

  // --- Test for FFFF + one <control> + character -------------------------------------------------------------------------------------------
  p = (PKMX_WCHAR)u"\U0000FFFF\U00000004\U00000062";
  q = incxstr(p);
  assert(q == p + 2);

}

constexpr const auto help_str = "\
test_kmx_xstring [--color]\n\
\n\
  --color         Force color output\n";

int error_args() {
  std::cerr << "debug_api: Invalid arguments." << std::endl;
  std::cout << help_str;
  return 1;
}

int main(int argc, char *argv []) {
  // TODO: choose/create a keyboard which has some rules
  // Global setup
  //std::string path(argv[1]);

  auto arg_color = argc > 1 && std::string(argv[1]) == "--color";
  console_color::enabled = console_color::isaterminal() || arg_color;

  test_incxstr();

  return 0;
}
<|endoftext|>


<commit_before>// Copyright 2021 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "iree/compiler/InputConversion/TOSA/Passes.h"

#include "iree/compiler/Dialect/Flow/Transforms/Passes.h"
#include "iree/compiler/InputConversion/Common/Passes.h"
#include "mlir/Conversion/TosaToArith/TosaToArith.h"
#include "mlir/Conversion/TosaToLinalg/TosaToLinalg.h"
#include "mlir/Conversion/TosaToSCF/TosaToSCF.h"
#include "mlir/Conversion/TosaToTensor/TosaToTensor.h"
#include "mlir/Dialect/Tosa/Transforms/Passes.h"
#include "mlir/Pass/PassOptions.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Transforms/Passes.h"

namespace mlir {
namespace iree_compiler {

void registerTOSAConversionPassPipeline() {
  PassPipelineRegistration<> tosa(
      "iree-tosa-input-transformation-pipeline",
      "Runs the TOSA IREE flow dialect transformation pipeline",
      [](OpPassManager &passManager) {
        buildTOSAInputConversionPassPipeline(passManager);
      });
}

// Prepare TOSA for use as an input to the Flow dialect.
void buildTOSAInputConversionPassPipeline(OpPassManager &passManager) {
  // Currently we don't handle SCF ops well and have to convert them all to CFG.
  // In the future it would be nice if we could have all of flow be both scf
  // and cfg compatible.
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToSCF());
  passManager.addNestedPass<func::FuncOp>(createTopLevelSCFToCFGPass());

  // We also don't handle calls well on the old codepath; until we remove the
  // use of the CFG we can continue inlining.
  passManager.addPass(mlir::createInlinerPass());

  passManager.addNestedPass<func::FuncOp>(
      tosa::createTosaMakeBroadcastablePass());
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToArith());
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToTensor());
  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());

  tosa::addTosaToLinalgPasses(passManager);

  // Sometimes we generate more TOSA operations during the lowering to linalg.
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToArith());
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToTensor());

  passManager.addNestedPass<func::FuncOp>(
      IREE::Flow::createStripSignednessPass());
  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());

  passManager.addNestedPass<func::FuncOp>(
      createLinalgQuantizedMatmulToMatmulPass());
  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());

  //----------------------------------------------------------------------------
  // Entry dialect cleanup
  //----------------------------------------------------------------------------
  passManager.addPass(createVerifyCompilerTOSAInputLegality());
}

namespace {
#define GEN_PASS_REGISTRATION
#include "iree/compiler/InputConversion/TOSA/Passes.h.inc"  // IWYU pragma: export
}  // namespace

void registerTOSAConversionPasses() {
  // Generated.
  registerPasses();

  // Pipelines.
  registerTOSAConversionPassPipeline();
}

}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>Enable quantized conv decomposition (#10852)<commit_after>// Copyright 2021 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "iree/compiler/InputConversion/TOSA/Passes.h"

#include "iree/compiler/Dialect/Flow/Transforms/Passes.h"
#include "iree/compiler/InputConversion/Common/Passes.h"
#include "mlir/Conversion/TosaToArith/TosaToArith.h"
#include "mlir/Conversion/TosaToLinalg/TosaToLinalg.h"
#include "mlir/Conversion/TosaToSCF/TosaToSCF.h"
#include "mlir/Conversion/TosaToTensor/TosaToTensor.h"
#include "mlir/Dialect/Tosa/Transforms/Passes.h"
#include "mlir/Pass/PassOptions.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Transforms/Passes.h"

namespace mlir {
namespace iree_compiler {

void registerTOSAConversionPassPipeline() {
  PassPipelineRegistration<> tosa(
      "iree-tosa-input-transformation-pipeline",
      "Runs the TOSA IREE flow dialect transformation pipeline",
      [](OpPassManager &passManager) {
        buildTOSAInputConversionPassPipeline(passManager);
      });
}

// Prepare TOSA for use as an input to the Flow dialect.
void buildTOSAInputConversionPassPipeline(OpPassManager &passManager) {
  // Currently we don't handle SCF ops well and have to convert them all to CFG.
  // In the future it would be nice if we could have all of flow be both scf
  // and cfg compatible.
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToSCF());
  passManager.addNestedPass<func::FuncOp>(createTopLevelSCFToCFGPass());

  // We also don't handle calls well on the old codepath; until we remove the
  // use of the CFG we can continue inlining.
  passManager.addPass(mlir::createInlinerPass());

  passManager.addNestedPass<func::FuncOp>(
      tosa::createTosaMakeBroadcastablePass());
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToArith());
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToTensor());
  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());

  tosa::addTosaToLinalgPasses(passManager);

  // Sometimes we generate more TOSA operations during the lowering to linalg.
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToArith());
  passManager.addNestedPass<func::FuncOp>(tosa::createTosaToTensor());

  passManager.addNestedPass<func::FuncOp>(
      IREE::Flow::createStripSignednessPass());
  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());

  passManager.addNestedPass<func::FuncOp>(
      createLinalgQuantizedMatmulToMatmulPass());
  passManager.addNestedPass<func::FuncOp>(
      createLinalgQuantizedConvToConvPass());
  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());

  //----------------------------------------------------------------------------
  // Entry dialect cleanup
  //----------------------------------------------------------------------------
  passManager.addPass(createVerifyCompilerTOSAInputLegality());
}

namespace {
#define GEN_PASS_REGISTRATION
#include "iree/compiler/InputConversion/TOSA/Passes.h.inc"  // IWYU pragma: export
}  // namespace

void registerTOSAConversionPasses() {
  // Generated.
  registerPasses();

  // Pipelines.
  registerTOSAConversionPassPipeline();
}

}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>