<commit_before>#include <string>
#include <math.h>
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>
#include <boost/shared_ptr.hpp>

using namespace std;

// for odometry
ros::Time currentTime;
ros::Time lastTime;
ros::Publisher odomPub;
boost::shared_ptr<tf::TransformBroadcaster> odomBroadcaster;
double x = 0;
double y = 0;
double theta = 0;
double vx = 0;
double vy = 0;
double vtheta = 0;

void velocityCallback(const geometry_msgs::Twist& msg) {
	//ROS_INFO("%f", msg.linear.x);

	// Store odometry input values
	lastTime = currentTime;
	currentTime = ros::Time::now();
	vx = msg.linear.x;
	vy = msg.linear.y;
	vtheta = msg.angular.z * 10; // absolutely uneducated guess
}

void publishOdometry(const ros::TimerEvent&) {
	// Source: http://wiki.ros.org/navigation/Tutorials/RobotSetup/Odom
	// Compute input values
	double dt = (currentTime - lastTime).toSec();
	double dx = (vx * cos(theta) - vy * sin(theta)) * dt * 1.164 /* m/s robot speed*/;
	double dy = (vx * sin(theta) - vy * cos(theta)) * dt * 1.164 /*m/s*/;
	double dtheta = vtheta * dt;
	x += dx;
	y += dy;
	theta += dtheta;

	// Transform frame
	//since all odometry is 6DOF we'll need a quaternion created from yaw
	geometry_msgs::Quaternion odomQuat = tf::createQuaternionMsgFromYaw(theta);

	geometry_msgs::TransformStamped odomTrans;
	odomTrans.header.stamp = currentTime;
	odomTrans.header.frame_id = "odom";
	odomTrans.child_frame_id = "base_link";

	odomTrans.transform.translation.x = x;
	odomTrans.transform.translation.y = y;
	odomTrans.transform.translation.z = 0.0;
	odomTrans.transform.rotation = odomQuat;

	odomBroadcaster->sendTransform(odomTrans);

	// Odometry message
	nav_msgs::Odometry odom;
	odom.header.stamp = currentTime;
	odom.header.frame_id = "odom";
	odom.child_frame_id = "base_link";

	//set the position
	odom.pose.pose.position.x = x;
	odom.pose.pose.position.y = y;
	odom.pose.pose.position.z = 0.0;
	odom.pose.pose.orientation = odomQuat;

	//set the velocity
	odom.twist.twist.linear.x = vx;
	odom.twist.twist.linear.y = vy;
	odom.twist.twist.angular.z = vtheta;

	odomPub.publish(odom);
}

int main(int argc, char **argv) {
	ros::init(argc, argv, "odometrytest");
	ros::NodeHandle n;
	currentTime = ros::Time::now();
	lastTime = ros::Time::now();
	ros::Subscriber sub = n.subscribe("turtle1/cmd_vel", 1, velocityCallback);
	odomPub = n.advertise<nav_msgs::Odometry>("odom", 50);
	odomBroadcaster = boost::make_shared<tf::TransformBroadcaster>();
	ros::Timer odoTimer = n.createTimer(ros::Duration(1.0/10.0/*10 Hz*/), publishOdometry);
	ROS_INFO("odometrytest up and running.");
	ros::spin();
	return 0;
}
<commit_msg>Remove obsolete odometrytest.<commit_after><|endoftext|>


<commit_before>#include "SliderWnd.h"

#include <windowsx.h>

#include "SliderKnob.h"

SliderWnd::SliderWnd(LPCWSTR className, LPCWSTR title, HINSTANCE hInstance) :
MeterWnd(className, title, hInstance),
_dragging(false) {
    long styles = GetWindowLongPtr(_hWnd, GWL_EXSTYLE);
    styles &= ~(WS_EX_NOACTIVATE | WS_EX_TRANSPARENT);
    SetWindowLongPtr(_hWnd, GWL_EXSTYLE, styles | WS_EX_TOPMOST);
}

void SliderWnd::Show() {
    PositionWindow();
    MeterWnd::Show();
}

void SliderWnd::Knob(SliderKnob *knob) {
    _knob = knob;
    AddMeter(knob);
}

void SliderWnd::PositionWindow() {
    POINT p;
    GetCursorPos(&p);

    HMONITOR monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST);
    MONITORINFO mInfo = {};
    mInfo.cbSize = sizeof(mInfo);
    GetMonitorInfo(monitor, &mInfo);
    RECT mRect = mInfo.rcWork;

    /* Default location is the bottom of the window centered above cursor. */
    POINT loc;
    loc.x = p.x - _size.cx / 2;
    loc.y = p.y - _size.cy;

    /* Reposition the window if it's falling off the monitor somewhere. */
    if (loc.y < mRect.top) {
        loc.y = mRect.top;
    }

    if (loc.x < mRect.left) {
        loc.x = mRect.left;
    }

    if (p.y > mRect.bottom) {
        loc.y = mRect.bottom - _size.cy;
    }

    if (p.x > mRect.right - _size.cx) {
        loc.x = mRect.right - _size.cx;
    }

    Move(loc.x, loc.y);
}

bool SliderWnd::MouseOverKnob(int x, int y) {
    if (x >= _knob->X() && x <= _knob->X() + _knob->Width()
        && y >= _knob->Y() && y <= _knob->Y() + _knob->Height()) {
        return true;
    } else {
        return false;
    }
}

bool SliderWnd::MouseOverTrack(int x, int y) {
    if (x >= _knob->TrackX()
        && x <= _knob->TrackX() + _knob->TrackWidth()
        && y >= _knob->TrackY()
        && y <= _knob->TrackY() + _knob->TrackHeight()) {

        return true;
    } else {
        return false;
    }
}

void SliderWnd::UpdateKnob(int x, int y) {
    int newX;
    int knobMax = _knob->TrackX() + _knob->TrackWidth() - _knob->Width();

    if (x > knobMax) {
        newX = knobMax;
    } else if (x - _dragOffset < _knob->TrackX()) {
        newX = _knob->TrackX();
    } else {
        newX = x - _dragOffset;
    }

    if (_knob->X() != newX) {
        _knob->X(newX);
        Update();
    }
}

/*    case WM_NCHITTEST: {
        LRESULT hit = DefWindowProc(_hWnd, message, wParam, lParam);
        /* Make the client area appear to be the window title bar:
        if (hit == HTCLIENT) {
            hit = HTCAPTION;
        }
        return hit;
    }
*/

LRESULT SliderWnd::WndProc(UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_KILLFOCUS:
        Hide();
        break;

    case WM_MOUSEMOVE:
        if (_dragging) {
            int x = GET_X_LPARAM(lParam);
            int y = GET_Y_LPARAM(lParam);
            UpdateKnob(x, y);
        }
        break;

    case WM_LBUTTONDOWN: {
        if (_knob == NULL) {
            break;
        }

        int x = GET_X_LPARAM(lParam);
        int y = GET_Y_LPARAM(lParam);

        if (MouseOverKnob(x, y)) {
            _dragging = true;
            _dragOffset = x - _knob->X();
            SetCapture(_hWnd);
        } else if (MouseOverTrack(x, y)) {
            /* Simulate the mouse dragging to the clicked location: */
            UpdateKnob(x, y);
        }

        break;
    }

    case WM_LBUTTONUP:
        _dragging = false;
        ReleaseCapture();
        break;
    }

    return MeterWnd::WndProc(message, wParam, lParam);
}

<commit_msg>Report the slider changes to the OSD<commit_after>#include "SliderWnd.h"

#include <windowsx.h>

#include "SliderKnob.h"

SliderWnd::SliderWnd(LPCWSTR className, LPCWSTR title, HINSTANCE hInstance) :
MeterWnd(className, title, hInstance),
_dragging(false) {
    long styles = GetWindowLongPtr(_hWnd, GWL_EXSTYLE);
    styles &= ~(WS_EX_NOACTIVATE | WS_EX_TRANSPARENT);
    SetWindowLongPtr(_hWnd, GWL_EXSTYLE, styles | WS_EX_TOPMOST);
}

void SliderWnd::Show() {
    PositionWindow();
    MeterWnd::Show();
}

void SliderWnd::Knob(SliderKnob *knob) {
    _knob = knob;
    AddMeter(knob);
}

void SliderWnd::PositionWindow() {
    POINT p;
    GetCursorPos(&p);

    HMONITOR monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST);
    MONITORINFO mInfo = {};
    mInfo.cbSize = sizeof(mInfo);
    GetMonitorInfo(monitor, &mInfo);
    RECT mRect = mInfo.rcWork;

    /* Default location is the bottom of the window centered above cursor. */
    POINT loc;
    loc.x = p.x - _size.cx / 2;
    loc.y = p.y - _size.cy;

    /* Reposition the window if it's falling off the monitor somewhere. */
    if (loc.y < mRect.top) {
        loc.y = mRect.top;
    }

    if (loc.x < mRect.left) {
        loc.x = mRect.left;
    }

    if (p.y > mRect.bottom) {
        loc.y = mRect.bottom - _size.cy;
    }

    if (p.x > mRect.right - _size.cx) {
        loc.x = mRect.right - _size.cx;
    }

    Move(loc.x, loc.y);
}

bool SliderWnd::MouseOverKnob(int x, int y) {
    if (x >= _knob->X() && x <= _knob->X() + _knob->Width()
        && y >= _knob->Y() && y <= _knob->Y() + _knob->Height()) {
        return true;
    } else {
        return false;
    }
}

bool SliderWnd::MouseOverTrack(int x, int y) {
    if (x >= _knob->TrackX()
        && x <= _knob->TrackX() + _knob->TrackWidth()
        && y >= _knob->TrackY()
        && y <= _knob->TrackY() + _knob->TrackHeight()) {

        return true;
    } else {
        return false;
    }
}

void SliderWnd::UpdateKnob(int x, int y) {
    int newX;
    int knobMax = _knob->TrackX() + _knob->TrackWidth() - _knob->Width();

    if (x > knobMax) {
        newX = knobMax;
    } else if (x - _dragOffset < _knob->TrackX()) {
        newX = _knob->TrackX();
    } else {
        newX = x - _dragOffset;
    }

    if (_knob->X() != newX) {
        _knob->X(newX);
        SliderChanged();
        Update();
    }
}

/*    case WM_NCHITTEST: {
        LRESULT hit = DefWindowProc(_hWnd, message, wParam, lParam);
        /* Make the client area appear to be the window title bar:
        if (hit == HTCLIENT) {
            hit = HTCAPTION;
        }
        return hit;
    }
*/

