<commit_before>/*****************************************************************************
 * fileinfo.cpp : WinCE gui plugin for vlc
 *****************************************************************************
 * Copyright (C) 2000-2004 the VideoLAN team
 * $Id$
 *
 * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
 *          Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>
#include <vlc_interface.h>
#include <vlc_input.h>

#include "wince.h"

#include <winuser.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <commdlg.h>

/*****************************************************************************
 * Constructor.
 *****************************************************************************/
FileInfo::FileInfo( intf_thread_t *p_intf, CBaseWindow *p_parent,
                    HINSTANCE h_inst )
  :  CBaseWindow( p_intf, p_parent, h_inst )
{
    /* Initializations */
    hwnd_fileinfo = hwndTV = NULL;
}

/***********************************************************************

FUNCTION:
  CreateTreeView

PURPOSE:
  Registers the TreeView control class and creates a TreeView.

***********************************************************************/
BOOL FileInfo::CreateTreeView(HWND hwnd)
{
    DWORD dwStyle;
    RECT rect;

    INITCOMMONCONTROLSEX iccex;
    iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
    iccex.dwICC = ICC_TREEVIEW_CLASSES;

    // Registers Statusbar control classes from the common control dll
    InitCommonControlsEx( &iccex );

    // Get the coordinates of the parent window's client area
    GetClientRect( hwnd, &rect );

    // Assign the window styles for the tree view.
    dwStyle = WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_LINESATROOT |
                          TVS_HASBUTTONS;

    // Create the tree-view control.
    hwndTV = CreateWindowEx( 0, WC_TREEVIEW, NULL, dwStyle, 0, MENU_HEIGHT,
                             rect.right-rect.left,
                             rect.bottom-rect.top-MENU_HEIGHT,
                             hwnd, NULL, hInst, NULL );

    // Be sure that the tree view actually was created.
    if( !hwndTV ) return FALSE;

    UpdateFileInfo();

    return TRUE;
}

/***********************************************************************

FUNCTION:
  UpdateFileInfo

PURPOSE:
  Update the TreeView with file information.

***********************************************************************/
void FileInfo::UpdateFileInfo()
{
    TVITEM tvi = {0};
    TVINSERTSTRUCT tvins = {0};
    HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
    HTREEITEM hPrevRootItem = NULL;
    HTREEITEM hPrevLev2Item = NULL;

    p_intf->p_sys->p_input = (input_thread_t *)
        vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );

    input_thread_t *p_input = p_intf->p_sys->p_input;

    if( !p_input ) return;

    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

    // Set the text of the item. Not right, but I don't know yet how to handle this
    //tvi.pszText = _FROMMB( p_input->input.p_item->psz_name ); <- old line
    input_item_t * inp_item = input_item_GetById( p_input, 1 );
    tvi.pszText = _FROMMB( input_item_GetName( inp_item ) );
    tvi.cchTextMax = _tcslen( tvi.pszText );

    // Save the heading level in the item's application-defined data area
    tvi.lParam = (LPARAM)1;
    tvins.item = tvi;
    //tvins.hInsertAfter = TVI_LAST;
    tvins.hInsertAfter = hPrev;
    tvins.hParent = TVI_ROOT;

    // Add the item to the tree-view control.
    hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );

    hPrevRootItem = hPrev;

    vlc_mutex_lock( &inp_item->lock );
    for( int i = 0; i < inp_item->i_categories; i++ )
    {
        info_category_t *p_cat = inp_item->pp_categories[i];

        // Set the text of the item.
        tvi.pszText = _FROMMB( inp_item->psz_name );
        tvi.cchTextMax = _tcslen( tvi.pszText );

        // Save the heading level in the item's application-defined data area
        tvi.lParam = (LPARAM)2; // level 2
        tvins.item = tvi;
        tvins.hInsertAfter = hPrev;
        tvins.hParent = hPrevRootItem;

        // Add the item to the tree-view control.
        hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );

        hPrevLev2Item = hPrev;

        for( int j = 0; j < p_cat->i_infos; j++ )
        {
            info_t *p_info = p_cat->pp_infos[j];

            // Set the text of the item.
            string szAnsi = (string)p_info->psz_name;
            szAnsi += ": ";
            szAnsi += p_info->psz_value;
            tvi.pszText = (TCHAR *)_FROMMB( szAnsi.c_str() );
            tvi.cchTextMax = _tcslen( tvi.pszText );
            tvi.lParam = (LPARAM)3; // level 3
            tvins.item = tvi;
            tvins.hInsertAfter = hPrev;
            tvins.hParent = hPrevLev2Item;

            // Add the item to the tree-view control.
            hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
        }

        TreeView_Expand( hwndTV, hPrevLev2Item, TVE_EXPANDPARTIAL|TVE_EXPAND );
    }
    vlc_mutex_unlock( &inp_item->lock );

    TreeView_Expand( hwndTV, hPrevRootItem, TVE_EXPANDPARTIAL|TVE_EXPAND );

    return;
}

/***********************************************************************

FUNCTION:
  WndProc

PURPOSE:
  Processes messages sent to the main window.

***********************************************************************/
LRESULT FileInfo::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
    SHINITDLGINFO shidi;

    switch( msg )
    {
    case WM_INITDIALOG:
        shidi.dwMask = SHIDIM_FLAGS;
        shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
            SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
        shidi.hDlg = hwnd;
        SHInitDialog( &shidi );
        CreateTreeView( hwnd );
        UpdateWindow( hwnd );
        SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
        break;

    case WM_CLOSE:
        EndDialog( hwnd, LOWORD( wp ) );
        break;

    case WM_SETFOCUS:
        SHSipPreference( hwnd, SIP_DOWN );
        SHFullScreen( hwnd, SHFS_HIDESIPBUTTON );
        break;

    case WM_COMMAND:
        if ( LOWORD(wp) == IDOK )
        {
            EndDialog( hwnd, LOWORD( wp ) );
        }
        break;

    default:
        break;
    }

    return FALSE;
}
<commit_msg>WinCE intf: use existing vlc functions<commit_after>/*****************************************************************************
 * fileinfo.cpp : WinCE gui plugin for vlc
 *****************************************************************************
 * Copyright (C) 2000-2004 the VideoLAN team
 * $Id$
 *
 * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
 *          Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>
#include <vlc_interface.h>
#include <vlc_input.h>

#include "wince.h"

#include <winuser.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <commdlg.h>

/*****************************************************************************
 * Constructor.
 *****************************************************************************/
FileInfo::FileInfo( intf_thread_t *p_intf, CBaseWindow *p_parent,
                    HINSTANCE h_inst )
  :  CBaseWindow( p_intf, p_parent, h_inst )
{
    /* Initializations */
    hwnd_fileinfo = hwndTV = NULL;
}

/***********************************************************************

FUNCTION:
  CreateTreeView

PURPOSE:
  Registers the TreeView control class and creates a TreeView.

***********************************************************************/
BOOL FileInfo::CreateTreeView(HWND hwnd)
{
    DWORD dwStyle;
    RECT rect;

    INITCOMMONCONTROLSEX iccex;
    iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
    iccex.dwICC = ICC_TREEVIEW_CLASSES;

    // Registers Statusbar control classes from the common control dll
    InitCommonControlsEx( &iccex );

    // Get the coordinates of the parent window's client area
    GetClientRect( hwnd, &rect );

    // Assign the window styles for the tree view.
    dwStyle = WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_LINESATROOT |
                          TVS_HASBUTTONS;

    // Create the tree-view control.
    hwndTV = CreateWindowEx( 0, WC_TREEVIEW, NULL, dwStyle, 0, MENU_HEIGHT,
                             rect.right-rect.left,
                             rect.bottom-rect.top-MENU_HEIGHT,
                             hwnd, NULL, hInst, NULL );

    // Be sure that the tree view actually was created.
    if( !hwndTV ) return FALSE;

    UpdateFileInfo();

    return TRUE;
}