LRESULT SliderWnd::WndProc(UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_KILLFOCUS:
        Hide();
        break;

    case WM_MOUSEMOVE:
        if (_dragging) {
            int x = GET_X_LPARAM(lParam);
            int y = GET_Y_LPARAM(lParam);
            UpdateKnob(x, y);
        }
        break;

    case WM_LBUTTONDOWN: {
        if (_knob == NULL) {
            break;
        }

        int x = GET_X_LPARAM(lParam);
        int y = GET_Y_LPARAM(lParam);

        if (MouseOverKnob(x, y)) {
            _dragging = true;
            _dragOffset = x - _knob->X();
            SetCapture(_hWnd);
        } else if (MouseOverTrack(x, y)) {
            /* Simulate the mouse dragging to the clicked location: */
            UpdateKnob(x, y);
        }

        break;
    }

    case WM_LBUTTONUP:
        _dragging = false;
        ReleaseCapture();
        break;
    }

    return MeterWnd::WndProc(message, wParam, lParam);
}

<|endoftext|>


<commit_before>// Copyright (c) 2010 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/frame/panel_controller.h"

#include <vector>

#include "app/resource_bundle.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/common/notification_service.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "cros/chromeos_wm_ipc_enums.h"
#include "views/controls/button/image_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/event.h"
#include "views/view.h"
#include "views/widget/widget_gtk.h"
#include "views/window/window.h"

namespace chromeos {

static int close_button_width;
static int close_button_height;
static SkBitmap* close_button_n;
static SkBitmap* close_button_m;
static SkBitmap* close_button_h;
static SkBitmap* close_button_p;
static gfx::Font* active_font = NULL;
static gfx::Font* inactive_font = NULL;

namespace {

const int kTitleWidth = 200;
const int kTitleHeight = 20;
const int kTitleIconSize = 16;
const int kTitleWidthPad = 2;
const int kTitleHeightPad = 1;
const int kButtonPad = 4;

const SkColor kActiveGradientStart = 0xffebeff9;
const SkColor kActiveGradientEnd = 0xffb3c4f6;
const SkColor kInactiveGradientStart = 0xfff2f2f2;
const SkColor kInactiveGradientEnd = 0xfff2f2f2;
const SkColor kActiveColor = SK_ColorBLACK;
const SkColor kInactiveColor = 0xff333333;
const SkColor kCloseButtonColor = SK_ColorBLACK;

static bool resources_initialized;
static void InitializeResources() {
  if (resources_initialized) {
    return;
  }

  resources_initialized = true;
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  inactive_font = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont));
  active_font = new gfx::Font(inactive_font->DeriveFont(0, gfx::Font::BOLD));
  close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
  close_button_m = rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK);
  close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
  close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
  close_button_width = close_button_n->width();
  close_button_height = close_button_n->height();
}

}  // namespace

PanelController::PanelController(Delegate* delegate,
                                 GtkWindow* window)
    :  delegate_(delegate),
       panel_(window),
       panel_xid_(x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(panel_))),
       title_window_(NULL),
       title_(NULL),
       title_content_(NULL),
       expanded_(true),
       mouse_down_(false),
       dragging_(false),
       client_event_handler_id_(0) {
}

void PanelController::Init(bool initial_focus,
                           const gfx::Rect& window_bounds,
                           XID creator_xid,
                           WmIpcPanelUserResizeType resize_type) {
  gfx::Rect title_bounds(
      0, 0, window_bounds.width(), kTitleHeight);

  title_window_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
  title_window_->Init(NULL, title_bounds);
  gtk_widget_set_size_request(title_window_->GetNativeView(),
                              title_bounds.width(), title_bounds.height());
  title_ = title_window_->GetNativeView();
  title_xid_ = x11_util::GetX11WindowFromGtkWidget(title_);

  WmIpc::instance()->SetWindowType(
      title_,
      WM_IPC_WINDOW_CHROME_PANEL_TITLEBAR,
      NULL);
  std::vector<int> type_params;
  type_params.push_back(title_xid_);
  type_params.push_back(expanded_ ? 1 : 0);
  type_params.push_back(initial_focus ? 1 : 0);
  type_params.push_back(creator_xid);
  type_params.push_back(resize_type);
  WmIpc::instance()->SetWindowType(
      GTK_WIDGET(panel_),
      WM_IPC_WINDOW_CHROME_PANEL_CONTENT,
      &type_params);

  client_event_handler_id_ = g_signal_connect(
      panel_, "client-event", G_CALLBACK(OnPanelClientEvent), this);

  title_content_ = new TitleContentView(this);
  title_window_->SetContentsView(title_content_);
  UpdateTitleBar();
  title_window_->Show();
}

void PanelController::UpdateTitleBar() {
  if (!delegate_ || !title_window_)
    return;
  DCHECK(title_content_);
  title_content_->title_label()->SetText(
      UTF16ToWideHack(delegate_->GetPanelTitle()));
  title_content_->title_icon()->SetImage(delegate_->GetPanelIcon());
}

bool PanelController::TitleMousePressed(const views::MouseEvent& event) {
  if (!event.IsOnlyLeftMouseButton()) {
    return false;
  }
  GdkEvent* gdk_event = gtk_get_current_event();
  if (gdk_event->type != GDK_BUTTON_PRESS) {
    gdk_event_free(gdk_event);
    NOTREACHED();
    return false;
  }
  DCHECK(title_);
  // Get the last titlebar width that we saw in a ConfigureNotify event -- we
  // need to give drag positions in terms of the top-right corner of the
  // titlebar window.  See WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED's declaration
  // for details.
  gint title_width = 1;
  gtk_window_get_size(GTK_WINDOW(title_), &title_width, NULL);

  GdkEventButton last_button_event = gdk_event->button;
  mouse_down_ = true;
  mouse_down_abs_x_ = last_button_event.x_root;
  mouse_down_abs_y_ = last_button_event.y_root;
  mouse_down_offset_x_ = event.x() - title_width;
  mouse_down_offset_y_ = event.y();
  dragging_ = false;
  gdk_event_free(gdk_event);
  return true;
}

void PanelController::TitleMouseReleased(
    const views::MouseEvent& event, bool canceled) {
  if (!event.IsLeftMouseButton()) {
    return;
  }
  // Only handle clicks that started in our window.
  if (!mouse_down_) {
    return;
  }

  mouse_down_ = false;
  if (!dragging_) {
    SetState(expanded_ ?
             PanelController::MINIMIZED : PanelController::EXPANDED);
  } else {
    WmIpc::Message msg(WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAG_COMPLETE);
    msg.set_param(0, panel_xid_);
    WmIpc::instance()->SendMessage(msg);
    dragging_ = false;
  }
}

void PanelController::SetState(State state) {
  WmIpc::Message msg(WM_IPC_MESSAGE_WM_SET_PANEL_STATE);
  msg.set_param(0, panel_xid_);
  msg.set_param(1, state == EXPANDED);
  WmIpc::instance()->SendMessage(msg);
}

bool PanelController::TitleMouseDragged(const views::MouseEvent& event) {
  if (!mouse_down_) {
    return false;
  }

  GdkEvent* gdk_event = gtk_get_current_event();
  if (gdk_event->type != GDK_MOTION_NOTIFY) {
    gdk_event_free(gdk_event);
    NOTREACHED();
    return false;
  }
  GdkEventMotion last_motion_event = gdk_event->motion;
  if (!dragging_) {
    if (views::View::ExceededDragThreshold(
        last_motion_event.x_root - mouse_down_abs_x_,
        last_motion_event.y_root - mouse_down_abs_y_)) {
      dragging_ = true;
    }
  }
  if (dragging_) {
    WmIpc::Message msg(WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED);
    msg.set_param(0, panel_xid_);
    msg.set_param(1, last_motion_event.x_root - mouse_down_offset_x_);
    msg.set_param(2, last_motion_event.y_root - mouse_down_offset_y_);
    WmIpc::instance()->SendMessage(msg);
  }
  gdk_event_free(gdk_event);
  return true;
}

// static
bool PanelController::OnPanelClientEvent(
    GtkWidget* widget,
    GdkEventClient* event,
    PanelController* panel_controller) {
  return panel_controller->PanelClientEvent(event);
}

void PanelController::OnFocusIn() {
  if (title_window_)
    title_content_->OnFocusIn();
}

void PanelController::OnFocusOut() {
  if (title_window_)
    title_content_->OnFocusOut();
}

bool PanelController::PanelClientEvent(GdkEventClient* event) {
  WmIpc::Message msg;
  WmIpc::instance()->DecodeMessage(*event, &msg);
  if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_PANEL_STATE) {
    bool new_state = msg.param(0);
    if (expanded_ != new_state) {
      expanded_ = new_state;
      State state = new_state ? EXPANDED : MINIMIZED;
      NotificationService::current()->Notify(
          NotificationType::PANEL_STATE_CHANGED,
          Source<PanelController>(this),
          Details<State>(&state));
    }
  }
  return true;
}

void PanelController::Close() {
  if (client_event_handler_id_ > 0) {
    g_signal_handler_disconnect(panel_, client_event_handler_id_);
    client_event_handler_id_ = 0;
  }
  // ignore if the title window is already closed.
  if (title_window_) {
    title_window_->Close();
    title_window_ = NULL;
    title_ = NULL;
    title_content_->OnClose();
    title_content_ = NULL;
  }
}

void PanelController::OnCloseButtonPressed() {
  DCHECK(title_content_);
  if (title_window_) {
    if (delegate_)
      delegate_->ClosePanel();
    Close();
  }
}

PanelController::TitleContentView::TitleContentView(
    PanelController* panel_controller)
        : panel_controller_(panel_controller) {
  InitializeResources();
  close_button_ = new views::ImageButton(this);
  close_button_->SetImage(views::CustomButton::BS_NORMAL, close_button_n);
  close_button_->SetImage(views::CustomButton::BS_HOT, close_button_h);
  close_button_->SetImage(views::CustomButton::BS_PUSHED, close_button_p);
  close_button_->SetBackground(
      kCloseButtonColor, close_button_n, close_button_m);
  AddChildView(close_button_);

  title_icon_ = new views::ImageView();
  AddChildView(title_icon_);
  title_label_ = new views::Label(std::wstring());
  title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  AddChildView(title_label_);

  // Default to inactive
  OnFocusOut();
}