/***********************************************************************

FUNCTION:
  UpdateFileInfo

PURPOSE:
  Update the TreeView with file information.

***********************************************************************/
void FileInfo::UpdateFileInfo()
{
    TVITEM tvi = {0};
    TVINSERTSTRUCT tvins = {0};
    HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
    HTREEITEM hPrevRootItem = NULL;
    HTREEITEM hPrevLev2Item = NULL;

    p_intf->p_sys->p_input = (input_thread_t *)
        vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );

    input_thread_t *p_input = p_intf->p_sys->p_input;

    if( !p_input ) return;

    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

    input_item_t * inp_item = input_GetItem(p_input);
    tvi.pszText = _FROMMB( input_item_GetName( inp_item ) );
    tvi.cchTextMax = _tcslen( tvi.pszText );

    // Save the heading level in the item's application-defined data area
    tvi.lParam = (LPARAM)1;
    tvins.item = tvi;
    //tvins.hInsertAfter = TVI_LAST;
    tvins.hInsertAfter = hPrev;
    tvins.hParent = TVI_ROOT;

    // Add the item to the tree-view control.
    hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );

    hPrevRootItem = hPrev;

    vlc_mutex_lock( &inp_item->lock );
    for( int i = 0; i < inp_item->i_categories; i++ )
    {
        info_category_t *p_cat = inp_item->pp_categories[i];

        // Set the text of the item.
        tvi.pszText = _FROMMB( inp_item->psz_name );
        tvi.cchTextMax = _tcslen( tvi.pszText );

        // Save the heading level in the item's application-defined data area
        tvi.lParam = (LPARAM)2; // level 2
        tvins.item = tvi;
        tvins.hInsertAfter = hPrev;
        tvins.hParent = hPrevRootItem;

        // Add the item to the tree-view control.
        hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );

        hPrevLev2Item = hPrev;

        for( int j = 0; j < p_cat->i_infos; j++ )
        {
            info_t *p_info = p_cat->pp_infos[j];

            // Set the text of the item.
            string szAnsi = (string)p_info->psz_name;
            szAnsi += ": ";
            szAnsi += p_info->psz_value;
            tvi.pszText = (TCHAR *)_FROMMB( szAnsi.c_str() );
            tvi.cchTextMax = _tcslen( tvi.pszText );
            tvi.lParam = (LPARAM)3; // level 3
            tvins.item = tvi;
            tvins.hInsertAfter = hPrev;
            tvins.hParent = hPrevLev2Item;

            // Add the item to the tree-view control.
            hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
        }

        TreeView_Expand( hwndTV, hPrevLev2Item, TVE_EXPANDPARTIAL|TVE_EXPAND );
    }
    vlc_mutex_unlock( &inp_item->lock );

    TreeView_Expand( hwndTV, hPrevRootItem, TVE_EXPANDPARTIAL|TVE_EXPAND );

    return;
}

/***********************************************************************

FUNCTION:
  WndProc

PURPOSE:
  Processes messages sent to the main window.

***********************************************************************/
LRESULT FileInfo::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
    SHINITDLGINFO shidi;

    switch( msg )
    {
    case WM_INITDIALOG:
        shidi.dwMask = SHIDIM_FLAGS;
        shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
            SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
        shidi.hDlg = hwnd;
        SHInitDialog( &shidi );
        CreateTreeView( hwnd );
        UpdateWindow( hwnd );
        SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
        break;

    case WM_CLOSE:
        EndDialog( hwnd, LOWORD( wp ) );
        break;

    case WM_SETFOCUS:
        SHSipPreference( hwnd, SIP_DOWN );
        SHFullScreen( hwnd, SHFS_HIDESIPBUTTON );
        break;

    case WM_COMMAND:
        if ( LOWORD(wp) == IDOK )
        {
            EndDialog( hwnd, LOWORD( wp ) );
        }
        break;

    default:
        break;
    }

    return FALSE;
}
<|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 "chrome/browser/chromeos/setting_level_bubble.h"

#include <gdk/gdk.h>

#include "base/timer.h"
#include "chrome/browser/chromeos/login/background_view.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/setting_level_bubble_view.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/views/bubble/bubble.h"
#include "ui/gfx/screen.h"
#include "views/widget/root_view.h"

namespace {

const int kBubbleShowTimeoutSec = 2;
const int kAnimationDurationMs = 200;

// Horizontal position of the center of the bubble on the screen: 0 is left
// edge, 0.5 is center, 1 is right edge.
const double kBubbleXRatio = 0.5;

// Vertical gap from the bottom of the screen in pixels.
const int kBubbleBottomGap = 30;

int LimitPercent(int percent) {
  if (percent < 0)
    percent = 0;
  else if (percent > 100)
    percent = 100;
  return percent;
}

}  // namespace

namespace chromeos {

// Temporary helper routine. Tries to first return the widget from the
// most-recently-focused normal browser window, then from a login
// background, and finally NULL if both of those fail.
// TODO(glotov): remove this in favor of enabling Bubble class act
// without |parent| specified. crosbug.com/4025
static views::Widget* GetToplevelWidget() {
  GtkWindow* window = NULL;

  // We just use the default profile here -- this gets overridden as needed
  // in Chrome OS depending on whether the user is logged in or not.
  Browser* browser =
      BrowserList::FindTabbedBrowser(
          ProfileManager::GetDefaultProfile(),
          true);  // match_incognito
  if (browser) {
    window = GTK_WINDOW(browser->window()->GetNativeHandle());
  } else {
    // Otherwise, see if there's a background window that we can use.
    BackgroundView* background = LoginUtils::Get()->GetBackgroundView();
    if (background)
      window = GTK_WINDOW(background->GetNativeWindow());
  }

  if (!window)
    return NULL;

  return views::Widget::GetWidgetForNativeWindow(window);
}

SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
                                       SkBitmap* decrease_icon,
                                       SkBitmap* zero_icon)
    : previous_percent_(-1),
      current_percent_(-1),
      increase_icon_(increase_icon),
      decrease_icon_(decrease_icon),
      zero_icon_(zero_icon),
      bubble_(NULL),
      view_(NULL),
      animation_(this) {
  animation_.SetSlideDuration(kAnimationDurationMs);
  animation_.SetTweenType(ui::Tween::LINEAR);
}

SettingLevelBubble::~SettingLevelBubble() {}

void SettingLevelBubble::ShowBubble(int percent) {
  percent = LimitPercent(percent);
  if (previous_percent_ == -1)
    previous_percent_ = percent;
  current_percent_ = percent;

  SkBitmap* icon = increase_icon_;
  if (current_percent_ == 0)
    icon = zero_icon_;
  else if (current_percent_ < previous_percent_)
    icon = decrease_icon_;

  if (!bubble_) {
    views::Widget* parent_widget = GetToplevelWidget();
    if (parent_widget == NULL)
      return;
    DCHECK(view_ == NULL);
    view_ = new SettingLevelBubbleView;
    view_->Init(icon, previous_percent_);

    // Calculate the position in screen coordinates that the bubble should
    // "point" at (since we use BubbleBorder::FLOAT, this position actually
    // specifies the center of the bubble).
    const gfx::Rect monitor_area =
        gfx::Screen::GetMonitorAreaNearestWindow(
            GTK_WIDGET(parent_widget->GetNativeWindow()));
    const gfx::Size view_size = view_->GetPreferredSize();
    const gfx::Rect position_relative_to(
        monitor_area.x() + kBubbleXRatio * monitor_area.width(),
        monitor_area.bottom() - view_size.height() / 2 - kBubbleBottomGap,
        0, 0);

    // ShowFocusless doesn't set ESC accelerator.
    bubble_ = Bubble::ShowFocusless(parent_widget,
                                    position_relative_to,
                                    BubbleBorder::FLOAT,
                                    view_,  // contents
                                    this,   // delegate
                                    true);  // show while screen is locked
  } else {
    DCHECK(view_);
    timeout_timer_.Stop();
    view_->SetIcon(icon);
  }
  if (animation_.is_animating())
    animation_.End();
  animation_.Reset();
  animation_.Show();
  timeout_timer_.Start(base::TimeDelta::FromSeconds(kBubbleShowTimeoutSec),
                       this, &SettingLevelBubble::OnTimeout);
}

void SettingLevelBubble::HideBubble() {
  if (bubble_)
    bubble_->Close();
}

void SettingLevelBubble::UpdateWithoutShowingBubble(int percent) {
  percent = LimitPercent(percent);

  previous_percent_ =
      animation_.is_animating() ?
      animation_.GetCurrentValue() :
      current_percent_;
  if (previous_percent_ < 0)
    previous_percent_ = percent;
  current_percent_ = percent;

  if (animation_.is_animating())
    animation_.End();
  animation_.Reset();
  animation_.Show();
}

void SettingLevelBubble::OnTimeout() {
  HideBubble();
}

void SettingLevelBubble::BubbleClosing(Bubble* bubble, bool) {
  DCHECK(bubble == bubble_);
  timeout_timer_.Stop();
  animation_.Stop();
  bubble_ = NULL;
  view_ = NULL;
}

bool SettingLevelBubble::CloseOnEscape() {
  return true;
}

bool SettingLevelBubble::FadeInOnShow() {
  return false;
}

void SettingLevelBubble::AnimationEnded(const ui::Animation* animation) {
  previous_percent_ = current_percent_;
}

void SettingLevelBubble::AnimationProgressed(const ui::Animation* animation) {
  if (view_) {
    view_->Update(
        ui::Tween::ValueBetween(animation->GetCurrentValue(),
                                previous_percent_,
                                current_percent_));
  }
}

}  // namespace chromeos
<commit_msg>System bubbles work with webui login display<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.

#include "chrome/browser/chromeos/setting_level_bubble.h"

#include <gdk/gdk.h>

#include "base/timer.h"
#include "chrome/browser/chromeos/login/background_view.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/webui_login_display.h"
#include "chrome/browser/chromeos/setting_level_bubble_view.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/views/bubble/bubble.h"
#include "ui/gfx/screen.h"
#include "views/widget/root_view.h"

namespace {

const int kBubbleShowTimeoutSec = 2;
const int kAnimationDurationMs = 200;

// Horizontal position of the center of the bubble on the screen: 0 is left
// edge, 0.5 is center, 1 is right edge.
const double kBubbleXRatio = 0.5;

// Vertical gap from the bottom of the screen in pixels.
const int kBubbleBottomGap = 30;

int LimitPercent(int percent) {
  if (percent < 0)
    percent = 0;
  else if (percent > 100)
    percent = 100;
  return percent;
}

}  // namespace

namespace chromeos {

// Temporary helper routine. Tries to first return the widget from the
// most-recently-focused normal browser window, then from a login
// background, and finally NULL if both of those fail.
// TODO(glotov): remove this in favor of enabling Bubble class act
// without |parent| specified. crosbug.com/4025
static views::Widget* GetToplevelWidget() {
  GtkWindow* window = NULL;

  // We just use the default profile here -- this gets overridden as needed
  // in Chrome OS depending on whether the user is logged in or not.
  Browser* browser =
      BrowserList::FindTabbedBrowser(
          ProfileManager::GetDefaultProfile(),
          true);  // match_incognito
  if (browser) {
    window = GTK_WINDOW(browser->window()->GetNativeHandle());
  } else {
    // Otherwise, see if there's a background window that we can use.
    BackgroundView* background = LoginUtils::Get()->GetBackgroundView();
    if (background)
      window = GTK_WINDOW(background->GetNativeWindow());
  }

  if (window)
    return views::Widget::GetWidgetForNativeWindow(window);
  else
    return WebUILoginDisplay::GetLoginWindow();
}

SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
                                       SkBitmap* decrease_icon,
                                       SkBitmap* zero_icon)
    : previous_percent_(-1),
      current_percent_(-1),
      increase_icon_(increase_icon),
      decrease_icon_(decrease_icon),
      zero_icon_(zero_icon),
      bubble_(NULL),
      view_(NULL),
      animation_(this) {
  animation_.SetSlideDuration(kAnimationDurationMs);
  animation_.SetTweenType(ui::Tween::LINEAR);
}

SettingLevelBubble::~SettingLevelBubble() {}

void SettingLevelBubble::ShowBubble(int percent) {
  percent = LimitPercent(percent);
  if (previous_percent_ == -1)
    previous_percent_ = percent;
  current_percent_ = percent;

  SkBitmap* icon = increase_icon_;
  if (current_percent_ == 0)
    icon = zero_icon_;
  else if (current_percent_ < previous_percent_)
    icon = decrease_icon_;

  if (!bubble_) {
    views::Widget* parent_widget = GetToplevelWidget();
    if (parent_widget == NULL) {
      LOG(WARNING) << "Unable to locate parent widget to display a bubble";
      return;
    }
    DCHECK(view_ == NULL);
    view_ = new SettingLevelBubbleView;
    view_->Init(icon, previous_percent_);

    // Calculate the position in screen coordinates that the bubble should
    // "point" at (since we use BubbleBorder::FLOAT, this position actually
    // specifies the center of the bubble).
    const gfx::Rect monitor_area =
        gfx::Screen::GetMonitorAreaNearestWindow(
            GTK_WIDGET(parent_widget->GetNativeWindow()));
    const gfx::Size view_size = view_->GetPreferredSize();
    const gfx::Rect position_relative_to(
        monitor_area.x() + kBubbleXRatio * monitor_area.width(),
        monitor_area.bottom() - view_size.height() / 2 - kBubbleBottomGap,
        0, 0);

    // ShowFocusless doesn't set ESC accelerator.
    bubble_ = Bubble::ShowFocusless(parent_widget,
                                    position_relative_to,
                                    BubbleBorder::FLOAT,
                                    view_,  // contents
                                    this,   // delegate
                                    true);  // show while screen is locked
  } else {
    DCHECK(view_);
    timeout_timer_.Stop();
    view_->SetIcon(icon);
  }
  if (animation_.is_animating())
    animation_.End();
  animation_.Reset();
  animation_.Show();
  timeout_timer_.Start(base::TimeDelta::FromSeconds(kBubbleShowTimeoutSec),
                       this, &SettingLevelBubble::OnTimeout);
}

void SettingLevelBubble::HideBubble() {
  if (bubble_)
    bubble_->Close();
}

void SettingLevelBubble::UpdateWithoutShowingBubble(int percent) {
  percent = LimitPercent(percent);

  previous_percent_ =
      animation_.is_animating() ?
      animation_.GetCurrentValue() :
      current_percent_;
  if (previous_percent_ < 0)
    previous_percent_ = percent;
  current_percent_ = percent;

  if (animation_.is_animating())
    animation_.End();
  animation_.Reset();
  animation_.Show();
}

void SettingLevelBubble::OnTimeout() {
  HideBubble();
}

void SettingLevelBubble::BubbleClosing(Bubble* bubble, bool) {
  DCHECK(bubble == bubble_);
  timeout_timer_.Stop();
  animation_.Stop();
  bubble_ = NULL;
  view_ = NULL;
}

bool SettingLevelBubble::CloseOnEscape() {
  return true;
}

bool SettingLevelBubble::FadeInOnShow() {
  return false;
}

void SettingLevelBubble::AnimationEnded(const ui::Animation* animation) {
  previous_percent_ = current_percent_;
}

void SettingLevelBubble::AnimationProgressed(const ui::Animation* animation) {
  if (view_) {
    view_->Update(
        ui::Tween::ValueBetween(animation->GetCurrentValue(),
                                previous_percent_,
                                current_percent_));
  }
}

}  // namespace chromeos
<|endoftext|>


<commit_before><commit_msg>Fix a conditional jump depending on an uninitialized value from r39951 by setting it to false in the ctor.<commit_after><|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2003-2010.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision: 62023 $
//
//  Description : unit test for new assertion construction based on input expression
// ***************************************************************************

// Boost.Test
#define BOOST_TEST_MODULE Boost.Test assertion consruction test
#include <boost/test/unit_test.hpp>
#include <boost/test/tools/assertion.hpp>

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_basic_value_expression_construction )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        assertion::expression const& E = seed->*1;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
        BOOST_CHECK( res.message().is_empty() );
    }

    {
        assertion::expression const& E = seed->*0;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
    }

    {
        assertion::expression const& E = seed->*true;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
        BOOST_CHECK( res.message().is_empty() );
    }

    {
        assertion::expression const& E = seed->*1.5;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
    }

#ifndef BOOST_NO_DECLTYPE
    {
        assertion::expression const& E = seed->* "abc";
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
    }
#endif

    {
        assertion::expression const& E = seed->* 1>2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "1<=2" );
    }

}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_comparison_expression )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        assertion::expression const& E = seed->* 1>2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "1<=2" );
    }

    {
        assertion::expression const& E = seed->* 100 < 50;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "100>=50" );
    }

    {
        assertion::expression const& E = seed->* 5<=4;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "5>4" );
    }

    {
        assertion::expression const& E = seed->* 10>=20;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "10<20" );
    }

    {
        int i = 10;
        assertion::expression const& E = seed->* i != 10;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "10==10" );
    }

    {
        int i = 5;
        assertion::expression const& E = seed->* i == 3;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "5!=3" );
    }
}

//____________________________________________________________________________//

#ifndef BOOST_NO_DECLTYPE

BOOST_AUTO_TEST_CASE( test_arithmetic_ops )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        int i = 3;
        int j = 5;
        assertion::expression const& E = seed->* i+j !=8;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "3+5==8" );
    }

    {
        int i = 3;
        int j = 5;
        assertion::expression const& E = seed->* 2*i-j > 1;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "2*3-5<=1" );
    }

    {
        int j = 5;
        assertion::expression const& E = seed->* 2<<j < 30;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "2<<5>=30" );
    }

    {
        int i = 2;
        int j = 5;
        assertion::expression const& E = seed->* i&j;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "2&5" );
    }

    {
        int i = 3;
        int j = 5;
        assertion::expression const& E = seed->* i^j^6;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "3^5^6" );
    }

    // do not support
    // assertion::expression const& E = seed->*99/2 == 48 || 101/2 > 50;
    // assertion::expression const& E = seed->* a ? 100 < 50 : 25*2 == 50;
    // assertion::expression const& E = seed->* true,false;
}

//____________________________________________________________________________//

#endif // BOOST_NO_DECLTYPE

struct Testee {
    static int s_copy_counter;

    Testee() : m_value( false ) {}
    Testee( Testee const& ) : m_value(false) { s_copy_counter++; }
#ifndef BOOST_NO_RVALUE_REFERENCES
    Testee( Testee&& ) : m_value(false)     {}
#endif

    bool foo() { return m_value; }
    operator bool() const { return m_value; }

    friend std::ostream& operator<<( std::ostream& ostr, Testee const& ) { return ostr << "Testee"; }

    bool m_value;
};

int Testee::s_copy_counter = 0;

#ifndef BOOST_NO_RVALUE_REFERENCES
Testee          get_obj() { return std::move( Testee() ); }
Testee const    get_const_obj() { return std::move( Testee() ); }
#else
Testee          get_obj() { return Testee(); }
Testee const    get_const_obj() { return Testee(); }
#endif

BOOST_AUTO_TEST_CASE( test_objects )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        Testee obj;
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* obj;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 0 );
#else
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 );
#endif
    }

    {
        Testee const obj;
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* obj;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 0 );
#else
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 );
#endif
    }

    {
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* get_obj();
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 ); // !! ??
    }

    {
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* get_const_obj();
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 ); // !! ??
    }
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_pointers )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        Testee* ptr = 0;

        assertion::expression const& E = seed->* ptr;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)00000000 is false" );
    }

    {
        Testee obj1;
        Testee obj2;

        assertion::expression const& E = seed->* &obj1 == &obj2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
    }

    {
        Testee obj;
        Testee* ptr =&obj;

        assertion::expression const& E = seed->* *ptr;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
    }