void PanelController::TitleContentView::Layout() {
  int close_button_x = bounds().width() - (close_button_width + kButtonPad);
  close_button_->SetBounds(
      close_button_x,
      (bounds().height() - close_button_height) / 2,
      close_button_width,
      close_button_height);
  title_icon_->SetBounds(
      kTitleWidthPad,
      kTitleHeightPad * 2,
      kTitleIconSize,
      kTitleIconSize);
  int title_x = kTitleWidthPad * 2 + kTitleIconSize;
  title_label_->SetBounds(
      title_x,
      kTitleHeightPad,
      close_button_x - (title_x + kButtonPad),
      bounds().height() - kTitleHeightPad);
}

bool PanelController::TitleContentView::OnMousePressed(
    const views::MouseEvent& event) {
  DCHECK(panel_controller_) << "OnMousePressed after Close";
  return panel_controller_->TitleMousePressed(event);
}

void PanelController::TitleContentView::OnMouseReleased(
    const views::MouseEvent& event, bool canceled) {
  DCHECK(panel_controller_) << "MouseReleased after Close";
  return panel_controller_->TitleMouseReleased(event, canceled);
}

bool PanelController::TitleContentView::OnMouseDragged(
    const views::MouseEvent& event) {
  DCHECK(panel_controller_) << "MouseDragged after Close";
  return panel_controller_->TitleMouseDragged(event);
}

void PanelController::TitleContentView::OnFocusIn() {
  set_background(views::Background::CreateVerticalGradientBackground(
      kActiveGradientStart, kActiveGradientEnd));
  title_label_->SetColor(kActiveColor);
  title_label_->SetFont(*active_font);
  Layout();
  SchedulePaint();
}

void PanelController::TitleContentView::OnFocusOut() {
  set_background(views::Background::CreateVerticalGradientBackground(
      kInactiveGradientStart, kInactiveGradientEnd));
  title_label_->SetColor(kInactiveColor);
  title_label_->SetFont(*inactive_font);
  Layout();
  SchedulePaint();
}

void PanelController::TitleContentView::OnClose() {
  panel_controller_ = NULL;
}

void PanelController::TitleContentView::ButtonPressed(
    views::Button* sender, const views::Event& event) {
  if (panel_controller_ && sender == close_button_)
    panel_controller_->OnCloseButtonPressed();
}

}  // namespace chromeos
<commit_msg>Update panel title to match current mock. The corners become slightly rounded. This will look a bit broken until the window manager changes its shadows to match. BUG=chromiumos:5156 TEST=Panels should have rounded corners, cleaner spacing of ui elements, and      shouldn't change when they have the focus.<commit_after>// Copyright (c) 2010 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/frame/panel_controller.h"

#include <vector>

#include "app/resource_bundle.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/common/notification_service.h"
#include "cros/chromeos_wm_ipc_enums.h"
#include "grit/app_resources.h"
#include "gfx/canvas_skia.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
#include "views/controls/button/image_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/event.h"
#include "views/painter.h"
#include "views/view.h"
#include "views/widget/widget_gtk.h"
#include "views/window/window.h"

namespace chromeos {

static int close_button_width;
static int close_button_height;
static SkBitmap* close_button_n;
static SkBitmap* close_button_m;
static SkBitmap* close_button_h;
static SkBitmap* close_button_p;
static gfx::Font* active_font = NULL;
static gfx::Font* inactive_font = NULL;
static views::Background* title_background;

namespace {

const int kTitleHeight = 24;
const int kTitleIconSize = 16;
const int kTitleWidthPad = 4;
const int kTitleHeightPad = 4;
const int kTitleCornerRadius = 4;
const int kTitleCloseButtonPad = 6;
const SkColor kTitleActiveGradientStart = SK_ColorWHITE;
const SkColor kTitleActiveGradientEnd = 0xffe7edf1;
const SkColor kTitleActiveColor = SK_ColorBLACK;
const SkColor kTitleInactiveColor = SK_ColorBLACK;
const SkColor kTitleCloseButtonColor = SK_ColorBLACK;

// Used to draw the background of the panel title window.
class TitleBackgroundPainter : public views::Painter {
  virtual void Paint(int w, int h, gfx::Canvas* canvas) {
    SkRect rect = {0, 0, w, h};
    SkPath path;
    SkScalar corners[] = {
        kTitleCornerRadius, kTitleCornerRadius,
        kTitleCornerRadius, kTitleCornerRadius,
        0, 0,
        0, 0
    };
    path.addRoundRect(rect, corners);
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setFlags(SkPaint::kAntiAlias_Flag);
    SkPoint p[2] = {{0, 0}, {0, h}};
    SkColor colors[2] = {kTitleActiveGradientStart, kTitleActiveGradientEnd};
    SkShader* s = SkGradientShader::CreateLinear(
        p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
    paint.setShader(s);
    // Need to unref shader, otherwise never deleted.
    s->unref();
    canvas->AsCanvasSkia()->drawPath(path, paint);
  }
};

static bool resources_initialized;
static void InitializeResources() {
  if (resources_initialized) {
    return;
  }

  resources_initialized = true;
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont);
  // Title fonts are the same for active and inactive.
  inactive_font = new gfx::Font(base_font.DeriveFont(0, gfx::Font::BOLD));
  active_font = inactive_font;
  close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
  close_button_m = rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK);
  close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
  close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
  close_button_width = close_button_n->width();
  close_button_height = close_button_n->height();

  title_background = views::Background::CreateBackgroundPainter(
      true, new TitleBackgroundPainter());
}

}  // namespace

PanelController::PanelController(Delegate* delegate,
                                 GtkWindow* window)
    :  delegate_(delegate),
       panel_(window),
       panel_xid_(x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(panel_))),
       title_window_(NULL),
       title_(NULL),
       title_content_(NULL),
       expanded_(true),
       mouse_down_(false),
       dragging_(false),
       client_event_handler_id_(0) {
}

void PanelController::Init(bool initial_focus,
                           const gfx::Rect& window_bounds,
                           XID creator_xid,
                           WmIpcPanelUserResizeType resize_type) {
  gfx::Rect title_bounds(0, 0, window_bounds.width(), kTitleHeight);

  title_window_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
  title_window_->MakeTransparent();
  title_window_->Init(NULL, title_bounds);
  gtk_widget_set_size_request(title_window_->GetNativeView(),
                              title_bounds.width(), title_bounds.height());
  title_ = title_window_->GetNativeView();
  title_xid_ = x11_util::GetX11WindowFromGtkWidget(title_);

  WmIpc::instance()->SetWindowType(
      title_,
      WM_IPC_WINDOW_CHROME_PANEL_TITLEBAR,
      NULL);
  std::vector<int> type_params;
  type_params.push_back(title_xid_);
  type_params.push_back(expanded_ ? 1 : 0);
  type_params.push_back(initial_focus ? 1 : 0);
  type_params.push_back(creator_xid);
  type_params.push_back(resize_type);
  WmIpc::instance()->SetWindowType(
      GTK_WIDGET(panel_),
      WM_IPC_WINDOW_CHROME_PANEL_CONTENT,
      &type_params);

  client_event_handler_id_ = g_signal_connect(
      panel_, "client-event", G_CALLBACK(OnPanelClientEvent), this);

  title_content_ = new TitleContentView(this);
  title_window_->SetContentsView(title_content_);
  UpdateTitleBar();
  title_window_->Show();
}

void PanelController::UpdateTitleBar() {
  if (!delegate_ || !title_window_)
    return;
  DCHECK(title_content_);
  title_content_->title_label()->SetText(
      UTF16ToWideHack(delegate_->GetPanelTitle()));
  title_content_->title_icon()->SetImage(delegate_->GetPanelIcon());
}

bool PanelController::TitleMousePressed(const views::MouseEvent& event) {
  if (!event.IsOnlyLeftMouseButton()) {
    return false;
  }
  GdkEvent* gdk_event = gtk_get_current_event();
  if (gdk_event->type != GDK_BUTTON_PRESS) {
    gdk_event_free(gdk_event);
    NOTREACHED();
    return false;
  }
  DCHECK(title_);
  // Get the last titlebar width that we saw in a ConfigureNotify event -- we
  // need to give drag positions in terms of the top-right corner of the
  // titlebar window.  See WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED's declaration
  // for details.
  gint title_width = 1;
  gtk_window_get_size(GTK_WINDOW(title_), &title_width, NULL);

  GdkEventButton last_button_event = gdk_event->button;
  mouse_down_ = true;
  mouse_down_abs_x_ = last_button_event.x_root;
  mouse_down_abs_y_ = last_button_event.y_root;
  mouse_down_offset_x_ = event.x() - title_width;
  mouse_down_offset_y_ = event.y();
  dragging_ = false;
  gdk_event_free(gdk_event);
  return true;
}

void PanelController::TitleMouseReleased(
    const views::MouseEvent& event, bool canceled) {
  if (!event.IsLeftMouseButton()) {
    return;
  }
  // Only handle clicks that started in our window.
  if (!mouse_down_) {
    return;
  }

  mouse_down_ = false;
  if (!dragging_) {
    SetState(expanded_ ?
             PanelController::MINIMIZED : PanelController::EXPANDED);
  } else {
    WmIpc::Message msg(WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAG_COMPLETE);
    msg.set_param(0, panel_xid_);
    WmIpc::instance()->SendMessage(msg);
    dragging_ = false;
  }
}

void PanelController::SetState(State state) {
  WmIpc::Message msg(WM_IPC_MESSAGE_WM_SET_PANEL_STATE);
  msg.set_param(0, panel_xid_);
  msg.set_param(1, state == EXPANDED);
  WmIpc::instance()->SendMessage(msg);
}

bool PanelController::TitleMouseDragged(const views::MouseEvent& event) {
  if (!mouse_down_) {
    return false;
  }

  GdkEvent* gdk_event = gtk_get_current_event();
  if (gdk_event->type != GDK_MOTION_NOTIFY) {
    gdk_event_free(gdk_event);
    NOTREACHED();
    return false;
  }
  GdkEventMotion last_motion_event = gdk_event->motion;
  if (!dragging_) {
    if (views::View::ExceededDragThreshold(
        last_motion_event.x_root - mouse_down_abs_x_,
        last_motion_event.y_root - mouse_down_abs_y_)) {
      dragging_ = true;
    }
  }
  if (dragging_) {
    WmIpc::Message msg(WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED);
    msg.set_param(0, panel_xid_);
    msg.set_param(1, last_motion_event.x_root - mouse_down_offset_x_);
    msg.set_param(2, last_motion_event.y_root - mouse_down_offset_y_);
    WmIpc::instance()->SendMessage(msg);
  }
  gdk_event_free(gdk_event);
  return true;
}

// static
bool PanelController::OnPanelClientEvent(
    GtkWidget* widget,
    GdkEventClient* event,
    PanelController* panel_controller) {
  return panel_controller->PanelClientEvent(event);
}

void PanelController::OnFocusIn() {
  if (title_window_)
    title_content_->OnFocusIn();
}

void PanelController::OnFocusOut() {
  if (title_window_)
    title_content_->OnFocusOut();
}

bool PanelController::PanelClientEvent(GdkEventClient* event) {
  WmIpc::Message msg;
  WmIpc::instance()->DecodeMessage(*event, &msg);
  if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_PANEL_STATE) {
    bool new_state = msg.param(0);
    if (expanded_ != new_state) {
      expanded_ = new_state;
      State state = new_state ? EXPANDED : MINIMIZED;
      NotificationService::current()->Notify(
          NotificationType::PANEL_STATE_CHANGED,
          Source<PanelController>(this),
          Details<State>(&state));
    }
  }
  return true;
}

void PanelController::Close() {
  if (client_event_handler_id_ > 0) {
    g_signal_handler_disconnect(panel_, client_event_handler_id_);
    client_event_handler_id_ = 0;
  }
  // ignore if the title window is already closed.
  if (title_window_) {
    title_window_->Close();
    title_window_ = NULL;
    title_ = NULL;
    title_content_->OnClose();
    title_content_ = NULL;
  }
}

void PanelController::OnCloseButtonPressed() {
  DCHECK(title_content_);
  if (title_window_) {
    if (delegate_)
      delegate_->ClosePanel();
    Close();
  }
}

PanelController::TitleContentView::TitleContentView(
    PanelController* panel_controller)
        : panel_controller_(panel_controller) {
  InitializeResources();
  close_button_ = new views::ImageButton(this);
  close_button_->SetImage(views::CustomButton::BS_NORMAL, close_button_n);
  close_button_->SetImage(views::CustomButton::BS_HOT, close_button_h);
  close_button_->SetImage(views::CustomButton::BS_PUSHED, close_button_p);
  close_button_->SetBackground(
      kTitleCloseButtonColor, close_button_n, close_button_m);
  AddChildView(close_button_);

  title_icon_ = new views::ImageView();
  AddChildView(title_icon_);
  title_label_ = new views::Label(std::wstring());
  title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  AddChildView(title_label_);

  // Default to inactive
  OnFocusOut();
}

void PanelController::TitleContentView::Layout() {
  int close_button_x = bounds().width() -
      (close_button_width + kTitleCloseButtonPad);
  close_button_->SetBounds(
      close_button_x,
      (bounds().height() - close_button_height) / 2,
      close_button_width,
      close_button_height);
  title_icon_->SetBounds(
      kTitleWidthPad,
      kTitleHeightPad,
      kTitleIconSize,
      kTitleIconSize);
  int title_x = kTitleWidthPad * 2 + kTitleIconSize;
  title_label_->SetBounds(
      title_x,
      0,
      close_button_x - (title_x + kTitleCloseButtonPad),
      bounds().height());
}

bool PanelController::TitleContentView::OnMousePressed(
    const views::MouseEvent& event) {
  DCHECK(panel_controller_) << "OnMousePressed after Close";
  return panel_controller_->TitleMousePressed(event);
}

void PanelController::TitleContentView::OnMouseReleased(
    const views::MouseEvent& event, bool canceled) {
  DCHECK(panel_controller_) << "MouseReleased after Close";
  return panel_controller_->TitleMouseReleased(event, canceled);
}

bool PanelController::TitleContentView::OnMouseDragged(
    const views::MouseEvent& event) {
  DCHECK(panel_controller_) << "MouseDragged after Close";
  return panel_controller_->TitleMouseDragged(event);
}

void PanelController::TitleContentView::OnFocusIn() {
  set_background(title_background);
  title_label_->SetColor(kTitleActiveColor);
  title_label_->SetFont(*active_font);
  Layout();
  SchedulePaint();
}

void PanelController::TitleContentView::OnFocusOut() {
  set_background(title_background);
  title_label_->SetColor(kTitleInactiveColor);
  title_label_->SetFont(*inactive_font);
  Layout();
  SchedulePaint();
}

void PanelController::TitleContentView::OnClose() {
  panel_controller_ = NULL;
}

void PanelController::TitleContentView::ButtonPressed(
    views::Button* sender, const views::Event& event) {
  if (panel_controller_ && sender == close_button_)
    panel_controller_->OnCloseButtonPressed();
}

}  // namespace chromeos
<|endoftext|>


<commit_before>// Copyright (c) 2010 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/configuration_policy_pref_store.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string16.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/configuration_policy_provider.h"
#if defined(OS_WIN)
#include "chrome/browser/configuration_policy_provider_win.h"
#elif defined(OS_MACOSX)
#include "chrome/browser/configuration_policy_provider_mac.h"
#elif defined(OS_POSIX)
#include "chrome/browser/config_dir_policy_provider.h"
#endif
#include "chrome/browser/dummy_configuration_policy_provider.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"

const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry
    ConfigurationPolicyPrefStore::simple_policy_map_[] = {
  { Value::TYPE_STRING, kPolicyHomePage,  prefs::kHomePage },
  { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
      prefs::kHomePageIsNewTabPage },
  { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
      prefs::kAlternateErrorPagesEnabled },
  { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled,
      prefs::kSearchSuggestEnabled },
  { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled,
      prefs::kDnsPrefetchingEnabled },
  { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
      prefs::kSafeBrowsingEnabled },
  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
      prefs::kPasswordManagerEnabled },
  { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
      prefs::kMetricsReportingEnabled },
  { Value::TYPE_STRING, kPolicyApplicationLocale,
      prefs::kApplicationLocale},
};

const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry
    ConfigurationPolicyPrefStore::proxy_policy_map_[] = {
  { Value::TYPE_STRING, kPolicyProxyServer, prefs::kProxyServer },
  { Value::TYPE_STRING, kPolicyProxyPacUrl, prefs::kProxyPacUrl },
  { Value::TYPE_STRING, kPolicyProxyBypassList, prefs::kProxyBypassList }
};

ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore(
    const CommandLine* command_line,
    ConfigurationPolicyProvider* provider)
    : command_line_(command_line),
      provider_(provider),
      prefs_(new DictionaryValue()),
      command_line_proxy_settings_cleared_(false),
      proxy_disabled_(false),
      proxy_configuration_specified_(false),
      use_system_proxy_(false) {
}

void ConfigurationPolicyPrefStore::ApplyProxySwitches() {
  bool proxy_disabled = command_line_->HasSwitch(switches::kNoProxyServer);
  if (proxy_disabled) {
    prefs_->Set(prefs::kNoProxyServer, Value::CreateBooleanValue(true));
  }
  bool has_explicit_proxy_config = false;
  if (command_line_->HasSwitch(switches::kProxyAutoDetect)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyAutoDetect, Value::CreateBooleanValue(true));
  }
  if (command_line_->HasSwitch(switches::kProxyServer)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyServer, Value::CreateStringValue(
        command_line_->GetSwitchValue(switches::kProxyServer)));
  }
  if (command_line_->HasSwitch(switches::kProxyPacUrl)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyPacUrl, Value::CreateStringValue(
        command_line_->GetSwitchValue(switches::kProxyPacUrl)));
  }
  if (command_line_->HasSwitch(switches::kProxyBypassList)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyBypassList, Value::CreateStringValue(
        command_line_->GetSwitchValue(switches::kProxyBypassList)));
  }

  // Warn about all the other proxy config switches we get if
  // the --no-proxy-server command-line argument is present.
  if (proxy_disabled && has_explicit_proxy_config) {
    LOG(WARNING) << "Additional command-line proxy switches specified when --"
                 << switches::kNoProxyServer << " was also specified.";
  }
}

PrefStore::PrefReadError ConfigurationPolicyPrefStore::ReadPrefs() {
  // Initialize proxy preference values from command-line switches. This is done
  // before calling Provide to allow the provider to overwrite proxy-related
  // preferences that are specified by line settings.
  ApplyProxySwitches();

  proxy_disabled_ = false;
  proxy_configuration_specified_ = false;
  command_line_proxy_settings_cleared_ = false;

  return (provider_.get() == NULL || provider_->Provide(this)) ?
      PrefStore::PREF_READ_ERROR_NONE : PrefStore::PREF_READ_ERROR_OTHER;
}

// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore() {
  ConfigurationPolicyProvider* provider;
#if defined(OS_WIN)
  provider = new ConfigurationPolicyProviderWin();
#elif defined(OS_MACOSX)
  provider = new ConfigurationPolicyProviderMac();
#elif defined(OS_POSIX)
  FilePath config_dir_path;
  if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path))
    provider = new ConfigDirPolicyProvider(
        config_dir_path.Append(FILE_PATH_LITERAL("managed")));
  else
    provider = new DummyConfigurationPolicyProvider();
#else
  provider = new DummyConfigurationPolicyProvider();
#endif

  return new ConfigurationPolicyPrefStore(CommandLine::ForCurrentProcess(),
                                          provider);
}

// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore() {
  ConfigurationPolicyProvider* provider;
#if defined(OS_POSIX) && !defined(OS_MACOSX)
  FilePath config_dir_path;
  if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path))
    provider = new ConfigDirPolicyProvider(
        config_dir_path.Append(FILE_PATH_LITERAL("recommended")));
  else
    provider = new DummyConfigurationPolicyProvider();
#else
  provider = new DummyConfigurationPolicyProvider();
#endif

  return new ConfigurationPolicyPrefStore(CommandLine::ForCurrentProcess(),
                                          provider);
}