#ifndef BOOST_NO_DECLTYPE
    {
        Testee obj;
        Testee* ptr =&obj;
        bool Testee::* mem_ptr =&Testee::m_value;

        assertion::expression const& E = seed->* ptr->*mem_ptr;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
    }
#endif

    // do not support
    // Testee obj;
    // bool Testee::* mem_ptr =&Testee::m_value;
    // assertion::expression const& E = seed->* obj.*mem_ptr;
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_mutating_ops )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        int j = 5;

        assertion::expression const& E = seed->* j = 0;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j -= 5;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j *= 0;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j /= 10;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 4;

        assertion::expression const& E = seed->* j %= 2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 4 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j ^= j;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }
}

//____________________________________________________________________________//

// EOF

<commit_msg>remove non portable comparison<commit_after>//  (C) Copyright Gennadiy Rozental 2003-2010.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision: 62023 $
//
//  Description : unit test for new assertion construction based on input expression
// ***************************************************************************

// Boost.Test
#define BOOST_TEST_MODULE Boost.Test assertion consruction test
#include <boost/test/unit_test.hpp>
#include <boost/test/tools/assertion.hpp>

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_basic_value_expression_construction )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        assertion::expression const& E = seed->*1;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
        BOOST_CHECK( res.message().is_empty() );
    }

    {
        assertion::expression const& E = seed->*0;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
    }

    {
        assertion::expression const& E = seed->*true;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
        BOOST_CHECK( res.message().is_empty() );
    }

    {
        assertion::expression const& E = seed->*1.5;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
    }

#ifndef BOOST_NO_DECLTYPE
    {
        assertion::expression const& E = seed->* "abc";
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( res );
    }
#endif

    {
        assertion::expression const& E = seed->* 1>2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "1<=2" );
    }

}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_comparison_expression )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        assertion::expression const& E = seed->* 1>2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "1<=2" );
    }

    {
        assertion::expression const& E = seed->* 100 < 50;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "100>=50" );
    }

    {
        assertion::expression const& E = seed->* 5<=4;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "5>4" );
    }

    {
        assertion::expression const& E = seed->* 10>=20;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "10<20" );
    }

    {
        int i = 10;
        assertion::expression const& E = seed->* i != 10;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "10==10" );
    }

    {
        int i = 5;
        assertion::expression const& E = seed->* i == 3;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "5!=3" );
    }
}

//____________________________________________________________________________//

#ifndef BOOST_NO_DECLTYPE

BOOST_AUTO_TEST_CASE( test_arithmetic_ops )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        int i = 3;
        int j = 5;
        assertion::expression const& E = seed->* i+j !=8;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "3+5==8" );
    }

    {
        int i = 3;
        int j = 5;
        assertion::expression const& E = seed->* 2*i-j > 1;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "2*3-5<=1" );
    }

    {
        int j = 5;
        assertion::expression const& E = seed->* 2<<j < 30;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "2<<5>=30" );
    }

    {
        int i = 2;
        int j = 5;
        assertion::expression const& E = seed->* i&j;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "2&5" );
    }

    {
        int i = 3;
        int j = 5;
        assertion::expression const& E = seed->* i^j^6;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "3^5^6" );
    }

    // do not support
    // assertion::expression const& E = seed->*99/2 == 48 || 101/2 > 50;
    // assertion::expression const& E = seed->* a ? 100 < 50 : 25*2 == 50;
    // assertion::expression const& E = seed->* true,false;
}

//____________________________________________________________________________//

#endif // BOOST_NO_DECLTYPE

struct Testee {
    static int s_copy_counter;

    Testee() : m_value( false ) {}
    Testee( Testee const& ) : m_value(false) { s_copy_counter++; }
#ifndef BOOST_NO_RVALUE_REFERENCES
    Testee( Testee&& ) : m_value(false)     {}
#endif

    bool foo() { return m_value; }
    operator bool() const { return m_value; }

    friend std::ostream& operator<<( std::ostream& ostr, Testee const& ) { return ostr << "Testee"; }

    bool m_value;
};

int Testee::s_copy_counter = 0;

#ifndef BOOST_NO_RVALUE_REFERENCES
Testee          get_obj() { return std::move( Testee() ); }
Testee const    get_const_obj() { return std::move( Testee() ); }
#else
Testee          get_obj() { return Testee(); }
Testee const    get_const_obj() { return Testee(); }
#endif

BOOST_AUTO_TEST_CASE( test_objects )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        Testee obj;
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* obj;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 0 );
#else
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 );
#endif
    }

    {
        Testee const obj;
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* obj;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 0 );
#else
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 );
#endif
    }

    {
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* get_obj();
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 ); // !! ??
    }

    {
        Testee::s_copy_counter = 0;

        assertion::expression const& E = seed->* get_const_obj();
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
        BOOST_CHECK_EQUAL( Testee::s_copy_counter, 1 ); // !! ??
    }
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_pointers )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        Testee* ptr = 0;

        assertion::expression const& E = seed->* ptr;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
    }

    {
        Testee obj1;
        Testee obj2;

        assertion::expression const& E = seed->* &obj1 == &obj2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
    }

    {
        Testee obj;
        Testee* ptr =&obj;

        assertion::expression const& E = seed->* *ptr;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)Testee is false" );
    }

#ifndef BOOST_NO_DECLTYPE
    {
        Testee obj;
        Testee* ptr =&obj;
        bool Testee::* mem_ptr =&Testee::m_value;

        assertion::expression const& E = seed->* ptr->*mem_ptr;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
    }
#endif

    // do not support
    // Testee obj;
    // bool Testee::* mem_ptr =&Testee::m_value;
    // assertion::expression const& E = seed->* obj.*mem_ptr;
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_mutating_ops )
{
    using namespace boost::test_tools;
    assertion::seed seed;

    {
        int j = 5;

        assertion::expression const& E = seed->* j = 0;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j -= 5;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j *= 0;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j /= 10;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }

    {
        int j = 4;

        assertion::expression const& E = seed->* j %= 2;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 4 );
#endif
    }

    {
        int j = 5;

        assertion::expression const& E = seed->* j ^= j;
        predicate_result const& res = E.evaluate();
        BOOST_CHECK( !res );
        BOOST_CHECK_EQUAL( res.message(), "(bool)0 is false" );
#ifndef BOOST_NO_RVALUE_REFERENCES
        BOOST_CHECK_EQUAL( j, 0 );
#else
        BOOST_CHECK_EQUAL( j, 5 );
#endif
    }
}

//____________________________________________________________________________//

// EOF

<|endoftext|>


<commit_before>// Copyright 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 "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "chrome/browser/extensions/blacklist.h"
#include "chrome/browser/extensions/blacklist_state_fetcher.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
#include "chrome/browser/extensions/test_blacklist.h"
#include "chrome/browser/extensions/test_blacklist_state_fetcher.h"
#include "chrome/browser/extensions/test_extension_prefs.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace extensions {
namespace {

std::set<std::string> Set(const std::string& a) {
  std::set<std::string> set;
  set.insert(a);
  return set;
}
std::set<std::string> Set(const std::string& a, const std::string& b) {
  std::set<std::string> set = Set(a);
  set.insert(b);
  return set;
}
std::set<std::string> Set(const std::string& a,
                          const std::string& b,
                          const std::string& c) {
  std::set<std::string> set = Set(a, b);
  set.insert(c);
  return set;
}
std::set<std::string> Set(const std::string& a,
                          const std::string& b,
                          const std::string& c,
                          const std::string& d) {
  std::set<std::string> set = Set(a, b, c);
  set.insert(d);
  return set;
}

class BlacklistTest : public testing::Test {
 public:
  BlacklistTest()
      : test_prefs_(base::MessageLoopProxy::current()),
        blacklist_db_(new FakeSafeBrowsingDatabaseManager(false)),
        scoped_blacklist_db_(blacklist_db_) {}

 protected:
  ExtensionPrefs* prefs() {
    return test_prefs_.prefs();
  }

  FakeSafeBrowsingDatabaseManager* blacklist_db() {
    return blacklist_db_.get();
  }

  std::string AddExtension(const std::string& id) {
    return test_prefs_.AddExtension(id)->id();
  }

 private:
  content::TestBrowserThreadBundle browser_thread_bundle_;

  TestExtensionPrefs test_prefs_;

  scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db_;

  Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db_;
};

class BlacklistStateFetcherMock : public BlacklistStateFetcher {
 public:
  virtual void Request(const std::string& id,
                       const RequestCallback& callback) OVERRIDE {
    request_count_++;

    BlacklistState result = NOT_BLACKLISTED;
    if (ContainsKey(states_, id))
      result = states_[id];

    base::MessageLoopProxy::current()->PostTask(FROM_HERE,
                                                base::Bind(callback, result));
  }

  void SetState(const std::string& id, BlacklistState state) {
    states_[id] = state;
  }