bool ConfigurationPolicyPrefStore::ApplyProxyPolicy(PolicyType policy,
                                                    Value* value) {
  bool result = false;
  bool warn_about_proxy_disable_config = false;
  bool warn_about_proxy_system_config = false;

  const PolicyToPreferenceMapEntry* match_entry_ = NULL;
  for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
       current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current) {
    if (current->policy_type == policy) {
      match_entry_ = current;
    }
  }

  // When the first proxy-related policy is applied, ALL proxy-related
  // preferences that have been set by command-line switches must be
  // removed. Otherwise it's possible for a user to interfere with proxy
  // policy by using proxy-related switches that are related to, but not
  // identical, to the ones set through policy.
  if ((match_entry_ ||
      policy == ConfigurationPolicyPrefStore::kPolicyProxyServerMode) &&
          !command_line_proxy_settings_cleared_) {
    for (const PolicyToPreferenceMapEntry* i = proxy_policy_map_;
        i != proxy_policy_map_ + arraysize(proxy_policy_map_); ++i) {
      if (prefs_->Get(i->preference_path, NULL)) {
        LOG(WARNING) << "proxy configuration options were specified on the"
                     << " command-line but will be ignored because an"
                     << " explicit proxy configuration has been specified"
                     << " through a centrally-administered policy.";
        break;
      }
    }

    // Now actually do the preference removal.
    for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
        current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current)
      prefs_->Remove(current->preference_path, NULL);
    prefs_->Remove(prefs::kNoProxyServer, NULL);
    prefs_->Remove(prefs::kProxyAutoDetect, NULL);

    command_line_proxy_settings_cleared_ = true;
  }

  // Translate the proxy policy into preferences.
  if (policy == ConfigurationPolicyStore::kPolicyProxyServerMode) {
    int int_value;
    bool proxy_auto_detect = false;
    if (value->GetAsInteger(&int_value)) {
      result = true;
      switch (int_value) {
        case ConfigurationPolicyStore::kPolicyNoProxyServerMode:
          if (!proxy_disabled_) {
            if (proxy_configuration_specified_)
              warn_about_proxy_disable_config = true;
            proxy_disabled_ = true;
          }
          break;
        case ConfigurationPolicyStore::kPolicyAutoDetectProxyMode:
          proxy_auto_detect = true;
          break;
        case ConfigurationPolicyStore::kPolicyManuallyConfiguredProxyMode:
          break;
        case ConfigurationPolicyStore::kPolicyUseSystemProxyMode:
          if (!use_system_proxy_) {
            if (proxy_configuration_specified_)
              warn_about_proxy_system_config = true;
            use_system_proxy_ = true;
          }
          break;
        default:
          // Not a valid policy, don't assume ownership of |value|
          result = false;
          break;
      }

      if (int_value != kPolicyUseSystemProxyMode) {
        prefs_->Set(prefs::kNoProxyServer,
                    Value::CreateBooleanValue(proxy_disabled_));
        prefs_->Set(prefs::kProxyAutoDetect,
                    Value::CreateBooleanValue(proxy_auto_detect));
      }

      // No proxy and system proxy mode should ensure that no other
      // proxy preferences are set.
      if (int_value == ConfigurationPolicyStore::kPolicyNoProxyServerMode ||
          int_value == kPolicyUseSystemProxyMode) {
        for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
            current != proxy_policy_map_ + arraysize(proxy_policy_map_);
            ++current)
          prefs_->Remove(current->preference_path, NULL);
      }
    }
  } else if (match_entry_) {
    // Determine if the applied proxy policy settings conflict and issue
    // a corresponding warning if they do.
    if (!proxy_configuration_specified_) {
      if (proxy_disabled_)
        warn_about_proxy_disable_config = true;
      if (use_system_proxy_)
        warn_about_proxy_system_config = true;
      proxy_configuration_specified_ = true;
    }
    if (!use_system_proxy_ && !proxy_disabled_) {
      prefs_->Set(match_entry_->preference_path, value);
      // The ownership of value has been passed on to |prefs_|,
      // don't clean it up later.
      value = NULL;
    }
    result = true;
  }

  if (warn_about_proxy_disable_config) {
    LOG(WARNING) << "A centrally-administered policy disables the use of"
                 << " a proxy but also specifies an explicit proxy"
                 << " configuration.";
  }

  if (warn_about_proxy_system_config) {
    LOG(WARNING) << "A centrally-administered policy dictates that the"
                 << " system proxy settings should be used but also specifies"
                 << " an explicit proxy configuration.";
  }

  // If the policy was a proxy policy, cleanup |value|.
  if (result && value)
    delete value;
  return result;
}

bool ConfigurationPolicyPrefStore::ApplyPluginPolicy(PolicyType policy,
                                                     Value* value) {
  if (policy == kPolicyDisabledPlugins) {
    string16 plugin_list;
    if (value->GetAsUTF16(&plugin_list)) {
      std::vector<string16> plugin_names;
      // Change commas into tabs so that we can change escaped
      // tabs back into commas, leaving non-escaped commas as tabs
      // that can be used for splitting the string. Note that plugin
      // names must not contain backslashes, since a trailing backslash
      // in a plugin name before a comma would get swallowed during the
      // splitting.
      std::replace(plugin_list.begin(), plugin_list.end(), L',', L'\t');
      ReplaceSubstringsAfterOffset(&plugin_list, 0,
                                   ASCIIToUTF16("\\\t"), ASCIIToUTF16(","));
      SplitString(plugin_list, L'\t', &plugin_names);
      bool added_plugin = false;
      scoped_ptr<ListValue> list(new ListValue());
      for (std::vector<string16>::const_iterator i(plugin_names.begin());
           i != plugin_names.end(); ++i) {
        if (!i->empty()) {
          list->Append(Value::CreateStringValueFromUTF16(*i));
          added_plugin = true;
        }
      }
      if (added_plugin) {
        prefs_->Set(prefs::kPluginsPluginsBlacklist, list.release());
        delete value;
        return true;
      }
    }
  }
  return false;
}

bool ConfigurationPolicyPrefStore::ApplySyncPolicy(PolicyType policy,
                                                   Value* value) {
  if (policy == ConfigurationPolicyStore::kPolicySyncDisabled) {
    bool disable_sync;
    if (value->GetAsBoolean(&disable_sync) && disable_sync)
      prefs_->Set(prefs::kSyncManaged, value);
    else
      delete value;
    return true;
  }
  return false;
}

bool ConfigurationPolicyPrefStore::ApplyPolicyFromMap(PolicyType policy,
    Value* value, const PolicyToPreferenceMapEntry map[], int size) {
  const PolicyToPreferenceMapEntry* end = map + size;
  for (const PolicyToPreferenceMapEntry* current = map;
       current != end; ++current) {
    if (current->policy_type == policy) {
      DCHECK(current->value_type == value->GetType());
      prefs_->Set(current->preference_path, value);
      return true;
    }
  }
  return false;
}

void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) {
  if (ApplyProxyPolicy(policy, value))
    return;

  if (ApplyPluginPolicy(policy, value))
    return;

  if (ApplySyncPolicy(policy, value))
    return;

  if (ApplyPolicyFromMap(policy, value, simple_policy_map_,
                         arraysize(simple_policy_map_)))
    return;

  // Other policy implementations go here.
  NOTIMPLEMENTED();
  delete value;
}
<commit_msg>Fix wrong line-ending.<commit_after>// Copyright (c) 2010 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/configuration_policy_pref_store.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string16.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/configuration_policy_provider.h"
#if defined(OS_WIN)
#include "chrome/browser/configuration_policy_provider_win.h"
#elif defined(OS_MACOSX)
#include "chrome/browser/configuration_policy_provider_mac.h"
#elif defined(OS_POSIX)
#include "chrome/browser/config_dir_policy_provider.h"
#endif
#include "chrome/browser/dummy_configuration_policy_provider.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"

const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry
    ConfigurationPolicyPrefStore::simple_policy_map_[] = {
  { Value::TYPE_STRING, kPolicyHomePage,  prefs::kHomePage },
  { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
      prefs::kHomePageIsNewTabPage },
  { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
      prefs::kAlternateErrorPagesEnabled },
  { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled,
      prefs::kSearchSuggestEnabled },
  { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled,
      prefs::kDnsPrefetchingEnabled },
  { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
      prefs::kSafeBrowsingEnabled },
  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
      prefs::kPasswordManagerEnabled },
  { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
      prefs::kMetricsReportingEnabled },
  { Value::TYPE_STRING, kPolicyApplicationLocale,
      prefs::kApplicationLocale},
};

const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry
    ConfigurationPolicyPrefStore::proxy_policy_map_[] = {
  { Value::TYPE_STRING, kPolicyProxyServer, prefs::kProxyServer },
  { Value::TYPE_STRING, kPolicyProxyPacUrl, prefs::kProxyPacUrl },
  { Value::TYPE_STRING, kPolicyProxyBypassList, prefs::kProxyBypassList }
};

ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore(
    const CommandLine* command_line,
    ConfigurationPolicyProvider* provider)
    : command_line_(command_line),
      provider_(provider),
      prefs_(new DictionaryValue()),
      command_line_proxy_settings_cleared_(false),
      proxy_disabled_(false),
      proxy_configuration_specified_(false),
      use_system_proxy_(false) {
}

void ConfigurationPolicyPrefStore::ApplyProxySwitches() {
  bool proxy_disabled = command_line_->HasSwitch(switches::kNoProxyServer);
  if (proxy_disabled) {
    prefs_->Set(prefs::kNoProxyServer, Value::CreateBooleanValue(true));
  }
  bool has_explicit_proxy_config = false;
  if (command_line_->HasSwitch(switches::kProxyAutoDetect)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyAutoDetect, Value::CreateBooleanValue(true));
  }
  if (command_line_->HasSwitch(switches::kProxyServer)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyServer, Value::CreateStringValue(
        command_line_->GetSwitchValue(switches::kProxyServer)));
  }
  if (command_line_->HasSwitch(switches::kProxyPacUrl)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyPacUrl, Value::CreateStringValue(
        command_line_->GetSwitchValue(switches::kProxyPacUrl)));
  }
  if (command_line_->HasSwitch(switches::kProxyBypassList)) {
    has_explicit_proxy_config = true;
    prefs_->Set(prefs::kProxyBypassList, Value::CreateStringValue(
        command_line_->GetSwitchValue(switches::kProxyBypassList)));
  }

  // Warn about all the other proxy config switches we get if
  // the --no-proxy-server command-line argument is present.
  if (proxy_disabled && has_explicit_proxy_config) {
    LOG(WARNING) << "Additional command-line proxy switches specified when --"
                 << switches::kNoProxyServer << " was also specified.";
  }
}

PrefStore::PrefReadError ConfigurationPolicyPrefStore::ReadPrefs() {
  // Initialize proxy preference values from command-line switches. This is done
  // before calling Provide to allow the provider to overwrite proxy-related
  // preferences that are specified by line settings.
  ApplyProxySwitches();

  proxy_disabled_ = false;
  proxy_configuration_specified_ = false;
  command_line_proxy_settings_cleared_ = false;

  return (provider_.get() == NULL || provider_->Provide(this)) ?
      PrefStore::PREF_READ_ERROR_NONE : PrefStore::PREF_READ_ERROR_OTHER;
}

// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore() {
  ConfigurationPolicyProvider* provider;
#if defined(OS_WIN)
  provider = new ConfigurationPolicyProviderWin();
#elif defined(OS_MACOSX)
  provider = new ConfigurationPolicyProviderMac();
#elif defined(OS_POSIX)
  FilePath config_dir_path;
  if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path))
    provider = new ConfigDirPolicyProvider(
        config_dir_path.Append(FILE_PATH_LITERAL("managed")));
  else
    provider = new DummyConfigurationPolicyProvider();
#else
  provider = new DummyConfigurationPolicyProvider();
#endif

  return new ConfigurationPolicyPrefStore(CommandLine::ForCurrentProcess(),
                                          provider);
}

// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore() {
  ConfigurationPolicyProvider* provider;
#if defined(OS_POSIX) && !defined(OS_MACOSX)
  FilePath config_dir_path;
  if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path))
    provider = new ConfigDirPolicyProvider(
        config_dir_path.Append(FILE_PATH_LITERAL("recommended")));
  else
    provider = new DummyConfigurationPolicyProvider();
#else
  provider = new DummyConfigurationPolicyProvider();
#endif

  return new ConfigurationPolicyPrefStore(CommandLine::ForCurrentProcess(),
                                          provider);
}

bool ConfigurationPolicyPrefStore::ApplyProxyPolicy(PolicyType policy,
                                                    Value* value) {
  bool result = false;
  bool warn_about_proxy_disable_config = false;
  bool warn_about_proxy_system_config = false;

  const PolicyToPreferenceMapEntry* match_entry_ = NULL;
  for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
       current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current) {
    if (current->policy_type == policy) {
      match_entry_ = current;
    }
  }

  // When the first proxy-related policy is applied, ALL proxy-related
  // preferences that have been set by command-line switches must be
  // removed. Otherwise it's possible for a user to interfere with proxy
  // policy by using proxy-related switches that are related to, but not
  // identical, to the ones set through policy.
  if ((match_entry_ ||
      policy == ConfigurationPolicyPrefStore::kPolicyProxyServerMode) &&
          !command_line_proxy_settings_cleared_) {
    for (const PolicyToPreferenceMapEntry* i = proxy_policy_map_;
        i != proxy_policy_map_ + arraysize(proxy_policy_map_); ++i) {
      if (prefs_->Get(i->preference_path, NULL)) {
        LOG(WARNING) << "proxy configuration options were specified on the"
                     << " command-line but will be ignored because an"
                     << " explicit proxy configuration has been specified"
                     << " through a centrally-administered policy.";
        break;
      }
    }

    // Now actually do the preference removal.
    for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
        current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current)
      prefs_->Remove(current->preference_path, NULL);
    prefs_->Remove(prefs::kNoProxyServer, NULL);
    prefs_->Remove(prefs::kProxyAutoDetect, NULL);

    command_line_proxy_settings_cleared_ = true;
  }

  // Translate the proxy policy into preferences.
  if (policy == ConfigurationPolicyStore::kPolicyProxyServerMode) {
    int int_value;
    bool proxy_auto_detect = false;
    if (value->GetAsInteger(&int_value)) {
      result = true;
      switch (int_value) {
        case ConfigurationPolicyStore::kPolicyNoProxyServerMode:
          if (!proxy_disabled_) {
            if (proxy_configuration_specified_)
              warn_about_proxy_disable_config = true;
            proxy_disabled_ = true;
          }
          break;
        case ConfigurationPolicyStore::kPolicyAutoDetectProxyMode:
          proxy_auto_detect = true;
          break;
        case ConfigurationPolicyStore::kPolicyManuallyConfiguredProxyMode:
          break;
        case ConfigurationPolicyStore::kPolicyUseSystemProxyMode:
          if (!use_system_proxy_) {
            if (proxy_configuration_specified_)
              warn_about_proxy_system_config = true;
            use_system_proxy_ = true;
          }
          break;
        default:
          // Not a valid policy, don't assume ownership of |value|
          result = false;
          break;
      }

      if (int_value != kPolicyUseSystemProxyMode) {
        prefs_->Set(prefs::kNoProxyServer,
                    Value::CreateBooleanValue(proxy_disabled_));
        prefs_->Set(prefs::kProxyAutoDetect,
                    Value::CreateBooleanValue(proxy_auto_detect));
      }

      // No proxy and system proxy mode should ensure that no other
      // proxy preferences are set.
      if (int_value == ConfigurationPolicyStore::kPolicyNoProxyServerMode ||
          int_value == kPolicyUseSystemProxyMode) {
        for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
            current != proxy_policy_map_ + arraysize(proxy_policy_map_);
            ++current)
          prefs_->Remove(current->preference_path, NULL);
      }
    }
  } else if (match_entry_) {
    // Determine if the applied proxy policy settings conflict and issue
    // a corresponding warning if they do.
    if (!proxy_configuration_specified_) {
      if (proxy_disabled_)
        warn_about_proxy_disable_config = true;
      if (use_system_proxy_)
        warn_about_proxy_system_config = true;
      proxy_configuration_specified_ = true;
    }
    if (!use_system_proxy_ && !proxy_disabled_) {
      prefs_->Set(match_entry_->preference_path, value);
      // The ownership of value has been passed on to |prefs_|,
      // don't clean it up later.
      value = NULL;
    }
    result = true;
  }

  if (warn_about_proxy_disable_config) {
    LOG(WARNING) << "A centrally-administered policy disables the use of"
                 << " a proxy but also specifies an explicit proxy"
                 << " configuration.";
  }

  if (warn_about_proxy_system_config) {
    LOG(WARNING) << "A centrally-administered policy dictates that the"
                 << " system proxy settings should be used but also specifies"
                 << " an explicit proxy configuration.";
  }

  // If the policy was a proxy policy, cleanup |value|.
  if (result && value)
    delete value;
  return result;
}

bool ConfigurationPolicyPrefStore::ApplyPluginPolicy(PolicyType policy,
                                                     Value* value) {
  if (policy == kPolicyDisabledPlugins) {
    string16 plugin_list;
    if (value->GetAsUTF16(&plugin_list)) {
      std::vector<string16> plugin_names;
      // Change commas into tabs so that we can change escaped
      // tabs back into commas, leaving non-escaped commas as tabs
      // that can be used for splitting the string. Note that plugin
      // names must not contain backslashes, since a trailing backslash
      // in a plugin name before a comma would get swallowed during the
      // splitting.
      std::replace(plugin_list.begin(), plugin_list.end(), L',', L'\t');
      ReplaceSubstringsAfterOffset(&plugin_list, 0,
                                   ASCIIToUTF16("\\\t"), ASCIIToUTF16(","));
      SplitString(plugin_list, L'\t', &plugin_names);
      bool added_plugin = false;
      scoped_ptr<ListValue> list(new ListValue());
      for (std::vector<string16>::const_iterator i(plugin_names.begin());
           i != plugin_names.end(); ++i) {
        if (!i->empty()) {
          list->Append(Value::CreateStringValueFromUTF16(*i));
          added_plugin = true;
        }
      }
      if (added_plugin) {
        prefs_->Set(prefs::kPluginsPluginsBlacklist, list.release());
        delete value;
        return true;
      }
    }
  }
  return false;
}

bool ConfigurationPolicyPrefStore::ApplySyncPolicy(PolicyType policy,
                                                   Value* value) {
  if (policy == ConfigurationPolicyStore::kPolicySyncDisabled) {
    bool disable_sync;
    if (value->GetAsBoolean(&disable_sync) && disable_sync)
      prefs_->Set(prefs::kSyncManaged, value);
    else
      delete value;
    return true;
  }
  return false;
}

bool ConfigurationPolicyPrefStore::ApplyPolicyFromMap(PolicyType policy,
    Value* value, const PolicyToPreferenceMapEntry map[], int size) {
  const PolicyToPreferenceMapEntry* end = map + size;
  for (const PolicyToPreferenceMapEntry* current = map;
       current != end; ++current) {
    if (current->policy_type == policy) {
      DCHECK(current->value_type == value->GetType());
      prefs_->Set(current->preference_path, value);
      return true;
    }
  }
  return false;
}

void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) {
  if (ApplyProxyPolicy(policy, value))
    return;

  if (ApplyPluginPolicy(policy, value))
    return;

  if (ApplySyncPolicy(policy, value))
    return;

  if (ApplyPolicyFromMap(policy, value, simple_policy_map_,
                         arraysize(simple_policy_map_)))
    return;

  // Other policy implementations go here.
  NOTIMPLEMENTED();
  delete value;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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/extensions/extension_install_ui.h"

#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/rand_util.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#if defined(TOOLKIT_VIEWS)  // TODO(port)
#include "chrome/browser/views/extensions/extension_installed_bubble.h"
#elif defined(TOOLKIT_GTK)
#include "chrome/browser/gtk/extension_installed_bubble_gtk.h"
#endif
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/platform_util.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

#if defined(TOOLKIT_GTK)
#include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

#if defined(OS_MACOSX)
#include "chrome/browser/cocoa/extension_installed_bubble_bridge.h"
#endif

// static
const int ExtensionInstallUI::kTitleIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_TITLE,
  IDS_EXTENSION_UNINSTALL_PROMPT_TITLE,
  IDS_EXTENSION_ENABLE_INCOGNITO_PROMPT_TITLE
};
// static
const int ExtensionInstallUI::kHeadingIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_HEADING,
  IDS_EXTENSION_UNINSTALL_PROMPT_HEADING,
  IDS_EXTENSION_ENABLE_INCOGNITO_PROMPT_HEADING
};
// static
const int ExtensionInstallUI::kButtonIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
  IDS_EXTENSION_PROMPT_UNINSTALL_BUTTON,
  IDS_EXTENSION_PROMPT_ENABLE_INCOGNITO_BUTTON
};