  int request_count() const {
    return request_count_;
  }

 private:
  std::map<std::string, BlacklistState> states_;
  int request_count_;
};

template<typename T>
void Assign(T *to, const T& from) {
  *to = from;
}

}  // namespace

TEST_F(BlacklistTest, OnlyIncludesRequestedIDs) {
  std::string a = AddExtension("a");
  std::string b = AddExtension("b");
  std::string c = AddExtension("c");

  Blacklist blacklist(prefs());
  TestBlacklist tester(&blacklist);
  BlacklistStateFetcherMock* fetcher = new BlacklistStateFetcherMock();
  fetcher->SetState(a, BLACKLISTED_MALWARE);
  fetcher->SetState(b, BLACKLISTED_MALWARE);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  blacklist_db()->Enable();
  blacklist_db()->SetUnsafe(a, b);

  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(a));
  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(b));
  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(c));

  std::set<std::string> blacklisted_ids;
  blacklist.GetMalwareIDs(
      Set(a, c), base::Bind(&Assign<std::set<std::string> >, &blacklisted_ids));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(Set(a), blacklisted_ids);
}

TEST_F(BlacklistTest, SafeBrowsing) {
  std::string a = AddExtension("a");

  Blacklist blacklist(prefs());
  TestBlacklist tester(&blacklist);
  BlacklistStateFetcherMock* fetcher = new BlacklistStateFetcherMock();
  fetcher->SetState(a, BLACKLISTED_MALWARE);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));

  blacklist_db()->SetUnsafe(a);
  // The manager is still disabled at this point, so it won't be blacklisted.
  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));

  blacklist_db()->Enable().NotifyUpdate();
  base::RunLoop().RunUntilIdle();
  // Now it should be.
  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(a));

  blacklist_db()->ClearUnsafe().NotifyUpdate();
  // Safe browsing blacklist empty, now enabled.
  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));
}

// Tests that Blacklist clears the old prefs blacklist on startup.
TEST_F(BlacklistTest, ClearsPreferencesBlacklist) {
  std::string a = AddExtension("a");
  std::string b = AddExtension("b");

  // Blacklist an installed extension.
  prefs()->SetExtensionBlacklisted(a, true);

  // Blacklist some non-installed extensions. This is what the old preferences
  // blacklist looked like.
  std::string c = "cccccccccccccccccccccccccccccccc";
  std::string d = "dddddddddddddddddddddddddddddddd";
  prefs()->SetExtensionBlacklisted(c, true);
  prefs()->SetExtensionBlacklisted(d, true);

  EXPECT_EQ(Set(a, c, d), prefs()->GetBlacklistedExtensions());

  Blacklist blacklist(prefs());
  blacklist.SetBlacklistStateFetcherForTest(new BlacklistStateFetcherMock());

  // Blacklist has been cleared. Only the installed extension "a" left.
  EXPECT_EQ(Set(a), prefs()->GetBlacklistedExtensions());
  EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(a).get());
  EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(b).get());

  // "a" won't actually be *blacklisted* since it doesn't appear in
  // safebrowsing. Blacklist no longer reads from prefs. This is purely a
  // concern of somebody else (currently, ExtensionService).
  std::set<std::string> blacklisted_ids;
  blacklist.GetMalwareIDs(Set(a, b, c, d),
                          base::Bind(&Assign<std::set<std::string> >,
                                     &blacklisted_ids));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(std::set<std::string>(), blacklisted_ids);

  // Prefs are still unaffected for installed extensions, though.
  EXPECT_TRUE(prefs()->IsExtensionBlacklisted(a));
  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(b));
  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(c));
  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(d));
}

// Test getting different blacklist states from Blacklist.
TEST_F(BlacklistTest, GetBlacklistStates) {
  Blacklist blacklist(prefs());

  std::string a = AddExtension("a");
  std::string b = AddExtension("b");
  std::string c = AddExtension("c");
  std::string d = AddExtension("d");
  std::string e = AddExtension("e");

  blacklist_db()->Enable();
  blacklist_db()->SetUnsafe(a, b, c, d);

  // Will be deleted by blacklist destructor.
  BlacklistStateFetcherMock* fetcher = new BlacklistStateFetcherMock();
  fetcher->SetState(a, BLACKLISTED_MALWARE);
  fetcher->SetState(b, BLACKLISTED_SECURITY_VULNERABILITY);
  fetcher->SetState(c, BLACKLISTED_CWS_POLICY_VIOLATION);
  fetcher->SetState(d, BLACKLISTED_POTENTIALLY_UNWANTED);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  Blacklist::BlacklistStateMap states_abc;
  Blacklist::BlacklistStateMap states_bcd;
  blacklist.GetBlacklistedIDs(Set(a, b, c, e),
                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                                         &states_abc));
  blacklist.GetBlacklistedIDs(Set(b, c, d, e),
                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                                         &states_bcd));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(BLACKLISTED_MALWARE, states_abc[a]);
  EXPECT_EQ(BLACKLISTED_SECURITY_VULNERABILITY, states_abc[b]);
  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states_abc[c]);
  EXPECT_EQ(BLACKLISTED_SECURITY_VULNERABILITY, states_bcd[b]);
  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states_bcd[c]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states_bcd[d]);
  EXPECT_EQ(states_abc.end(), states_abc.find(e));
  EXPECT_EQ(states_bcd.end(), states_bcd.find(e));

  int old_request_count = fetcher->request_count();
  Blacklist::BlacklistStateMap states_ad;
  blacklist.GetBlacklistedIDs(Set(a, d, e),
                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                                         &states_ad));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(BLACKLISTED_MALWARE, states_ad[a]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states_ad[d]);
  EXPECT_EQ(states_ad.end(), states_ad.find(e));
  EXPECT_EQ(old_request_count, fetcher->request_count());
}

// Test both Blacklist and BlacklistStateFetcher by requesting the blacklist
// states, sending fake requests and parsing the responses.
TEST_F(BlacklistTest, FetchBlacklistStates) {
  Blacklist blacklist(prefs());

  std::string a = AddExtension("a");
  std::string b = AddExtension("b");
  std::string c = AddExtension("c");

  blacklist_db()->Enable();
  blacklist_db()->SetUnsafe(a, b);

  // Prepare real fetcher.
  BlacklistStateFetcher* fetcher = new BlacklistStateFetcher();
  TestBlacklistStateFetcher fetcher_tester(fetcher);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  fetcher_tester.SetBlacklistVerdict(
      a, ClientCRXListInfoResponse_Verdict_CWS_POLICY_VIOLATION);
  fetcher_tester.SetBlacklistVerdict(
      b, ClientCRXListInfoResponse_Verdict_POTENTIALLY_UNWANTED);

  Blacklist::BlacklistStateMap states;
  blacklist.GetBlacklistedIDs(
      Set(a, b, c), base::Bind(&Assign<Blacklist::BlacklistStateMap>, &states));
  base::RunLoop().RunUntilIdle();

   // Two fetchers should be created.
  EXPECT_TRUE(fetcher_tester.HandleFetcher(0));
  EXPECT_TRUE(fetcher_tester.HandleFetcher(1));

  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states[a]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states[b]);
  EXPECT_EQ(states.end(), states.find(c));

  Blacklist::BlacklistStateMap cached_states;

  blacklist.GetBlacklistedIDs(
      Set(a, b, c), base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                               &cached_states));
  base::RunLoop().RunUntilIdle();

  // No new fetchers.
  EXPECT_FALSE(fetcher_tester.HandleFetcher(2));
  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, cached_states[a]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, cached_states[b]);
  EXPECT_EQ(cached_states.end(), cached_states.find(c));
}

}  // namespace extensions
<commit_msg>Fix uninitialized field.<commit_after>// Copyright 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 "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "chrome/browser/extensions/blacklist.h"
#include "chrome/browser/extensions/blacklist_state_fetcher.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
#include "chrome/browser/extensions/test_blacklist.h"
#include "chrome/browser/extensions/test_blacklist_state_fetcher.h"
#include "chrome/browser/extensions/test_extension_prefs.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace extensions {
namespace {

std::set<std::string> Set(const std::string& a) {
  std::set<std::string> set;
  set.insert(a);
  return set;
}
std::set<std::string> Set(const std::string& a, const std::string& b) {
  std::set<std::string> set = Set(a);
  set.insert(b);
  return set;
}
std::set<std::string> Set(const std::string& a,
                          const std::string& b,
                          const std::string& c) {
  std::set<std::string> set = Set(a, b);
  set.insert(c);
  return set;
}
std::set<std::string> Set(const std::string& a,
                          const std::string& b,
                          const std::string& c,
                          const std::string& d) {
  std::set<std::string> set = Set(a, b, c);
  set.insert(d);
  return set;
}

class BlacklistTest : public testing::Test {
 public:
  BlacklistTest()
      : test_prefs_(base::MessageLoopProxy::current()),
        blacklist_db_(new FakeSafeBrowsingDatabaseManager(false)),
        scoped_blacklist_db_(blacklist_db_) {}

 protected:
  ExtensionPrefs* prefs() {
    return test_prefs_.prefs();
  }

  FakeSafeBrowsingDatabaseManager* blacklist_db() {
    return blacklist_db_.get();
  }

  std::string AddExtension(const std::string& id) {
    return test_prefs_.AddExtension(id)->id();
  }

 private:
  content::TestBrowserThreadBundle browser_thread_bundle_;

  TestExtensionPrefs test_prefs_;

  scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db_;

  Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db_;
};

class BlacklistStateFetcherMock : public BlacklistStateFetcher {
 public:
  BlacklistStateFetcherMock() : request_count_(0) {
  }

  virtual void Request(const std::string& id,
                       const RequestCallback& callback) OVERRIDE {
    request_count_++;

    BlacklistState result = NOT_BLACKLISTED;
    if (ContainsKey(states_, id))
      result = states_[id];

    base::MessageLoopProxy::current()->PostTask(FROM_HERE,
                                                base::Bind(callback, result));
  }

  void SetState(const std::string& id, BlacklistState state) {
    states_[id] = state;
  }

  int request_count() const {
    return request_count_;
  }

 private:
  std::map<std::string, BlacklistState> states_;
  int request_count_;
};

template<typename T>
void Assign(T *to, const T& from) {
  *to = from;
}

}  // namespace

TEST_F(BlacklistTest, OnlyIncludesRequestedIDs) {
  std::string a = AddExtension("a");
  std::string b = AddExtension("b");
  std::string c = AddExtension("c");

  Blacklist blacklist(prefs());
  TestBlacklist tester(&blacklist);
  BlacklistStateFetcherMock* fetcher = new BlacklistStateFetcherMock();
  fetcher->SetState(a, BLACKLISTED_MALWARE);
  fetcher->SetState(b, BLACKLISTED_MALWARE);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  blacklist_db()->Enable();
  blacklist_db()->SetUnsafe(a, b);

  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(a));
  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(b));
  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(c));

  std::set<std::string> blacklisted_ids;
  blacklist.GetMalwareIDs(
      Set(a, c), base::Bind(&Assign<std::set<std::string> >, &blacklisted_ids));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(Set(a), blacklisted_ids);
}

TEST_F(BlacklistTest, SafeBrowsing) {
  std::string a = AddExtension("a");

  Blacklist blacklist(prefs());
  TestBlacklist tester(&blacklist);
  BlacklistStateFetcherMock* fetcher = new BlacklistStateFetcherMock();
  fetcher->SetState(a, BLACKLISTED_MALWARE);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));

  blacklist_db()->SetUnsafe(a);
  // The manager is still disabled at this point, so it won't be blacklisted.
  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));

  blacklist_db()->Enable().NotifyUpdate();
  base::RunLoop().RunUntilIdle();
  // Now it should be.
  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(a));

  blacklist_db()->ClearUnsafe().NotifyUpdate();
  // Safe browsing blacklist empty, now enabled.
  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));
}

// Tests that Blacklist clears the old prefs blacklist on startup.
TEST_F(BlacklistTest, ClearsPreferencesBlacklist) {
  std::string a = AddExtension("a");
  std::string b = AddExtension("b");

  // Blacklist an installed extension.
  prefs()->SetExtensionBlacklisted(a, true);

  // Blacklist some non-installed extensions. This is what the old preferences
  // blacklist looked like.
  std::string c = "cccccccccccccccccccccccccccccccc";
  std::string d = "dddddddddddddddddddddddddddddddd";
  prefs()->SetExtensionBlacklisted(c, true);
  prefs()->SetExtensionBlacklisted(d, true);

  EXPECT_EQ(Set(a, c, d), prefs()->GetBlacklistedExtensions());

  Blacklist blacklist(prefs());
  blacklist.SetBlacklistStateFetcherForTest(new BlacklistStateFetcherMock());

  // Blacklist has been cleared. Only the installed extension "a" left.
  EXPECT_EQ(Set(a), prefs()->GetBlacklistedExtensions());
  EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(a).get());
  EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(b).get());

  // "a" won't actually be *blacklisted* since it doesn't appear in
  // safebrowsing. Blacklist no longer reads from prefs. This is purely a
  // concern of somebody else (currently, ExtensionService).
  std::set<std::string> blacklisted_ids;
  blacklist.GetMalwareIDs(Set(a, b, c, d),
                          base::Bind(&Assign<std::set<std::string> >,
                                     &blacklisted_ids));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(std::set<std::string>(), blacklisted_ids);

  // Prefs are still unaffected for installed extensions, though.
  EXPECT_TRUE(prefs()->IsExtensionBlacklisted(a));
  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(b));
  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(c));
  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(d));
}

// Test getting different blacklist states from Blacklist.
TEST_F(BlacklistTest, GetBlacklistStates) {
  Blacklist blacklist(prefs());

  std::string a = AddExtension("a");
  std::string b = AddExtension("b");
  std::string c = AddExtension("c");
  std::string d = AddExtension("d");
  std::string e = AddExtension("e");

  blacklist_db()->Enable();
  blacklist_db()->SetUnsafe(a, b, c, d);

  // Will be deleted by blacklist destructor.
  BlacklistStateFetcherMock* fetcher = new BlacklistStateFetcherMock();
  fetcher->SetState(a, BLACKLISTED_MALWARE);
  fetcher->SetState(b, BLACKLISTED_SECURITY_VULNERABILITY);
  fetcher->SetState(c, BLACKLISTED_CWS_POLICY_VIOLATION);
  fetcher->SetState(d, BLACKLISTED_POTENTIALLY_UNWANTED);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  Blacklist::BlacklistStateMap states_abc;
  Blacklist::BlacklistStateMap states_bcd;
  blacklist.GetBlacklistedIDs(Set(a, b, c, e),
                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                                         &states_abc));
  blacklist.GetBlacklistedIDs(Set(b, c, d, e),
                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                                         &states_bcd));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(BLACKLISTED_MALWARE, states_abc[a]);
  EXPECT_EQ(BLACKLISTED_SECURITY_VULNERABILITY, states_abc[b]);
  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states_abc[c]);
  EXPECT_EQ(BLACKLISTED_SECURITY_VULNERABILITY, states_bcd[b]);
  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states_bcd[c]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states_bcd[d]);
  EXPECT_EQ(states_abc.end(), states_abc.find(e));
  EXPECT_EQ(states_bcd.end(), states_bcd.find(e));

  int old_request_count = fetcher->request_count();
  Blacklist::BlacklistStateMap states_ad;
  blacklist.GetBlacklistedIDs(Set(a, d, e),
                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                                         &states_ad));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(BLACKLISTED_MALWARE, states_ad[a]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states_ad[d]);
  EXPECT_EQ(states_ad.end(), states_ad.find(e));
  EXPECT_EQ(old_request_count, fetcher->request_count());
}

// Test both Blacklist and BlacklistStateFetcher by requesting the blacklist
// states, sending fake requests and parsing the responses.
TEST_F(BlacklistTest, FetchBlacklistStates) {
  Blacklist blacklist(prefs());

  std::string a = AddExtension("a");
  std::string b = AddExtension("b");
  std::string c = AddExtension("c");

  blacklist_db()->Enable();
  blacklist_db()->SetUnsafe(a, b);

  // Prepare real fetcher.
  BlacklistStateFetcher* fetcher = new BlacklistStateFetcher();
  TestBlacklistStateFetcher fetcher_tester(fetcher);
  blacklist.SetBlacklistStateFetcherForTest(fetcher);

  fetcher_tester.SetBlacklistVerdict(
      a, ClientCRXListInfoResponse_Verdict_CWS_POLICY_VIOLATION);
  fetcher_tester.SetBlacklistVerdict(
      b, ClientCRXListInfoResponse_Verdict_POTENTIALLY_UNWANTED);

  Blacklist::BlacklistStateMap states;
  blacklist.GetBlacklistedIDs(
      Set(a, b, c), base::Bind(&Assign<Blacklist::BlacklistStateMap>, &states));
  base::RunLoop().RunUntilIdle();

   // Two fetchers should be created.
  EXPECT_TRUE(fetcher_tester.HandleFetcher(0));
  EXPECT_TRUE(fetcher_tester.HandleFetcher(1));

  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states[a]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states[b]);
  EXPECT_EQ(states.end(), states.find(c));

  Blacklist::BlacklistStateMap cached_states;

  blacklist.GetBlacklistedIDs(
      Set(a, b, c), base::Bind(&Assign<Blacklist::BlacklistStateMap>,
                               &cached_states));
  base::RunLoop().RunUntilIdle();

  // No new fetchers.
  EXPECT_FALSE(fetcher_tester.HandleFetcher(2));
  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, cached_states[a]);
  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, cached_states[b]);
  EXPECT_EQ(cached_states.end(), cached_states.find(c));
}

}  // namespace extensions
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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/renderer_host/backing_store.h"

#include <stdlib.h>
#include <utility>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "chrome/common/transport_dib.h"
#include "chrome/common/x11_util.h"
#include "chrome/common/x11_util_internal.h"

// X Backing Stores:
//
// Unlike Windows, where the backing store is kept in heap memory, we keep our
// backing store in the X server, as a pixmap. Thus expose events just require
// instructing the X server to copy from the backing store to the window.
//
// The backing store is in the same format as the visual which our main window
// is using. Bitmaps from the renderer are uploaded to the X server, either via
// shared memory or over the wire, and XRENDER is used to convert them to the
// correct format for the backing store.