namespace {

// We also show the severe warning if the extension has access to any file://
// URLs. They aren't *quite* as dangerous as full access to the system via
// NPAPI, but pretty dang close. Content scripts are currently the only way
// that extension can get access to file:// URLs.
static bool ExtensionHasFileAccess(Extension* extension) {
  for (UserScriptList::const_iterator script =
           extension->content_scripts().begin();
       script != extension->content_scripts().end();
       ++script) {
    for (UserScript::PatternList::const_iterator pattern =
             script->url_patterns().begin();
         pattern != script->url_patterns().end();
         ++pattern) {
      if (pattern->scheme() == chrome::kFileScheme)
        return true;
    }
  }

  return false;
}

// TODO(estade): remove this function when the old install UI is removed. It
// is commented out on linux/gtk due to compiler warnings.
#if !defined(TOOLKIT_GTK)
static std::wstring GetInstallWarning(Extension* extension) {
  // If the extension has a plugin, it's easy: the plugin has the most severe
  // warning.
  if (!extension->plugins().empty() || ExtensionHasFileAccess(extension))
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS);

  // Otherwise, we go in descending order of severity: all hosts, several hosts,
  // a single host, no hosts. For each of these, we also have a variation of the
  // message for when api permissions are also requested.
  if (extension->HasAccessToAllHosts()) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS_AND_BROWSER);
  }

  const std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
  if (hosts.size() > 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_MULTIPLE_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_MULTIPLE_HOSTS_AND_BROWSER);
  }

  if (hosts.size() == 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_SINGLE_HOST,
          UTF8ToWide(*hosts.begin()));
    else
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_SINGLE_HOST_AND_BROWSER,
          UTF8ToWide(*hosts.begin()));
  }

  DCHECK(hosts.size() == 0);
  if (extension->api_permissions().empty())
    return L"";
  else
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_BROWSER);
}
#endif

#if defined(OS_WIN) || defined(TOOLKIT_GTK)
static void GetV2Warnings(Extension* extension,
                          std::vector<string16>* warnings) {
  if (!extension->plugins().empty() || ExtensionHasFileAccess(extension)) {
    // TODO(aa): This one is a bit awkward. Should we have a separate
    // presentation for this case?
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_FULL_ACCESS));
    return;
  }

  if (extension->HasAccessToAllHosts()) {
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_ALL_HOSTS));
  } else {
    std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
    if (hosts.size() == 1) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_1_HOST,
                                     UTF8ToUTF16(*hosts.begin())));
    } else if (hosts.size() == 2) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_2_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin()))));
    } else if (hosts.size() == 3) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_3_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin())),
                                     UTF8ToUTF16(*(++++hosts.begin()))));
    } else if (hosts.size() >= 4) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(
              IDS_EXTENSION_PROMPT2_WARNING_4_OR_MORE_HOSTS,
              UTF8ToUTF16(*hosts.begin()),
              UTF8ToUTF16(*(++hosts.begin())),
              IntToString16(hosts.size() - 2)));
    }
  }

  if (extension->HasApiPermission(Extension::kTabPermission) ||
      extension->HasApiPermission(Extension::kBookmarkPermission)) {
    warnings->push_back(
        l10n_util::GetStringUTF16(
            IDS_EXTENSION_PROMPT2_WARNING_BROWSING_HISTORY));
  }

  // TODO(aa): Geolocation, camera/mic, what else?
}
#endif

}  // namespace

ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
    : profile_(profile),
      ui_loop_(MessageLoop::current()),
      extension_(NULL),
      delegate_(NULL),
      prompt_type_(NUM_PROMPT_TYPES),
      ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this))
#if defined(TOOLKIT_GTK)
    , previous_use_gtk_theme_(false)
#endif
{}

void ExtensionInstallUI::ConfirmInstall(Delegate* delegate,
                                        Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  // We special-case themes to not show any confirm UI. Instead they are
  // immediately installed, and then we show an infobar (see OnInstallSuccess)
  // to allow the user to revert if they don't like it.
  if (extension->IsTheme()) {
    // Remember the current theme in case the user pressed undo.
    Extension* previous_theme = profile_->GetTheme();
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();

#if defined(TOOLKIT_GTK)
    // On Linux, we also need to take the user's system settings into account
    // to undo theme installation.
    previous_use_gtk_theme_ =
        GtkThemeProvider::GetFrom(profile_)->UseGtkTheme();
#endif

    delegate->InstallUIProceed(false);
    return;
  }

  ShowConfirmation(INSTALL_PROMPT);
}

void ExtensionInstallUI::ConfirmUninstall(Delegate* delegate,
                                          Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  ShowConfirmation(UNINSTALL_PROMPT);
}

void ExtensionInstallUI::ConfirmEnableIncognito(Delegate* delegate,
                                                Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  ShowConfirmation(ENABLE_INCOGNITO_PROMPT);
}

void ExtensionInstallUI::OnInstallSuccess(Extension* extension) {
  if (extension->IsTheme()) {
    ShowThemeInfoBar(extension);
    return;
  }

  // GetLastActiveWithProfile will fail on the build bots. This needs to be
  // implemented differently if any test is created which depends on
  // ExtensionInstalledBubble showing.
#if defined(TOOLKIT_VIEWS)
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  ExtensionInstalledBubble::Show(extension, browser, icon_);
#elif defined(OS_MACOSX)
  if (extension->browser_action() ||
      (extension->page_action() &&
      !extension->page_action()->default_icon_path().empty())) {
    Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
    DCHECK(browser);
    ExtensionInstalledBubbleCocoa::ShowExtensionInstalledBubble(
        browser->window()->GetNativeHandle(),
        extension, browser, icon_);
  }  else {
    // If the extension is of type GENERIC, launch infobar instead of popup
    // bubble, because we have no guaranteed wrench menu button to point to.
    ShowGenericExtensionInstalledInfoBar(extension);
  }
#elif defined(TOOLKIT_GTK)
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;
  ExtensionInstalledBubbleGtk::Show(extension, browser, icon_);
#endif  // TOOLKIT_VIEWS
}

void ExtensionInstallUI::OnInstallFailure(const std::string& error) {
  DCHECK(ui_loop_ == MessageLoop::current());

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  platform_util::SimpleErrorBox(
      browser ? browser->window()->GetNativeHandle() : NULL,
      l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_FAILURE_TITLE),
      UTF8ToUTF16(error));
}

void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) {
  ShowThemeInfoBar(extension);
}

void ExtensionInstallUI::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  if (image)
    icon_ = *image;
  else
    icon_ = SkBitmap();
  if (icon_.empty()) {
    icon_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
        IDR_EXTENSION_DEFAULT_ICON);
  }

  switch (prompt_type_) {
    case INSTALL_PROMPT: {
      NotificationService* service = NotificationService::current();
      service->Notify(NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
          Source<ExtensionInstallUI>(this),
          NotificationService::NoDetails());

#if defined(OS_WIN) || defined(TOOLKIT_GTK)
      std::vector<string16> warnings;
      GetV2Warnings(extension_, &warnings);
      ShowExtensionInstallUIPrompt2Impl(
          profile_, delegate_, extension_, &icon_, warnings);
#else
      ShowExtensionInstallUIPromptImpl(
          profile_, delegate_, extension_, &icon_,
          WideToUTF16Hack(GetInstallWarning(extension_)), INSTALL_PROMPT);
#endif
      break;
    }
    case UNINSTALL_PROMPT: {
      string16 message =
          l10n_util::GetStringUTF16(IDS_EXTENSION_UNINSTALL_CONFIRMATION);
      ShowExtensionInstallUIPromptImpl(profile_, delegate_, extension_, &icon_,
          message, UNINSTALL_PROMPT);
      break;
    }
    case ENABLE_INCOGNITO_PROMPT: {
      string16 message =
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_INCOGNITO,
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
      ShowExtensionInstallUIPromptImpl(profile_, delegate_, extension_, &icon_,
          message, ENABLE_INCOGNITO_PROMPT);
      break;
    }
    default:
      NOTREACHED() << "Unknown message";
      break;
  }
}

void ExtensionInstallUI::ShowThemeInfoBar(Extension* new_theme) {
  if (!new_theme->IsTheme())
    return;

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) {
    InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i);
    if (delegate->AsThemePreviewInfobarDelegate()) {
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate = GetNewInfoBarDelegate(new_theme,
      tab_contents);

  if (old_delegate)
    tab_contents->ReplaceInfoBar(old_delegate, new_delegate);
  else
    tab_contents->AddInfoBar(new_delegate);
}

void ExtensionInstallUI::ShowConfirmation(PromptType prompt_type) {
  // Load the image asynchronously. For the response, check OnImageLoaded.
  prompt_type_ = prompt_type;
  ExtensionResource image =
      extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE);
  tracker_.LoadImage(extension_, image,
                     gfx::Size(Extension::EXTENSION_ICON_LARGE,
                               Extension::EXTENSION_ICON_LARGE),
                     ImageLoadingTracker::DONT_CACHE);
}

#if defined(OS_MACOSX)
void ExtensionInstallUI::ShowGenericExtensionInstalledInfoBar(
    Extension* new_extension) {
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  std::wstring msg = l10n_util::GetStringF(IDS_EXTENSION_INSTALLED_HEADING,
                                           UTF8ToWide(new_extension->name())) +
         L" " + l10n_util::GetString(IDS_EXTENSION_INSTALLED_MANAGE_INFO_MAC);
  InfoBarDelegate* delegate = new SimpleAlertInfoBarDelegate(
      tab_contents, msg, new SkBitmap(icon_));
  tab_contents->AddInfoBar(delegate);
}
#endif

InfoBarDelegate* ExtensionInstallUI::GetNewInfoBarDelegate(
    Extension* new_theme, TabContents* tab_contents) {
#if defined(TOOLKIT_GTK)
  return new GtkThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id_, previous_use_gtk_theme_);
#else
  return new ThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id_);
#endif
}
<commit_msg>Use the infobar for installed extensions in incognito, since the browser action will not be visible.<commit_after>// Copyright (c) 2010 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/extensions/extension_install_ui.h"

#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/rand_util.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#if defined(TOOLKIT_VIEWS)  // TODO(port)
#include "chrome/browser/views/extensions/extension_installed_bubble.h"
#elif defined(TOOLKIT_GTK)
#include "chrome/browser/gtk/extension_installed_bubble_gtk.h"
#endif
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/platform_util.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

#if defined(TOOLKIT_GTK)
#include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

#if defined(OS_MACOSX)
#include "chrome/browser/cocoa/extension_installed_bubble_bridge.h"
#endif

// static
const int ExtensionInstallUI::kTitleIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_TITLE,
  IDS_EXTENSION_UNINSTALL_PROMPT_TITLE,
  IDS_EXTENSION_ENABLE_INCOGNITO_PROMPT_TITLE
};
// static
const int ExtensionInstallUI::kHeadingIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_HEADING,
  IDS_EXTENSION_UNINSTALL_PROMPT_HEADING,
  IDS_EXTENSION_ENABLE_INCOGNITO_PROMPT_HEADING
};
// static
const int ExtensionInstallUI::kButtonIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
  IDS_EXTENSION_PROMPT_UNINSTALL_BUTTON,
  IDS_EXTENSION_PROMPT_ENABLE_INCOGNITO_BUTTON
};

namespace {

// We also show the severe warning if the extension has access to any file://
// URLs. They aren't *quite* as dangerous as full access to the system via
// NPAPI, but pretty dang close. Content scripts are currently the only way
// that extension can get access to file:// URLs.
static bool ExtensionHasFileAccess(Extension* extension) {
  for (UserScriptList::const_iterator script =
           extension->content_scripts().begin();
       script != extension->content_scripts().end();
       ++script) {
    for (UserScript::PatternList::const_iterator pattern =
             script->url_patterns().begin();
         pattern != script->url_patterns().end();
         ++pattern) {
      if (pattern->scheme() == chrome::kFileScheme)
        return true;
    }
  }

  return false;
}

// TODO(estade): remove this function when the old install UI is removed. It
// is commented out on linux/gtk due to compiler warnings.
#if !defined(TOOLKIT_GTK)
static std::wstring GetInstallWarning(Extension* extension) {
  // If the extension has a plugin, it's easy: the plugin has the most severe
  // warning.
  if (!extension->plugins().empty() || ExtensionHasFileAccess(extension))
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS);

  // Otherwise, we go in descending order of severity: all hosts, several hosts,
  // a single host, no hosts. For each of these, we also have a variation of the
  // message for when api permissions are also requested.
  if (extension->HasAccessToAllHosts()) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS_AND_BROWSER);
  }

  const std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
  if (hosts.size() > 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_MULTIPLE_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_MULTIPLE_HOSTS_AND_BROWSER);
  }

  if (hosts.size() == 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_SINGLE_HOST,
          UTF8ToWide(*hosts.begin()));
    else
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_SINGLE_HOST_AND_BROWSER,
          UTF8ToWide(*hosts.begin()));
  }

  DCHECK(hosts.size() == 0);
  if (extension->api_permissions().empty())
    return L"";
  else
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_BROWSER);
}
#endif

#if defined(OS_WIN) || defined(TOOLKIT_GTK)
static void GetV2Warnings(Extension* extension,
                          std::vector<string16>* warnings) {
  if (!extension->plugins().empty() || ExtensionHasFileAccess(extension)) {
    // TODO(aa): This one is a bit awkward. Should we have a separate
    // presentation for this case?
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_FULL_ACCESS));
    return;
  }

  if (extension->HasAccessToAllHosts()) {
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_ALL_HOSTS));
  } else {
    std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
    if (hosts.size() == 1) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_1_HOST,
                                     UTF8ToUTF16(*hosts.begin())));
    } else if (hosts.size() == 2) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_2_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin()))));
    } else if (hosts.size() == 3) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_3_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin())),
                                     UTF8ToUTF16(*(++++hosts.begin()))));
    } else if (hosts.size() >= 4) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(
              IDS_EXTENSION_PROMPT2_WARNING_4_OR_MORE_HOSTS,
              UTF8ToUTF16(*hosts.begin()),
              UTF8ToUTF16(*(++hosts.begin())),
              IntToString16(hosts.size() - 2)));
    }
  }

  if (extension->HasApiPermission(Extension::kTabPermission) ||
      extension->HasApiPermission(Extension::kBookmarkPermission)) {
    warnings->push_back(
        l10n_util::GetStringUTF16(
            IDS_EXTENSION_PROMPT2_WARNING_BROWSING_HISTORY));
  }

  // TODO(aa): Geolocation, camera/mic, what else?
}
#endif

}  // namespace

ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
    : profile_(profile),
      ui_loop_(MessageLoop::current()),
      extension_(NULL),
      delegate_(NULL),
      prompt_type_(NUM_PROMPT_TYPES),
      ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this))
#if defined(TOOLKIT_GTK)
    , previous_use_gtk_theme_(false)
#endif
{}

void ExtensionInstallUI::ConfirmInstall(Delegate* delegate,
                                        Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  // We special-case themes to not show any confirm UI. Instead they are
  // immediately installed, and then we show an infobar (see OnInstallSuccess)
  // to allow the user to revert if they don't like it.
  if (extension->IsTheme()) {
    // Remember the current theme in case the user pressed undo.
    Extension* previous_theme = profile_->GetTheme();
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();

#if defined(TOOLKIT_GTK)
    // On Linux, we also need to take the user's system settings into account
    // to undo theme installation.
    previous_use_gtk_theme_ =
        GtkThemeProvider::GetFrom(profile_)->UseGtkTheme();
#endif

    delegate->InstallUIProceed(false);
    return;
  }

  ShowConfirmation(INSTALL_PROMPT);
}

void ExtensionInstallUI::ConfirmUninstall(Delegate* delegate,
                                          Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  ShowConfirmation(UNINSTALL_PROMPT);
}

void ExtensionInstallUI::ConfirmEnableIncognito(Delegate* delegate,
                                                Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  ShowConfirmation(ENABLE_INCOGNITO_PROMPT);
}

void ExtensionInstallUI::OnInstallSuccess(Extension* extension) {
  if (extension->IsTheme()) {
    ShowThemeInfoBar(extension);
    return;
  }

  // GetLastActiveWithProfile will fail on the build bots. This needs to be
  // implemented differently if any test is created which depends on
  // ExtensionInstalledBubble showing.
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);

#if defined(TOOLKIT_VIEWS)
  if (!browser)
    return;

  ExtensionInstalledBubble::Show(extension, browser, icon_);
#elif defined(OS_MACOSX)
  DCHECK(browser);
  // Note that browser actions don't appear in incognito mode initially,
  // so fall back to the generic case.
  if ((extension->browser_action() && !browser->profile()->IsOffTheRecord()) ||
      (extension->page_action() &&
      !extension->page_action()->default_icon_path().empty())) {
    ExtensionInstalledBubbleCocoa::ShowExtensionInstalledBubble(
        browser->window()->GetNativeHandle(),
        extension, browser, icon_);
  }  else {
    // If the extension is of type GENERIC, meaning it doesn't have a UI
    // surface to display for this window, launch infobar instead of popup
    // bubble, because we have no guaranteed wrench menu button to point to.
    ShowGenericExtensionInstalledInfoBar(extension);
  }
#elif defined(TOOLKIT_GTK)
  if (!browser)
    return;
  ExtensionInstalledBubbleGtk::Show(extension, browser, icon_);
#endif  // TOOLKIT_VIEWS
}

void ExtensionInstallUI::OnInstallFailure(const std::string& error) {
  DCHECK(ui_loop_ == MessageLoop::current());

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  platform_util::SimpleErrorBox(
      browser ? browser->window()->GetNativeHandle() : NULL,
      l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_FAILURE_TITLE),
      UTF8ToUTF16(error));
}

void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) {
  ShowThemeInfoBar(extension);
}

void ExtensionInstallUI::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  if (image)
    icon_ = *image;
  else
    icon_ = SkBitmap();
  if (icon_.empty()) {
    icon_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
        IDR_EXTENSION_DEFAULT_ICON);
  }

  switch (prompt_type_) {
    case INSTALL_PROMPT: {
      NotificationService* service = NotificationService::current();
      service->Notify(NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
          Source<ExtensionInstallUI>(this),
          NotificationService::NoDetails());

#if defined(OS_WIN) || defined(TOOLKIT_GTK)
      std::vector<string16> warnings;
      GetV2Warnings(extension_, &warnings);
      ShowExtensionInstallUIPrompt2Impl(
          profile_, delegate_, extension_, &icon_, warnings);
#else
      ShowExtensionInstallUIPromptImpl(
          profile_, delegate_, extension_, &icon_,
          WideToUTF16Hack(GetInstallWarning(extension_)), INSTALL_PROMPT);
#endif
      break;
    }
    case UNINSTALL_PROMPT: {
      string16 message =
          l10n_util::GetStringUTF16(IDS_EXTENSION_UNINSTALL_CONFIRMATION);
      ShowExtensionInstallUIPromptImpl(profile_, delegate_, extension_, &icon_,
          message, UNINSTALL_PROMPT);
      break;
    }
    case ENABLE_INCOGNITO_PROMPT: {
      string16 message =
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_INCOGNITO,
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
      ShowExtensionInstallUIPromptImpl(profile_, delegate_, extension_, &icon_,
          message, ENABLE_INCOGNITO_PROMPT);
      break;
    }
    default:
      NOTREACHED() << "Unknown message";
      break;
  }
}

void ExtensionInstallUI::ShowThemeInfoBar(Extension* new_theme) {
  if (!new_theme->IsTheme())
    return;

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) {
    InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i);
    if (delegate->AsThemePreviewInfobarDelegate()) {
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate = GetNewInfoBarDelegate(new_theme,
      tab_contents);

  if (old_delegate)
    tab_contents->ReplaceInfoBar(old_delegate, new_delegate);
  else
    tab_contents->AddInfoBar(new_delegate);
}

void ExtensionInstallUI::ShowConfirmation(PromptType prompt_type) {
  // Load the image asynchronously. For the response, check OnImageLoaded.
  prompt_type_ = prompt_type;
  ExtensionResource image =
      extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE);
  tracker_.LoadImage(extension_, image,
                     gfx::Size(Extension::EXTENSION_ICON_LARGE,
                               Extension::EXTENSION_ICON_LARGE),
                     ImageLoadingTracker::DONT_CACHE);
}

#if defined(OS_MACOSX)
void ExtensionInstallUI::ShowGenericExtensionInstalledInfoBar(
    Extension* new_extension) {
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  std::wstring msg = l10n_util::GetStringF(IDS_EXTENSION_INSTALLED_HEADING,
                                           UTF8ToWide(new_extension->name())) +
         L" " + l10n_util::GetString(IDS_EXTENSION_INSTALLED_MANAGE_INFO_MAC);
  InfoBarDelegate* delegate = new SimpleAlertInfoBarDelegate(
      tab_contents, msg, new SkBitmap(icon_));
  tab_contents->AddInfoBar(delegate);
}
#endif

InfoBarDelegate* ExtensionInstallUI::GetNewInfoBarDelegate(
    Extension* new_theme, TabContents* tab_contents) {
#if defined(TOOLKIT_GTK)
  return new GtkThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id_, previous_use_gtk_theme_);
#else
  return new ThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id_);
#endif
}
<|endoftext|>