BackingStore::BackingStore(const gfx::Size& size,
                           Display* display,
                           int depth,
                           void* visual,
                           Drawable root_window,
                           bool use_render,
                           bool use_shared_memory)
    : size_(size),
      display_(display),
      use_shared_memory_(use_shared_memory),
      use_render_(use_render),
      visual_depth_(depth),
      root_window_(root_window) {
  const int width = size.width();
  const int height = size.height();

  COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);

  pixmap_ = XCreatePixmap(display_, root_window, width, height, depth);

  if (use_render_) {
    picture_ = XRenderCreatePicture(
        display_, pixmap_,
        x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)),
        0, NULL);
  } else {
    picture_ = 0;
    pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display, depth);
  }

  pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
}

BackingStore::BackingStore(const gfx::Size& size)
    : size_(size),
      display_(NULL),
      use_shared_memory_(false),
      use_render_(false),
      visual_depth_(-1),
      root_window_(0) {
}

BackingStore::~BackingStore() {
  // In unit tests, display_ may be NULL.
  if (!display_)
    return;

  XRenderFreePicture(display_, picture_);
  XFreePixmap(display_, pixmap_);
  XFreeGC(display_, static_cast<GC>(pixmap_gc_));
}

void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap,
                                           const gfx::Rect &bitmap_rect) {
  const int width = bitmap_rect.width();
  const int height = bitmap_rect.height();
  Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height,
                                visual_depth_);

  XImage image;
  memset(&image, 0, sizeof(image));

  image.width = width;
  image.height = height;
  image.format = ZPixmap;
  image.byte_order = LSBFirst;
  image.bitmap_unit = 8;
  image.bitmap_bit_order = LSBFirst;
  image.red_mask = 0xff;
  image.green_mask = 0xff00;
  image.blue_mask = 0xff0000;

  if (pixmap_bpp_ == 32) {
    // If the X server depth is already 32-bits, then our job is easy.
    image.depth = visual_depth_;
    image.bits_per_pixel = 32;
    image.bytes_per_line = width * 4;
    image.data = static_cast<char*>(bitmap->memory());

    XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);
  } else if (pixmap_bpp_ == 24) {
    // In this case we just need to strip the alpha channel out of each
    // pixel. This is the case which covers VNC servers since they don't
    // support Xrender but typically have 24-bit visuals.
    //
    // It's possible to use some fancy SSE tricks here, but since this is the
    // slow path anyway, we do it slowly.

    uint8_t* bitmap24 = static_cast<uint8_t*>(malloc(3 * width * height));
    const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory());
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        const uint32_t pixel = *(bitmap_in++);
        bitmap24[0] = (pixel >> 16) & 0xff;
        bitmap24[1] = (pixel >> 8) & 0xff;
        bitmap24[2] = pixel & 0xff;
        bitmap24 += 3;
      }
    }

    image.depth = visual_depth_;
    image.bits_per_pixel = 24;
    image.bytes_per_line = width * 3;
    image.data = reinterpret_cast<char*>(bitmap24);

    XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);

    free(bitmap24);
  } else if (pixmap_bpp_ == 16) {
    // Some folks have VNC setups which still use 16-bit visuals and VNC
    // doesn't include Xrender.

    uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * width * height));
    uint16_t* const orig_bitmap16 = bitmap16;
    const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory());
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        const uint32_t pixel = *(bitmap_in++);
        uint16_t out_pixel = (pixel >> 8) & 0xf800 |
                             (pixel >> 5) & 0x07e0 |
                             (pixel >> 3) & 0x001f;
        *(bitmap16++) = out_pixel;
      }
    }

    image.depth = visual_depth_;
    image.bits_per_pixel = 16;
    image.bytes_per_line = width * 2;
    image.data = reinterpret_cast<char*>(orig_bitmap16);

    image.red_mask = 0xf800;
    image.green_mask = 0x07e0;
    image.blue_mask = 0x001f;

    XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);
    free(orig_bitmap16);
  } else {
    CHECK(false) << "Sorry, we don't support your visual depth without "
                    "Xrender support (depth:" << visual_depth_
                 << " bpp:" << pixmap_bpp_ << ")";
  }

  XCopyArea(display_, pixmap /* source */, pixmap_ /* target */,
            static_cast<GC>(pixmap_gc_),
            0, 0 /* source x, y */, bitmap_rect.width(), bitmap_rect.height(),
            bitmap_rect.x(), bitmap_rect.y() /* dest x, y */);

  XFreePixmap(display_, pixmap);
}

void BackingStore::PaintRect(base::ProcessHandle process,
                             TransportDIB* bitmap,
                             const gfx::Rect& bitmap_rect) {
  if (!display_)
    return;

  if (bitmap_rect.IsEmpty())
    return;

  if (!use_render_)
    return PaintRectWithoutXrender(bitmap, bitmap_rect);

  const int width = bitmap_rect.width();
  const int height = bitmap_rect.height();
  Picture picture;
  Pixmap pixmap;

  if (use_shared_memory_) {
    const XID shmseg = bitmap->MapToX(display_);

    XShmSegmentInfo shminfo;
    memset(&shminfo, 0, sizeof(shminfo));
    shminfo.shmseg = shmseg;

    // The NULL in the following is the |data| pointer: this is an artifact of
    // Xlib trying to be helpful, rather than just exposing the X protocol. It
    // assumes that we have the shared memory segment mapped into our memory,
    // which we don't, and it's trying to calculate an offset by taking the
    // difference between the |data| pointer and the address of the mapping in
    // |shminfo|. Since both are NULL, the offset will be calculated to be 0,
    // which is correct for us.
    pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, width,
                              height, 32);
  } else {
    // No shared memory support, we have to copy the bitmap contents to the X
    // server. Xlib wraps the underlying PutImage call behind several layers of
    // functions which try to convert the image into the format which the X
    // server expects. The following values hopefully disable all conversions.
    XImage image;
    memset(&image, 0, sizeof(image));

    image.width = width;
    image.height = height;
    image.depth = 32;
    image.bits_per_pixel = 32;
    image.format = ZPixmap;
    image.byte_order = LSBFirst;
    image.bitmap_unit = 8;
    image.bitmap_bit_order = LSBFirst;
    image.bytes_per_line = width * 4;
    image.red_mask = 0xff;
    image.green_mask = 0xff00;
    image.blue_mask = 0xff0000;
    image.data = static_cast<char*>(bitmap->memory());

    pixmap = XCreatePixmap(display_, root_window_, width, height, 32);
    GC gc = XCreateGC(display_, pixmap, 0, NULL);
    XPutImage(display_, pixmap, gc, &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);
    XFreeGC(display_, gc);
  }

  picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap);
  XRenderComposite(display_, PictOpSrc, picture /* source */, 0 /* mask */,
                   picture_ /* dest */, 0, 0 /* source x, y */,
                   0, 0 /* mask x, y */,
                   bitmap_rect.x(), bitmap_rect.y() /* target x, y */,
                   width, height);

  // In the case of shared memory, we wait for the composite to complete so that
  // we are sure that the X server has finished reading.
  if (use_shared_memory_)
    XSync(display_, False);

  XRenderFreePicture(display_, picture);
  XFreePixmap(display_, pixmap);
}

void BackingStore::ScrollRect(base::ProcessHandle process,
                              TransportDIB* bitmap,
                              const gfx::Rect& bitmap_rect,
                              int dx, int dy,
                              const gfx::Rect& clip_rect,
                              const gfx::Size& view_size) {
  if (!display_)
    return;

  // We only support scrolling in one direction at a time.
  DCHECK(dx == 0 || dy == 0);

  if (dy) {
    // Positive values of |dy| scroll up
    if (abs(dy) < clip_rect.height()) {
      XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
                clip_rect.x() /* source x */,
                std::max(clip_rect.y(), clip_rect.y() - dy),
                clip_rect.width(),
                clip_rect.height() - abs(dy),
                clip_rect.x() /* dest x */,
                std::max(clip_rect.y(), clip_rect.y() + dy) /* dest y */);
    }
  } else if (dx) {
    // Positive values of |dx| scroll right
    if (abs(dx) < clip_rect.width()) {
      XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
                std::max(clip_rect.x(), clip_rect.x() - dx),
                clip_rect.y() /* source y */,
                clip_rect.width() - abs(dx),
                clip_rect.height(),
                std::max(clip_rect.x(), clip_rect.x() + dx) /* dest x */,
                clip_rect.y() /* dest x */);
    }
  }

  PaintRect(process, bitmap, bitmap_rect);
}

void BackingStore::ShowRect(const gfx::Rect& rect, XID target) {
  XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_),
            rect.x(), rect.y(), rect.width(), rect.height(),
            rect.x(), rect.y());
}
<commit_msg>Linux: don't trigger GCC 4.3 warnings<commit_after>// Copyright (c) 2006-2008 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/renderer_host/backing_store.h"

#include <stdlib.h>
#include <utility>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "chrome/common/transport_dib.h"
#include "chrome/common/x11_util.h"
#include "chrome/common/x11_util_internal.h"

// X Backing Stores:
//
// Unlike Windows, where the backing store is kept in heap memory, we keep our
// backing store in the X server, as a pixmap. Thus expose events just require
// instructing the X server to copy from the backing store to the window.
//
// The backing store is in the same format as the visual which our main window
// is using. Bitmaps from the renderer are uploaded to the X server, either via
// shared memory or over the wire, and XRENDER is used to convert them to the
// correct format for the backing store.

BackingStore::BackingStore(const gfx::Size& size,
                           Display* display,
                           int depth,
                           void* visual,
                           Drawable root_window,
                           bool use_render,
                           bool use_shared_memory)
    : size_(size),
      display_(display),
      use_shared_memory_(use_shared_memory),
      use_render_(use_render),
      visual_depth_(depth),
      root_window_(root_window) {
  const int width = size.width();
  const int height = size.height();

  COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);

  pixmap_ = XCreatePixmap(display_, root_window, width, height, depth);

  if (use_render_) {
    picture_ = XRenderCreatePicture(
        display_, pixmap_,
        x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)),
        0, NULL);
  } else {
    picture_ = 0;
    pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display, depth);
  }

  pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
}

BackingStore::BackingStore(const gfx::Size& size)
    : size_(size),
      display_(NULL),
      use_shared_memory_(false),
      use_render_(false),
      visual_depth_(-1),
      root_window_(0) {
}

BackingStore::~BackingStore() {
  // In unit tests, display_ may be NULL.
  if (!display_)
    return;

  XRenderFreePicture(display_, picture_);
  XFreePixmap(display_, pixmap_);
  XFreeGC(display_, static_cast<GC>(pixmap_gc_));
}

void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap,
                                           const gfx::Rect &bitmap_rect) {
  const int width = bitmap_rect.width();
  const int height = bitmap_rect.height();
  Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height,
                                visual_depth_);

  XImage image;
  memset(&image, 0, sizeof(image));

  image.width = width;
  image.height = height;
  image.format = ZPixmap;
  image.byte_order = LSBFirst;
  image.bitmap_unit = 8;
  image.bitmap_bit_order = LSBFirst;
  image.red_mask = 0xff;
  image.green_mask = 0xff00;
  image.blue_mask = 0xff0000;

  if (pixmap_bpp_ == 32) {
    // If the X server depth is already 32-bits, then our job is easy.
    image.depth = visual_depth_;
    image.bits_per_pixel = 32;
    image.bytes_per_line = width * 4;
    image.data = static_cast<char*>(bitmap->memory());

    XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);
  } else if (pixmap_bpp_ == 24) {
    // In this case we just need to strip the alpha channel out of each
    // pixel. This is the case which covers VNC servers since they don't
    // support Xrender but typically have 24-bit visuals.
    //
    // It's possible to use some fancy SSE tricks here, but since this is the
    // slow path anyway, we do it slowly.

    uint8_t* bitmap24 = static_cast<uint8_t*>(malloc(3 * width * height));
    const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory());
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        const uint32_t pixel = *(bitmap_in++);
        bitmap24[0] = (pixel >> 16) & 0xff;
        bitmap24[1] = (pixel >> 8) & 0xff;
        bitmap24[2] = pixel & 0xff;
        bitmap24 += 3;
      }
    }

    image.depth = visual_depth_;
    image.bits_per_pixel = 24;
    image.bytes_per_line = width * 3;
    image.data = reinterpret_cast<char*>(bitmap24);

    XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);

    free(bitmap24);
  } else if (pixmap_bpp_ == 16) {
    // Some folks have VNC setups which still use 16-bit visuals and VNC
    // doesn't include Xrender.

    uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * width * height));
    uint16_t* const orig_bitmap16 = bitmap16;
    const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory());
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        const uint32_t pixel = *(bitmap_in++);
        uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
                             ((pixel >> 5) & 0x07e0) |
                             ((pixel >> 3) & 0x001f);
        *(bitmap16++) = out_pixel;
      }
    }

    image.depth = visual_depth_;
    image.bits_per_pixel = 16;
    image.bytes_per_line = width * 2;
    image.data = reinterpret_cast<char*>(orig_bitmap16);

    image.red_mask = 0xf800;
    image.green_mask = 0x07e0;
    image.blue_mask = 0x001f;

    XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);
    free(orig_bitmap16);
  } else {
    CHECK(false) << "Sorry, we don't support your visual depth without "
                    "Xrender support (depth:" << visual_depth_
                 << " bpp:" << pixmap_bpp_ << ")";
  }

  XCopyArea(display_, pixmap /* source */, pixmap_ /* target */,
            static_cast<GC>(pixmap_gc_),
            0, 0 /* source x, y */, bitmap_rect.width(), bitmap_rect.height(),
            bitmap_rect.x(), bitmap_rect.y() /* dest x, y */);

  XFreePixmap(display_, pixmap);
}

void BackingStore::PaintRect(base::ProcessHandle process,
                             TransportDIB* bitmap,
                             const gfx::Rect& bitmap_rect) {
  if (!display_)
    return;

  if (bitmap_rect.IsEmpty())
    return;

  if (!use_render_)
    return PaintRectWithoutXrender(bitmap, bitmap_rect);

  const int width = bitmap_rect.width();
  const int height = bitmap_rect.height();
  Picture picture;
  Pixmap pixmap;

  if (use_shared_memory_) {
    const XID shmseg = bitmap->MapToX(display_);

    XShmSegmentInfo shminfo;
    memset(&shminfo, 0, sizeof(shminfo));
    shminfo.shmseg = shmseg;

    // The NULL in the following is the |data| pointer: this is an artifact of
    // Xlib trying to be helpful, rather than just exposing the X protocol. It
    // assumes that we have the shared memory segment mapped into our memory,
    // which we don't, and it's trying to calculate an offset by taking the
    // difference between the |data| pointer and the address of the mapping in
    // |shminfo|. Since both are NULL, the offset will be calculated to be 0,
    // which is correct for us.
    pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, width,
                              height, 32);
  } else {
    // No shared memory support, we have to copy the bitmap contents to the X
    // server. Xlib wraps the underlying PutImage call behind several layers of
    // functions which try to convert the image into the format which the X
    // server expects. The following values hopefully disable all conversions.
    XImage image;
    memset(&image, 0, sizeof(image));

    image.width = width;
    image.height = height;
    image.depth = 32;
    image.bits_per_pixel = 32;
    image.format = ZPixmap;
    image.byte_order = LSBFirst;
    image.bitmap_unit = 8;
    image.bitmap_bit_order = LSBFirst;
    image.bytes_per_line = width * 4;
    image.red_mask = 0xff;
    image.green_mask = 0xff00;
    image.blue_mask = 0xff0000;
    image.data = static_cast<char*>(bitmap->memory());

    pixmap = XCreatePixmap(display_, root_window_, width, height, 32);
    GC gc = XCreateGC(display_, pixmap, 0, NULL);
    XPutImage(display_, pixmap, gc, &image,
              0, 0 /* source x, y */, 0, 0 /* dest x, y */,
              width, height);
    XFreeGC(display_, gc);
  }

  picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap);
  XRenderComposite(display_, PictOpSrc, picture /* source */, 0 /* mask */,
                   picture_ /* dest */, 0, 0 /* source x, y */,
                   0, 0 /* mask x, y */,
                   bitmap_rect.x(), bitmap_rect.y() /* target x, y */,
                   width, height);

  // In the case of shared memory, we wait for the composite to complete so that
  // we are sure that the X server has finished reading.
  if (use_shared_memory_)
    XSync(display_, False);

  XRenderFreePicture(display_, picture);
  XFreePixmap(display_, pixmap);
}

void BackingStore::ScrollRect(base::ProcessHandle process,
                              TransportDIB* bitmap,
                              const gfx::Rect& bitmap_rect,
                              int dx, int dy,
                              const gfx::Rect& clip_rect,
                              const gfx::Size& view_size) {
  if (!display_)
    return;

  // We only support scrolling in one direction at a time.
  DCHECK(dx == 0 || dy == 0);

  if (dy) {
    // Positive values of |dy| scroll up
    if (abs(dy) < clip_rect.height()) {
      XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
                clip_rect.x() /* source x */,
                std::max(clip_rect.y(), clip_rect.y() - dy),
                clip_rect.width(),
                clip_rect.height() - abs(dy),
                clip_rect.x() /* dest x */,
                std::max(clip_rect.y(), clip_rect.y() + dy) /* dest y */);
    }
  } else if (dx) {
    // Positive values of |dx| scroll right
    if (abs(dx) < clip_rect.width()) {
      XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
                std::max(clip_rect.x(), clip_rect.x() - dx),
                clip_rect.y() /* source y */,
                clip_rect.width() - abs(dx),
                clip_rect.height(),
                std::max(clip_rect.x(), clip_rect.x() + dx) /* dest x */,
                clip_rect.y() /* dest x */);
    }
  }

  PaintRect(process, bitmap, bitmap_rect);
}

void BackingStore::ShowRect(const gfx::Rect& rect, XID target) {
  XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_),
            rect.x(), rect.y(), rect.width(), rect.height(),
            rect.x(), rect.y());
}
<|endoftext|>