<commit_before>#include "platcompat.h"
#include "USBinternal.h"
#include "vl.h"

#define USB_DEVICE_GET_CLASS(p) (&p->klass)

static void usb_device_realize(USBDevice *dev/*, Error **errp*/)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);

    if (klass->realize) {
        klass->realize(dev/*, errp*/);
    }
}

USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->find_device) {
        return klass->find_device(dev, addr);
    }
    return NULL;
}

static void usb_device_unrealize(USBDevice *dev/*, Error **errp*/)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);

    if (klass->unrealize) {
        klass->unrealize(dev/*, errp*/);
    }
}

void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->cancel_packet) {
        klass->cancel_packet(dev, p);
    }
}

void usb_device_handle_attach(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_attach) {
        klass->handle_attach(dev);
    }
}

void usb_device_handle_reset(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_reset) {
        klass->handle_reset(dev);
    }
}

void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
                               int value, int index, int length, uint8_t *data)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_control) {
        klass->handle_control(dev, p, request, value, index, length, data);
    }
}

void usb_device_handle_data(USBDevice *dev, USBPacket *p)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_data) {
        klass->handle_data(dev, p);
    }
}

const char *usb_device_get_product_desc(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    return klass->product_desc;
}

const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (dev->usb_desc) {
        return dev->usb_desc;
    }
    return klass->usb_desc;
}

void usb_device_set_interface(USBDevice *dev, int intf,
                              int alt_old, int alt_new)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->set_interface) {
        klass->set_interface(dev, intf, alt_old, alt_new);
    }
}

void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->flush_ep_queue) {
        klass->flush_ep_queue(dev, ep);
    }
}

void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->ep_stopped) {
        klass->ep_stopped(dev, ep);
    }
}

int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps,
                             int streams)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->alloc_streams) {
        return klass->alloc_streams(dev, eps, nr_eps, streams);
    }
    return 0;
}

void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->free_streams) {
        klass->free_streams(dev, eps, nr_eps);
    }
}<commit_msg>qemu-usb: comment out so usb descs won't accidentally use nullptr product string.<commit_after>#include "platcompat.h"
#include "USBinternal.h"
#include "vl.h"

#define USB_DEVICE_GET_CLASS(p) (&p->klass)

static void usb_device_realize(USBDevice *dev/*, Error **errp*/)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);

    if (klass->realize) {
        klass->realize(dev/*, errp*/);
    }
}

USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->find_device) {
        return klass->find_device(dev, addr);
    }
    return NULL;
}

static void usb_device_unrealize(USBDevice *dev/*, Error **errp*/)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);

    if (klass->unrealize) {
        klass->unrealize(dev/*, errp*/);
    }
}

void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->cancel_packet) {
        klass->cancel_packet(dev, p);
    }
}

void usb_device_handle_attach(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_attach) {
        klass->handle_attach(dev);
    }
}

void usb_device_handle_reset(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_reset) {
        klass->handle_reset(dev);
    }
}

void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
                               int value, int index, int length, uint8_t *data)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_control) {
        klass->handle_control(dev, p, request, value, index, length, data);
    }
}

void usb_device_handle_data(USBDevice *dev, USBPacket *p)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_data) {
        klass->handle_data(dev, p);
    }
}

/*const char *usb_device_get_product_desc(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    return klass->product_desc;
}*/

const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (dev->usb_desc) {
        return dev->usb_desc;
    }
    return klass->usb_desc;
}

void usb_device_set_interface(USBDevice *dev, int intf,
                              int alt_old, int alt_new)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->set_interface) {
        klass->set_interface(dev, intf, alt_old, alt_new);
    }
}

void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->flush_ep_queue) {
        klass->flush_ep_queue(dev, ep);
    }
}

void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->ep_stopped) {
        klass->ep_stopped(dev, ep);
    }
}

int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps,
                             int streams)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->alloc_streams) {
        return klass->alloc_streams(dev, eps, nr_eps, streams);
    }
    return 0;
}

void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->free_streams) {
        klass->free_streams(dev, eps, nr_eps);
    }
}<|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/login/background_view.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/x11_util.h"
#include "base/string_util.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/status/clock_menu_button.h"
#include "chrome/browser/chromeos/status/feedback_menu_button.h"
#include "chrome/browser/chromeos/status/language_menu_button.h"
#include "chrome/browser/chromeos/status/network_menu_button.h"
#include "chrome/browser/chromeos/status/status_area_view.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "third_party/cros/chromeos_wm_ipc_enums.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "views/controls/label.h"
#include "views/screen.h"
#include "views/widget/widget_gtk.h"

// X Windows headers have "#define Status int". That interferes with
// NetworkLibrary header which defines enum "Status".
#include <X11/cursorfont.h>
#include <X11/Xcursor/Xcursor.h>

using views::WidgetGtk;

namespace chromeos {

BackgroundView::BackgroundView() : status_area_(NULL),
                                   os_version_label_(NULL),
                                   boot_times_label_(NULL),
                                   did_paint_(false) {
  views::Painter* painter = chromeos::CreateWizardPainter(
      &chromeos::BorderDefinition::kWizardBorder);
  set_background(views::Background::CreateBackgroundPainter(true, painter));
  InitStatusArea();
  InitInfoLabels();
}

static void ResetXCursor() {
  // TODO(sky): nuke this once new window manager is in place.
  // This gets rid of the ugly X default cursor.
  Display* display = x11_util::GetXDisplay();
  Cursor cursor = XCreateFontCursor(display, XC_left_ptr);
  XID root_window = x11_util::GetX11RootWindow();
  XSetWindowAttributes attr;
  attr.cursor = cursor;
  XChangeWindowAttributes(display, root_window, CWCursor, &attr);
}

// static
views::Widget* BackgroundView::CreateWindowContainingView(
    const gfx::Rect& bounds,
    BackgroundView** view) {
  ResetXCursor();

  WidgetGtk* window = new WidgetGtk(WidgetGtk::TYPE_WINDOW);
  window->Init(NULL, bounds);
  *view = new BackgroundView();
  window->SetContentsView(*view);

  (*view)->UpdateWindowType();

  // This keeps the window from flashing at startup.
  GdkWindow* gdk_window = window->GetNativeView()->window;
  gdk_window_set_back_pixmap(gdk_window, NULL, false);

  return window;
}

void BackgroundView::SetStatusAreaVisible(bool visible) {
  status_area_->SetVisible(visible);
}

void BackgroundView::Paint(gfx::Canvas* canvas) {
  views::View::Paint(canvas);
  if (!did_paint_) {
    did_paint_ = true;
    UpdateWindowType();
  }
}

void BackgroundView::Layout() {
  int corner_padding =
      chromeos::BorderDefinition::kWizardBorder.padding +
      chromeos::BorderDefinition::kWizardBorder.corner_radius / 2;
  int kInfoLeftPadding = 60;
  int kInfoBottomPadding = 40;
  int kInfoBetweenLinesPadding = 4;
  gfx::Size status_area_size = status_area_->GetPreferredSize();
  status_area_->SetBounds(
      width() - status_area_size.width() - corner_padding,
      corner_padding,
      status_area_size.width(),
      status_area_size.height());
  gfx::Size version_size = os_version_label_->GetPreferredSize();
  os_version_label_->SetBounds(
      kInfoLeftPadding,
      height() -
          ((2 * version_size.height()) +
          kInfoBottomPadding +
          kInfoBetweenLinesPadding),
      width() - 2 * kInfoLeftPadding,
      version_size.height());
  boot_times_label_->SetBounds(
      kInfoLeftPadding,
      height() - (version_size.height() + kInfoBottomPadding),
      width() - 2 * corner_padding,
      version_size.height());
}

void BackgroundView::ChildPreferredSizeChanged(View* child) {
  Layout();
  SchedulePaint();
}

gfx::NativeWindow BackgroundView::GetNativeWindow() const {
  return
      GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
}

bool BackgroundView::ShouldOpenButtonOptions(
    const views::View* button_view) const {
  if (button_view == status_area_->clock_view() ||
      button_view == status_area_->feedback_view() ||
      button_view == status_area_->language_view() ||
      button_view == status_area_->network_view()) {
    return false;
  }
  return true;
}

void BackgroundView::OpenButtonOptions(const views::View* button_view) const {
  // TODO(avayvod): Add some dialog for options or remove them completely.
}

bool BackgroundView::IsButtonVisible(const views::View* button_view) const {
  return true;
}

bool BackgroundView::IsBrowserMode() const {
  return false;
}

void BackgroundView::LocaleChanged() {
  Layout();
  SchedulePaint();
}

void BackgroundView::InitStatusArea() {
  DCHECK(status_area_ == NULL);
  status_area_ = new StatusAreaView(this);
  status_area_->Init();
  AddChildView(status_area_);
}

void BackgroundView::InitInfoLabels() {
  const SkColor kVersionColor = 0xff8eb1f4;
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();

  os_version_label_ = new views::Label();
  os_version_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  os_version_label_->SetColor(kVersionColor);
  os_version_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
  AddChildView(os_version_label_);
  boot_times_label_ = new views::Label();
  boot_times_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  boot_times_label_->SetColor(kVersionColor);
  boot_times_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
  AddChildView(boot_times_label_);

  if (CrosLibrary::Get()->EnsureLoaded()) {
    version_loader_.GetVersion(
        &version_consumer_, NewCallback(this, &BackgroundView::OnVersion));
    boot_times_loader_.GetBootTimes(
        &boot_times_consumer_, NewCallback(this, &BackgroundView::OnBootTimes));
  } else {
    os_version_label_->SetText(
        ASCIIToWide(CrosLibrary::Get()->load_error_string()));
  }
}

void BackgroundView::UpdateWindowType() {
  std::vector<int> params;
  params.push_back(did_paint_ ? 1 : 0);
  WmIpc::instance()->SetWindowType(
      GTK_WIDGET(GetNativeWindow()),
      WM_IPC_WINDOW_LOGIN_BACKGROUND,
      &params);
}

void BackgroundView::OnVersion(
    VersionLoader::Handle handle, std::string version) {
  std::string version_text = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
  version_text += ' ';
  version_text += l10n_util::GetStringUTF8(IDS_VERSION_FIELD_PREFIX);
  version_text += ' ';
  version_text += version;
  os_version_label_->SetText(ASCIIToWide(version_text));
}

void BackgroundView::OnBootTimes(
    BootTimesLoader::Handle handle, BootTimesLoader::BootTimes boot_times) {
  // TODO(davemoore) if we decide to keep these times visible we will need
  // to localize the strings.
  const char* kBootTimesNoChromeExec =
      "Boot took %.2f seconds (firmware %.2fs, kernel %.2fs, system %.2fs)";
  const char* kBootTimesChromeExec =
      "Boot took %.2f seconds "
      "(firmware %.2fs, kernel %.2fs, system %.2fs, chrome %.2fs)";
  std::string boot_times_text;

  if (boot_times.chrome_exec > 0) {
    boot_times_text =
        StringPrintf(
            kBootTimesChromeExec,
            boot_times.firmware + boot_times.login_prompt_ready,
            boot_times.firmware,
            boot_times.pre_startup,
            boot_times.chrome_exec - boot_times.pre_startup,
            boot_times.login_prompt_ready - boot_times.chrome_exec);
  } else {
    boot_times_text =
        StringPrintf(
            kBootTimesNoChromeExec,
            boot_times.firmware + boot_times.login_prompt_ready,
            boot_times.firmware,
            boot_times.pre_startup,
            boot_times.login_prompt_ready - boot_times.pre_startup);
  }
  boot_times_label_->SetText(ASCIIToWide(boot_times_text));
}

}  // namespace chromeos
<commit_msg>Made feedback icon hidden on login screen.<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/login/background_view.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/x11_util.h"
#include "base/string_util.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/status/clock_menu_button.h"
#include "chrome/browser/chromeos/status/feedback_menu_button.h"
#include "chrome/browser/chromeos/status/language_menu_button.h"
#include "chrome/browser/chromeos/status/network_menu_button.h"
#include "chrome/browser/chromeos/status/status_area_view.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "third_party/cros/chromeos_wm_ipc_enums.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "views/controls/label.h"
#include "views/screen.h"
#include "views/widget/widget_gtk.h"

// X Windows headers have "#define Status int". That interferes with
// NetworkLibrary header which defines enum "Status".
#include <X11/cursorfont.h>
#include <X11/Xcursor/Xcursor.h>

using views::WidgetGtk;

namespace chromeos {

BackgroundView::BackgroundView() : status_area_(NULL),
                                   os_version_label_(NULL),
                                   boot_times_label_(NULL),
                                   did_paint_(false) {
  views::Painter* painter = chromeos::CreateWizardPainter(
      &chromeos::BorderDefinition::kWizardBorder);
  set_background(views::Background::CreateBackgroundPainter(true, painter));
  InitStatusArea();
  InitInfoLabels();
}

static void ResetXCursor() {
  // TODO(sky): nuke this once new window manager is in place.
  // This gets rid of the ugly X default cursor.
  Display* display = x11_util::GetXDisplay();
  Cursor cursor = XCreateFontCursor(display, XC_left_ptr);
  XID root_window = x11_util::GetX11RootWindow();
  XSetWindowAttributes attr;
  attr.cursor = cursor;
  XChangeWindowAttributes(display, root_window, CWCursor, &attr);
}

// static
views::Widget* BackgroundView::CreateWindowContainingView(
    const gfx::Rect& bounds,
    BackgroundView** view) {
  ResetXCursor();

  WidgetGtk* window = new WidgetGtk(WidgetGtk::TYPE_WINDOW);
  window->Init(NULL, bounds);
  *view = new BackgroundView();
  window->SetContentsView(*view);

  (*view)->UpdateWindowType();

  // This keeps the window from flashing at startup.
  GdkWindow* gdk_window = window->GetNativeView()->window;
  gdk_window_set_back_pixmap(gdk_window, NULL, false);

  return window;
}

void BackgroundView::SetStatusAreaVisible(bool visible) {
  status_area_->SetVisible(visible);
}

void BackgroundView::Paint(gfx::Canvas* canvas) {
  views::View::Paint(canvas);
  if (!did_paint_) {
    did_paint_ = true;
    UpdateWindowType();
  }
}

void BackgroundView::Layout() {
  int corner_padding =
      chromeos::BorderDefinition::kWizardBorder.padding +
      chromeos::BorderDefinition::kWizardBorder.corner_radius / 2;
  int kInfoLeftPadding = 60;
  int kInfoBottomPadding = 40;
  int kInfoBetweenLinesPadding = 4;
  gfx::Size status_area_size = status_area_->GetPreferredSize();
  status_area_->SetBounds(
      width() - status_area_size.width() - corner_padding,
      corner_padding,
      status_area_size.width(),
      status_area_size.height());
  gfx::Size version_size = os_version_label_->GetPreferredSize();
  os_version_label_->SetBounds(
      kInfoLeftPadding,
      height() -
          ((2 * version_size.height()) +
          kInfoBottomPadding +
          kInfoBetweenLinesPadding),
      width() - 2 * kInfoLeftPadding,
      version_size.height());
  boot_times_label_->SetBounds(
      kInfoLeftPadding,
      height() - (version_size.height() + kInfoBottomPadding),
      width() - 2 * corner_padding,
      version_size.height());
}

void BackgroundView::ChildPreferredSizeChanged(View* child) {
  Layout();
  SchedulePaint();
}

gfx::NativeWindow BackgroundView::GetNativeWindow() const {
  return
      GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
}

bool BackgroundView::ShouldOpenButtonOptions(
    const views::View* button_view) const {
  if (button_view == status_area_->clock_view() ||
      button_view == status_area_->feedback_view() ||
      button_view == status_area_->language_view() ||
      button_view == status_area_->network_view()) {
    return false;
  }
  return true;
}

void BackgroundView::OpenButtonOptions(const views::View* button_view) const {
  // TODO(avayvod): Add some dialog for options or remove them completely.
}

bool BackgroundView::IsButtonVisible(const views::View* button_view) const {
  if (button_view == status_area_->feedback_view())
    return false;
  return true;
}

bool BackgroundView::IsBrowserMode() const {
  return false;
}

void BackgroundView::LocaleChanged() {
  Layout();
  SchedulePaint();
}

void BackgroundView::InitStatusArea() {
  DCHECK(status_area_ == NULL);
  status_area_ = new StatusAreaView(this);
  status_area_->Init();
  status_area_->Update();
  AddChildView(status_area_);
}

void BackgroundView::InitInfoLabels() {
  const SkColor kVersionColor = 0xff8eb1f4;
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();

  os_version_label_ = new views::Label();
  os_version_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  os_version_label_->SetColor(kVersionColor);
  os_version_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
  AddChildView(os_version_label_);
  boot_times_label_ = new views::Label();
  boot_times_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  boot_times_label_->SetColor(kVersionColor);
  boot_times_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
  AddChildView(boot_times_label_);

  if (CrosLibrary::Get()->EnsureLoaded()) {
    version_loader_.GetVersion(
        &version_consumer_, NewCallback(this, &BackgroundView::OnVersion));
    boot_times_loader_.GetBootTimes(
        &boot_times_consumer_, NewCallback(this, &BackgroundView::OnBootTimes));
  } else {
    os_version_label_->SetText(
        ASCIIToWide(CrosLibrary::Get()->load_error_string()));
  }
}

void BackgroundView::UpdateWindowType() {
  std::vector<int> params;
  params.push_back(did_paint_ ? 1 : 0);
  WmIpc::instance()->SetWindowType(
      GTK_WIDGET(GetNativeWindow()),
      WM_IPC_WINDOW_LOGIN_BACKGROUND,
      &params);
}

void BackgroundView::OnVersion(
    VersionLoader::Handle handle, std::string version) {
  std::string version_text = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
  version_text += ' ';
  version_text += l10n_util::GetStringUTF8(IDS_VERSION_FIELD_PREFIX);
  version_text += ' ';
  version_text += version;
  os_version_label_->SetText(ASCIIToWide(version_text));
}

void BackgroundView::OnBootTimes(
    BootTimesLoader::Handle handle, BootTimesLoader::BootTimes boot_times) {
  // TODO(davemoore) if we decide to keep these times visible we will need
  // to localize the strings.
  const char* kBootTimesNoChromeExec =
      "Boot took %.2f seconds (firmware %.2fs, kernel %.2fs, system %.2fs)";
  const char* kBootTimesChromeExec =
      "Boot took %.2f seconds "
      "(firmware %.2fs, kernel %.2fs, system %.2fs, chrome %.2fs)";
  std::string boot_times_text;

  if (boot_times.chrome_exec > 0) {
    boot_times_text =
        StringPrintf(
            kBootTimesChromeExec,
            boot_times.firmware + boot_times.login_prompt_ready,
            boot_times.firmware,
            boot_times.pre_startup,
            boot_times.chrome_exec - boot_times.pre_startup,
            boot_times.login_prompt_ready - boot_times.chrome_exec);
  } else {
    boot_times_text =
        StringPrintf(
            kBootTimesNoChromeExec,
            boot_times.firmware + boot_times.login_prompt_ready,
            boot_times.firmware,
            boot_times.pre_startup,
            boot_times.login_prompt_ready - boot_times.pre_startup);
  }
  boot_times_label_->SetText(ASCIIToWide(boot_times_text));
}

}  // 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/dom_ui/browser_options_handler.h"

#include "app/l10n_util.h"
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/custom_home_pages_table_model.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/session_startup_pref.h"
#include "chrome/installer/util/browser_distribution.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

BrowserOptionsHandler::BrowserOptionsHandler()
    : template_url_model_(NULL), startup_custom_pages_table_model_(NULL) {
#if !defined(OS_MACOSX)
  default_browser_worker_ = new ShellIntegration::DefaultBrowserWorker(this);
#endif
}

BrowserOptionsHandler::~BrowserOptionsHandler() {
  if (default_browser_worker_.get())
    default_browser_worker_->ObserverDestroyed();
  if (template_url_model_)
    template_url_model_->RemoveObserver(this);
}

void BrowserOptionsHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);
  localized_strings->SetString(L"startupGroupName",
      l10n_util::GetString(IDS_OPTIONS_STARTUP_GROUP_NAME));
  localized_strings->SetString(L"startupShowDefaultAndNewTab",
      l10n_util::GetString(IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB));
  localized_strings->SetString(L"startupShowLastSession",
      l10n_util::GetString(IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION));
  localized_strings->SetString(L"startupShowPages",
      l10n_util::GetString(IDS_OPTIONS_STARTUP_SHOW_PAGES));
  localized_strings->SetString(L"startupAddButton",
      l10n_util::GetString(IDS_OPTIONS_STARTUP_ADD_BUTTON));
  localized_strings->SetString(L"startupRemoveButton",
      l10n_util::GetString(IDS_OPTIONS_STARTUP_REMOVE_BUTTON));
  localized_strings->SetString(L"startupUseCurrent",
      l10n_util::GetString(IDS_OPTIONS_STARTUP_USE_CURRENT));
  localized_strings->SetString(L"homepageGroupName",
      l10n_util::GetString(IDS_OPTIONS_HOMEPAGE_GROUP_NAME));
  localized_strings->SetString(L"homepageUseNewTab",
      l10n_util::GetString(IDS_OPTIONS_HOMEPAGE_USE_NEWTAB));
  localized_strings->SetString(L"homepageUseURL",
      l10n_util::GetString(IDS_OPTIONS_HOMEPAGE_USE_URL));
  localized_strings->SetString(L"homepageShowButton",
      l10n_util::GetString(IDS_OPTIONS_HOMEPAGE_SHOW_BUTTON));
  localized_strings->SetString(L"defaultSearchGroupName",
      l10n_util::GetString(IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME));
  localized_strings->SetString(L"defaultSearchManageEnginesLink",
      l10n_util::GetString(IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES_LINK));
  localized_strings->SetString(L"defaultBrowserGroupName",
      l10n_util::GetString(IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME));
  localized_strings->SetString(L"defaultBrowserUnknown",
      l10n_util::GetStringF(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN,
          l10n_util::GetString(IDS_PRODUCT_NAME)));
  localized_strings->SetString(L"defaultBrowserUseAsDefault",
      l10n_util::GetStringF(IDS_OPTIONS_DEFAULTBROWSER_USEASDEFAULT,
          l10n_util::GetString(IDS_PRODUCT_NAME)));
}

void BrowserOptionsHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback(
      "becomeDefaultBrowser",
      NewCallback(this, &BrowserOptionsHandler::BecomeDefaultBrowser));
  dom_ui_->RegisterMessageCallback(
      "setDefaultSearchEngine",
      NewCallback(this, &BrowserOptionsHandler::SetDefaultSearchEngine));
  dom_ui_->RegisterMessageCallback(
      "removeStartupPages",
      NewCallback(this, &BrowserOptionsHandler::RemoveStartupPages));
  dom_ui_->RegisterMessageCallback(
      "setStartupPagesToCurrentPages",
      NewCallback(this, &BrowserOptionsHandler::SetStartupPagesToCurrentPages));
}

void BrowserOptionsHandler::Initialize() {
  UpdateDefaultBrowserState();
  UpdateStartupPages();
  UpdateSearchEngines();
}

void BrowserOptionsHandler::UpdateDefaultBrowserState() {
#if defined(OS_WIN)
  // Check for side-by-side first.
  if (!BrowserDistribution::GetDistribution()->CanSetAsDefault()) {
    SetDefaultBrowserUIString(IDS_OPTIONS_DEFAULTBROWSER_SXS);
    return;
  }
#endif

#if defined(OS_MACOSX)
  ShellIntegration::DefaultBrowserState state =
      ShellIntegration::IsDefaultBrowser();
  int status_string_id;
  if (state == ShellIntegration::IS_DEFAULT_BROWSER)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
  else if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
  else
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;

  SetDefaultBrowserUIString(status_string_id);
#else
  default_browser_worker_->StartCheckDefaultBrowser();
#endif
}

void BrowserOptionsHandler::BecomeDefaultBrowser(const Value* value) {
#if defined(OS_MACOSX)
  if (ShellIntegration::SetAsDefaultBrowser())
    UpdateDefaultBrowserState();
#else
  default_browser_worker_->StartSetAsDefaultBrowser();
  // Callback takes care of updating UI.
#endif
}

int BrowserOptionsHandler::StatusStringIdForState(
    ShellIntegration::DefaultBrowserState state) {
  if (state == ShellIntegration::IS_DEFAULT_BROWSER)
    return IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
  if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
    return IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
  return IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
}

void BrowserOptionsHandler::SetDefaultBrowserUIState(
    ShellIntegration::DefaultBrowserUIState state) {
  int status_string_id;
  if (state == ShellIntegration::STATE_IS_DEFAULT)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
  else if (state == ShellIntegration::STATE_NOT_DEFAULT)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
  else if (state == ShellIntegration::STATE_UNKNOWN)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
  else
    return;  // Still processing.

  SetDefaultBrowserUIString(status_string_id);
}

void BrowserOptionsHandler::SetDefaultBrowserUIString(int status_string_id) {
  scoped_ptr<Value> status_string(Value::CreateStringValue(
      l10n_util::GetStringF(status_string_id,
                            l10n_util::GetString(IDS_PRODUCT_NAME))));

  scoped_ptr<Value> is_default(Value::CreateBooleanValue(
      status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT));

  dom_ui_->CallJavascriptFunction(
      L"BrowserOptions.updateDefaultBrowserState",
      *(status_string.get()), *(is_default.get()));
}

void BrowserOptionsHandler::OnTemplateURLModelChanged() {
  if (!template_url_model_ || !template_url_model_->loaded())
    return;

  const TemplateURL* default_url =
      template_url_model_->GetDefaultSearchProvider();

  int default_index = 0;
  ListValue search_engines;
  std::vector<const TemplateURL*> model_urls =
      template_url_model_->GetTemplateURLs();
  for (size_t i = 0; i < model_urls.size(); ++i) {
    if (!model_urls[i]->ShowInDefaultList())
      continue;

    DictionaryValue* entry = new DictionaryValue();
    entry->SetString(L"name", model_urls[i]->short_name());
    entry->SetInteger(L"index", i);
    search_engines.Append(entry);
    if (model_urls[i] == default_url)
      default_index = i;
  }

  scoped_ptr<Value> default_value(Value::CreateIntegerValue(default_index));

  dom_ui_->CallJavascriptFunction(L"BrowserOptions.updateSearchEngines",
                                  search_engines, *(default_value.get()));
}

void BrowserOptionsHandler::SetDefaultSearchEngine(const Value* value) {
  if (!value || !value->IsType(Value::TYPE_LIST)) {
    NOTREACHED();
    return;
  }
  const ListValue* param_values = static_cast<const ListValue*>(value);
  std::string string_value;
  if (param_values->GetSize() != 1 ||
      !param_values->GetString(0, &string_value)) {
    NOTREACHED();
    return;
  }
  int selected_index;
  base::StringToInt(string_value, &selected_index);

  std::vector<const TemplateURL*> model_urls =
      template_url_model_->GetTemplateURLs();
  if (selected_index >= 0 &&
      selected_index < static_cast<int>(model_urls.size()))
    template_url_model_->SetDefaultSearchProvider(model_urls[selected_index]);
}

void BrowserOptionsHandler::UpdateSearchEngines() {
  template_url_model_ = dom_ui_->GetProfile()->GetTemplateURLModel();
  if (template_url_model_) {
    template_url_model_->Load();
    template_url_model_->AddObserver(this);
    OnTemplateURLModelChanged();
  }
}

void BrowserOptionsHandler::UpdateStartupPages() {
  Profile* profile = dom_ui_->GetProfile();
  startup_custom_pages_table_model_.reset(
      new CustomHomePagesTableModel(profile));
  startup_custom_pages_table_model_->SetObserver(this);

  const SessionStartupPref startup_pref =
      SessionStartupPref::GetStartupPref(profile->GetPrefs());
  startup_custom_pages_table_model_->SetURLs(startup_pref.urls);
}

void BrowserOptionsHandler::OnModelChanged() {
  // TODO(stuartmorgan): Add support for showing favicons.
  ListValue startup_pages;
  int page_count = startup_custom_pages_table_model_->RowCount();
  for (int i = 0; i < page_count; ++i) {
    DictionaryValue* entry = new DictionaryValue();
    entry->SetString(L"title",
                     startup_custom_pages_table_model_->GetText(i, 0));
    entry->SetString(L"tooltip",
                     startup_custom_pages_table_model_->GetTooltip(i));
    startup_pages.Append(entry);
  }

  dom_ui_->CallJavascriptFunction(L"BrowserOptions.updateStartupPages",
                                  startup_pages);
}

void BrowserOptionsHandler::OnItemsChanged(int start, int length) {
  OnModelChanged();
}

void BrowserOptionsHandler::OnItemsAdded(int start, int length) {
  OnModelChanged();
}

void BrowserOptionsHandler::OnItemsRemoved(int start, int length) {
  OnModelChanged();
}

void BrowserOptionsHandler::SetStartupPagesToCurrentPages(const Value* value) {
  startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
  SaveStartupPagesPref();
}

void BrowserOptionsHandler::RemoveStartupPages(const Value* value) {
  if (!value || !value->IsType(Value::TYPE_LIST)) {
    NOTREACHED();
    return;
  }
  const ListValue* param_values = static_cast<const ListValue*>(value);
  for (int i = param_values->GetSize() - 1; i >= 0; --i) {
    std::string string_value;
    if (!param_values->GetString(i, &string_value)) {
      NOTREACHED();
      return;
    }
    int selected_index;
    base::StringToInt(string_value, &selected_index);
    if (selected_index < 0 ||
        selected_index >= startup_custom_pages_table_model_->RowCount()) {
      NOTREACHED();
      return;
    }
    startup_custom_pages_table_model_->Remove(selected_index);
  }

  SaveStartupPagesPref();
}

void BrowserOptionsHandler::SaveStartupPagesPref() {
  PrefService* prefs = dom_ui_->GetProfile()->GetPrefs();

  SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs);
  pref.urls = startup_custom_pages_table_model_->GetURLs();

  SessionStartupPref::SetStartupPref(prefs, pref);
}
<commit_msg>Convert browser/dom_ui/browser_options_handler.cc to stop using wstrings/wchar_t*s.<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/dom_ui/browser_options_handler.h"

#include "app/l10n_util.h"
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/custom_home_pages_table_model.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/session_startup_pref.h"
#include "chrome/installer/util/browser_distribution.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

BrowserOptionsHandler::BrowserOptionsHandler()
    : template_url_model_(NULL), startup_custom_pages_table_model_(NULL) {
#if !defined(OS_MACOSX)
  default_browser_worker_ = new ShellIntegration::DefaultBrowserWorker(this);
#endif
}

BrowserOptionsHandler::~BrowserOptionsHandler() {
  if (default_browser_worker_.get())
    default_browser_worker_->ObserverDestroyed();
  if (template_url_model_)
    template_url_model_->RemoveObserver(this);
}

void BrowserOptionsHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);
  localized_strings->SetString("startupGroupName",
      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_GROUP_NAME));
  localized_strings->SetString("startupShowDefaultAndNewTab",
      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB));
  localized_strings->SetString("startupShowLastSession",
      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION));
  localized_strings->SetString("startupShowPages",
      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_PAGES));
  localized_strings->SetString("startupAddButton",
      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_ADD_BUTTON));
  localized_strings->SetString("startupRemoveButton",
      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_REMOVE_BUTTON));
  localized_strings->SetString("startupUseCurrent",
      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_USE_CURRENT));
  localized_strings->SetString("homepageGroupName",
      l10n_util::GetStringUTF16(IDS_OPTIONS_HOMEPAGE_GROUP_NAME));
  localized_strings->SetString("homepageUseNewTab",
      l10n_util::GetStringUTF16(IDS_OPTIONS_HOMEPAGE_USE_NEWTAB));
  localized_strings->SetString("homepageUseURL",
      l10n_util::GetStringUTF16(IDS_OPTIONS_HOMEPAGE_USE_URL));
  localized_strings->SetString("homepageShowButton",
      l10n_util::GetStringUTF16(IDS_OPTIONS_HOMEPAGE_SHOW_BUTTON));
  localized_strings->SetString("defaultSearchGroupName",
      l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME));
  localized_strings->SetString("defaultSearchManageEnginesLink",
      l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES_LINK));
  localized_strings->SetString("defaultBrowserGroupName",
      l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME));
  localized_strings->SetString("defaultBrowserUnknown",
      l10n_util::GetStringFUTF16(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN,
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
  localized_strings->SetString("defaultBrowserUseAsDefault",
      l10n_util::GetStringFUTF16(IDS_OPTIONS_DEFAULTBROWSER_USEASDEFAULT,
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
}

void BrowserOptionsHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback(
      "becomeDefaultBrowser",
      NewCallback(this, &BrowserOptionsHandler::BecomeDefaultBrowser));
  dom_ui_->RegisterMessageCallback(
      "setDefaultSearchEngine",
      NewCallback(this, &BrowserOptionsHandler::SetDefaultSearchEngine));
  dom_ui_->RegisterMessageCallback(
      "removeStartupPages",
      NewCallback(this, &BrowserOptionsHandler::RemoveStartupPages));
  dom_ui_->RegisterMessageCallback(
      "setStartupPagesToCurrentPages",
      NewCallback(this, &BrowserOptionsHandler::SetStartupPagesToCurrentPages));
}

void BrowserOptionsHandler::Initialize() {
  UpdateDefaultBrowserState();
  UpdateStartupPages();
  UpdateSearchEngines();
}

void BrowserOptionsHandler::UpdateDefaultBrowserState() {
#if defined(OS_WIN)
  // Check for side-by-side first.
  if (!BrowserDistribution::GetDistribution()->CanSetAsDefault()) {
    SetDefaultBrowserUIString(IDS_OPTIONS_DEFAULTBROWSER_SXS);
    return;
  }
#endif

#if defined(OS_MACOSX)
  ShellIntegration::DefaultBrowserState state =
      ShellIntegration::IsDefaultBrowser();
  int status_string_id;
  if (state == ShellIntegration::IS_DEFAULT_BROWSER)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
  else if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
  else
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;

  SetDefaultBrowserUIString(status_string_id);
#else
  default_browser_worker_->StartCheckDefaultBrowser();
#endif
}

void BrowserOptionsHandler::BecomeDefaultBrowser(const Value* value) {
#if defined(OS_MACOSX)
  if (ShellIntegration::SetAsDefaultBrowser())
    UpdateDefaultBrowserState();
#else
  default_browser_worker_->StartSetAsDefaultBrowser();
  // Callback takes care of updating UI.
#endif
}

int BrowserOptionsHandler::StatusStringIdForState(
    ShellIntegration::DefaultBrowserState state) {
  if (state == ShellIntegration::IS_DEFAULT_BROWSER)
    return IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
  if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
    return IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
  return IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
}

void BrowserOptionsHandler::SetDefaultBrowserUIState(
    ShellIntegration::DefaultBrowserUIState state) {
  int status_string_id;
  if (state == ShellIntegration::STATE_IS_DEFAULT)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
  else if (state == ShellIntegration::STATE_NOT_DEFAULT)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
  else if (state == ShellIntegration::STATE_UNKNOWN)
    status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
  else
    return;  // Still processing.

  SetDefaultBrowserUIString(status_string_id);
}

void BrowserOptionsHandler::SetDefaultBrowserUIString(int status_string_id) {
  scoped_ptr<Value> status_string(Value::CreateStringValue(
      l10n_util::GetStringFUTF16(status_string_id,
                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))));

  scoped_ptr<Value> is_default(Value::CreateBooleanValue(
      status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT));

  dom_ui_->CallJavascriptFunction(
      L"BrowserOptions.updateDefaultBrowserState",
      *(status_string.get()), *(is_default.get()));
}

void BrowserOptionsHandler::OnTemplateURLModelChanged() {
  if (!template_url_model_ || !template_url_model_->loaded())
    return;

  const TemplateURL* default_url =
      template_url_model_->GetDefaultSearchProvider();

  int default_index = 0;
  ListValue search_engines;
  std::vector<const TemplateURL*> model_urls =
      template_url_model_->GetTemplateURLs();
  for (size_t i = 0; i < model_urls.size(); ++i) {
    if (!model_urls[i]->ShowInDefaultList())
      continue;

    DictionaryValue* entry = new DictionaryValue();
    entry->SetString("name", WideToUTF16Hack(model_urls[i]->short_name()));
    entry->SetInteger("index", i);
    search_engines.Append(entry);
    if (model_urls[i] == default_url)
      default_index = i;
  }

  scoped_ptr<Value> default_value(Value::CreateIntegerValue(default_index));

  dom_ui_->CallJavascriptFunction(L"BrowserOptions.updateSearchEngines",
                                  search_engines, *(default_value.get()));
}

void BrowserOptionsHandler::SetDefaultSearchEngine(const Value* value) {
  if (!value || !value->IsType(Value::TYPE_LIST)) {
    NOTREACHED();
    return;
  }
  const ListValue* param_values = static_cast<const ListValue*>(value);
  std::string string_value;
  if (param_values->GetSize() != 1 ||
      !param_values->GetString(0, &string_value)) {
    NOTREACHED();
    return;
  }
  int selected_index;
  base::StringToInt(string_value, &selected_index);

  std::vector<const TemplateURL*> model_urls =
      template_url_model_->GetTemplateURLs();
  if (selected_index >= 0 &&
      selected_index < static_cast<int>(model_urls.size()))
    template_url_model_->SetDefaultSearchProvider(model_urls[selected_index]);
}

void BrowserOptionsHandler::UpdateSearchEngines() {
  template_url_model_ = dom_ui_->GetProfile()->GetTemplateURLModel();
  if (template_url_model_) {
    template_url_model_->Load();
    template_url_model_->AddObserver(this);
    OnTemplateURLModelChanged();
  }
}

void BrowserOptionsHandler::UpdateStartupPages() {
  Profile* profile = dom_ui_->GetProfile();
  startup_custom_pages_table_model_.reset(
      new CustomHomePagesTableModel(profile));
  startup_custom_pages_table_model_->SetObserver(this);

  const SessionStartupPref startup_pref =
      SessionStartupPref::GetStartupPref(profile->GetPrefs());
  startup_custom_pages_table_model_->SetURLs(startup_pref.urls);
}

void BrowserOptionsHandler::OnModelChanged() {
  // TODO(stuartmorgan): Add support for showing favicons.
  ListValue startup_pages;
  int page_count = startup_custom_pages_table_model_->RowCount();
  for (int i = 0; i < page_count; ++i) {
    DictionaryValue* entry = new DictionaryValue();
    entry->SetString("title", WideToUTF16Hack(
                        startup_custom_pages_table_model_->GetText(i, 0)));
    entry->SetString("tooltip", WideToUTF16Hack(
                         startup_custom_pages_table_model_->GetTooltip(i)));
    startup_pages.Append(entry);
  }

  dom_ui_->CallJavascriptFunction(L"BrowserOptions.updateStartupPages",
                                  startup_pages);
}

void BrowserOptionsHandler::OnItemsChanged(int start, int length) {
  OnModelChanged();
}

void BrowserOptionsHandler::OnItemsAdded(int start, int length) {
  OnModelChanged();
}

void BrowserOptionsHandler::OnItemsRemoved(int start, int length) {
  OnModelChanged();
}

void BrowserOptionsHandler::SetStartupPagesToCurrentPages(const Value* value) {
  startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
  SaveStartupPagesPref();
}

void BrowserOptionsHandler::RemoveStartupPages(const Value* value) {
  if (!value || !value->IsType(Value::TYPE_LIST)) {
    NOTREACHED();
    return;
  }
  const ListValue* param_values = static_cast<const ListValue*>(value);
  for (int i = param_values->GetSize() - 1; i >= 0; --i) {
    std::string string_value;
    if (!param_values->GetString(i, &string_value)) {
      NOTREACHED();
      return;
    }
    int selected_index;
    base::StringToInt(string_value, &selected_index);
    if (selected_index < 0 ||
        selected_index >= startup_custom_pages_table_model_->RowCount()) {
      NOTREACHED();
      return;
    }
    startup_custom_pages_table_model_->Remove(selected_index);
  }

  SaveStartupPagesPref();
}

void BrowserOptionsHandler::SaveStartupPagesPref() {
  PrefService* prefs = dom_ui_->GetProfile()->GetPrefs();

  SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs);
  pref.urls = startup_custom_pages_table_model_->GetURLs();

  SessionStartupPref::SetStartupPref(prefs, pref);
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/dom_ui/chrome_url_data_manager.h"

#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/ref_counted_util.h"
#include "googleurl/src/url_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_job.h"
#ifdef CHROME_PERSONALIZATION
// TODO(timsteele): Remove all CHROME_PERSONALIZATION code in this file.
// It is only temporarily needed to configure some personalization data sources
// that will go away soon.
#include "chrome/personalization/personalization.h"
#endif

// The URL scheme used for internal chrome resources.
// TODO(glen): Choose a better location for this.
static const char kChromeURLScheme[] = "chrome-ui";

// The single global instance of ChromeURLDataManager.
ChromeURLDataManager chrome_url_data_manager;

// URLRequestChromeJob is a URLRequestJob that manages running chrome-internal
// resource requests asynchronously.
// It hands off URL requests to ChromeURLDataManager, which asynchronously
// calls back once the data is available.
class URLRequestChromeJob : public URLRequestJob {
 public:
  explicit URLRequestChromeJob(URLRequest* request);
  virtual ~URLRequestChromeJob();

  // URLRequestJob implementation.
  virtual void Start();
  virtual void Kill();
  virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
  virtual bool GetMimeType(std::string* mime_type);

  // Called by ChromeURLDataManager to notify us that the data blob is ready
  // for us.
  void DataAvailable(RefCountedBytes* bytes);

  void SetMimeType(const std::string& mime_type) {
    mime_type_ = mime_type;
  }

 private:
  // Helper for Start(), to let us start asynchronously.
  // (This pattern is shared by most URLRequestJob implementations.)
  void StartAsync();

  // Do the actual copy from data_ (the data we're serving) into |buf|.
  // Separate from ReadRawData so we can handle async I/O.
  void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read);

  // The actual data we're serving.  NULL until it's been fetched.
  scoped_refptr<RefCountedBytes> data_;
  // The current offset into the data that we're handing off to our
  // callers via the Read interfaces.
  int data_offset_;

  // For async reads, we keep around a pointer to the buffer that
  // we're reading into.
  scoped_refptr<net::IOBuffer> pending_buf_;
  int pending_buf_size_;
  std::string mime_type_;

  DISALLOW_EVIL_CONSTRUCTORS(URLRequestChromeJob);
};

// URLRequestChromeFileJob is a URLRequestJob that acts like a file:// URL
class URLRequestChromeFileJob : public URLRequestFileJob {
 public:
  URLRequestChromeFileJob(URLRequest* request, const FilePath& path);
  virtual ~URLRequestChromeFileJob();

 private:
  DISALLOW_EVIL_CONSTRUCTORS(URLRequestChromeFileJob);
};

void RegisterURLRequestChromeJob() {
  // Being a standard scheme allows us to resolve relative paths. This method
  // is invoked multiple times during testing, so only add the scheme once.
  url_parse::Component url_scheme_component(0, arraysize(kChromeURLScheme) - 1);
  if (!url_util::IsStandard(kChromeURLScheme, arraysize(kChromeURLScheme) - 1,
                            url_scheme_component)) {
    url_util::AddStandardScheme(kChromeURLScheme);
  }

  std::wstring inspector_dir;
  if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
    chrome_url_data_manager.AddFileSource("inspector", inspector_dir);

  URLRequest::RegisterProtocolFactory(kChromeURLScheme,
                                      &ChromeURLDataManager::Factory);
#ifdef CHROME_PERSONALIZATION
  url_util::AddStandardScheme(kPersonalizationScheme);
  URLRequest::RegisterProtocolFactory(kPersonalizationScheme,
                                      &ChromeURLDataManager::Factory);
#endif
}

void UnregisterURLRequestChromeJob() {
  std::wstring inspector_dir;
  if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
    chrome_url_data_manager.RemoveFileSource("inspector");
}

// static
void ChromeURLDataManager::URLToRequest(const GURL& url,
                                        std::string* source_name,
                                        std::string* path) {
#ifdef CHROME_PERSONALIZATION
  DCHECK(url.SchemeIs(kChromeURLScheme) ||
         url.SchemeIs(kPersonalizationScheme));
#else
  DCHECK(url.SchemeIs(kChromeURLScheme));
#endif

  if (!url.is_valid()) {
    NOTREACHED();
    return;
  }

  // Our input looks like: chrome-ui://source_name/extra_bits?foo .
  // So the url's "host" is our source, and everything after the host is
  // the path.
  source_name->assign(url.host());

  const std::string& spec = url.possibly_invalid_spec();
  const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
  int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
  ++offset;  // Skip the slash at the beginning of the path.
  if (offset < static_cast<int>(spec.size()))
    path->assign(spec.substr(offset));
}

// static
bool ChromeURLDataManager::URLToFilePath(const GURL& url,
                                         std::wstring* file_path) {
  // Parse the URL into a request for a source and path.
  std::string source_name;
  std::string relative_path;
  URLToRequest(url, &source_name, &relative_path);

  FileSourceMap::const_iterator i(
      chrome_url_data_manager.file_sources_.find(source_name));
  if (i == chrome_url_data_manager.file_sources_.end())
    return false;

  file_path->assign(i->second);
  file_util::AppendToPath(file_path, UTF8ToWide(relative_path));
  return true;
}

ChromeURLDataManager::ChromeURLDataManager() : next_request_id_(0) { }

ChromeURLDataManager::~ChromeURLDataManager() { }

void ChromeURLDataManager::AddDataSource(scoped_refptr<DataSource> source) {
  // TODO(jackson): A new data source with same name should not clobber the
  // existing one.
  data_sources_[source->source_name()] = source;
}

void ChromeURLDataManager::AddFileSource(const std::string& source_name,
                                         const std::wstring& file_path) {
  DCHECK(file_sources_.count(source_name) == 0);
  file_sources_[source_name] = file_path;
}

void ChromeURLDataManager::RemoveFileSource(const std::string& source_name) {
  DCHECK(file_sources_.count(source_name) == 1);
  file_sources_.erase(source_name);
}

bool ChromeURLDataManager::StartRequest(const GURL& url,
                                        URLRequestChromeJob* job) {
  // Parse the URL into a request for a source and path.
  std::string source_name;
  std::string path;
  URLToRequest(url, &source_name, &path);

  // Look up the data source for the request.
  DataSourceMap::iterator i = data_sources_.find(source_name);
  if (i == data_sources_.end())
    return false;
  DataSource* source = i->second;

  // Save this request so we know where to send the data.
  RequestID request_id = next_request_id_++;
  pending_requests_.insert(std::make_pair(request_id, job));

  // TODO(eroman): would be nicer if the mimetype were set at the same time
  // as the data blob. For now do it here, since NotifyHeadersComplete() is
  // going to get called once we return.
  job->SetMimeType(source->GetMimeType(path));

  // Forward along the request to the data source.
  source->message_loop()->PostTask(FROM_HERE,
      NewRunnableMethod(source, &DataSource::StartDataRequest,
                        path, request_id));
  return true;
}

void ChromeURLDataManager::RemoveRequest(URLRequestChromeJob* job) {
  // Remove the request from our list of pending requests.
  // If/when the source sends the data that was requested, the data will just
  // be thrown away.
  for (PendingRequestMap::iterator i = pending_requests_.begin();
       i != pending_requests_.end(); ++i) {
    if (i->second == job) {
      pending_requests_.erase(i);
      return;
    }
  }
}

void ChromeURLDataManager::DataAvailable(
    RequestID request_id,
    scoped_refptr<RefCountedBytes> bytes) {
  // Forward this data on to the pending URLRequest, if it exists.
  PendingRequestMap::iterator i = pending_requests_.find(request_id);
  if (i != pending_requests_.end()) {
    URLRequestChromeJob* job = i->second;
    pending_requests_.erase(i);
    job->DataAvailable(bytes);
  }
}

void ChromeURLDataManager::DataSource::SendResponse(
    RequestID request_id,
    RefCountedBytes* bytes) {
  g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
      NewRunnableMethod(&chrome_url_data_manager,
                        &ChromeURLDataManager::DataAvailable,
                        request_id, scoped_refptr<RefCountedBytes>(bytes)));
}

// static
URLRequestJob* ChromeURLDataManager::Factory(URLRequest* request,
                                             const std::string& scheme) {
  // Try first with a file handler
  std::wstring path;
  if (ChromeURLDataManager::URLToFilePath(request->url(), &path))
    return new URLRequestChromeFileJob(request,
                                       FilePath::FromWStringHack(path));

  // Fall back to using a custom handler
  return new URLRequestChromeJob(request);
}

URLRequestChromeJob::URLRequestChromeJob(URLRequest* request)
    : URLRequestJob(request), data_offset_(0) {}

URLRequestChromeJob::~URLRequestChromeJob() {
}

void URLRequestChromeJob::Start() {
  // Start reading asynchronously so that all error reporting and data
  // callbacks happen as they would for network requests.
  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
      this, &URLRequestChromeJob::StartAsync));
}

void URLRequestChromeJob::Kill() {
  chrome_url_data_manager.RemoveRequest(this);
}

bool URLRequestChromeJob::GetMimeType(std::string* mime_type) {
  *mime_type = mime_type_;
  return !mime_type_.empty();
}

void URLRequestChromeJob::DataAvailable(RefCountedBytes* bytes) {
  if (bytes) {
    // The request completed, and we have all the data.
    // Clear any IO pending status.
    SetStatus(URLRequestStatus());

    data_ = bytes;
    int bytes_read;
    if (pending_buf_.get()) {
      CompleteRead(pending_buf_, pending_buf_size_, &bytes_read);
      NotifyReadComplete(bytes_read);
      pending_buf_ = NULL;
    }
  } else {
    // The request failed.
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0));
  }
}

bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size,
                                      int* bytes_read) {
  if (!data_.get()) {
    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
    DCHECK(!pending_buf_.get());
    pending_buf_ = buf;
    pending_buf_size_ = buf_size;
    return false;  // Tell the caller we're still waiting for data.
  }

  // Otherwise, the data is available.
  CompleteRead(buf, buf_size, bytes_read);
  return true;
}

void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size,
                                       int* bytes_read) {
  int remaining = static_cast<int>(data_->data.size()) - data_offset_;
  if (buf_size > remaining)
    buf_size = remaining;
  if (buf_size > 0) {
    memcpy(buf->data(), &data_->data[0] + data_offset_, buf_size);
    data_offset_ += buf_size;
  }
  *bytes_read = buf_size;
}

void URLRequestChromeJob::StartAsync() {
  if (!request_)
    return;

  if (chrome_url_data_manager.StartRequest(request_->url(), this)) {
    NotifyHeadersComplete();
  } else {
    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
                                      net::ERR_INVALID_URL));
  }
}

URLRequestChromeFileJob::URLRequestChromeFileJob(URLRequest* request,
                                                 const FilePath& path)
    : URLRequestFileJob(request, path) {
}

URLRequestChromeFileJob::~URLRequestChromeFileJob() { }

<commit_msg>Fix a browser crash when the URLRequestChromeJob goes away from the NotifyReadComplete notification.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/dom_ui/chrome_url_data_manager.h"

#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/ref_counted_util.h"
#include "googleurl/src/url_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_job.h"
#ifdef CHROME_PERSONALIZATION
// TODO(timsteele): Remove all CHROME_PERSONALIZATION code in this file.
// It is only temporarily needed to configure some personalization data sources
// that will go away soon.
#include "chrome/personalization/personalization.h"
#endif

// The URL scheme used for internal chrome resources.
// TODO(glen): Choose a better location for this.
static const char kChromeURLScheme[] = "chrome-ui";

// The single global instance of ChromeURLDataManager.
ChromeURLDataManager chrome_url_data_manager;

// URLRequestChromeJob is a URLRequestJob that manages running chrome-internal
// resource requests asynchronously.
// It hands off URL requests to ChromeURLDataManager, which asynchronously
// calls back once the data is available.
class URLRequestChromeJob : public URLRequestJob {
 public:
  explicit URLRequestChromeJob(URLRequest* request);
  virtual ~URLRequestChromeJob();

  // URLRequestJob implementation.
  virtual void Start();
  virtual void Kill();
  virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
  virtual bool GetMimeType(std::string* mime_type);

  // Called by ChromeURLDataManager to notify us that the data blob is ready
  // for us.
  void DataAvailable(RefCountedBytes* bytes);

  void SetMimeType(const std::string& mime_type) {
    mime_type_ = mime_type;
  }

 private:
  // Helper for Start(), to let us start asynchronously.
  // (This pattern is shared by most URLRequestJob implementations.)
  void StartAsync();

  // Do the actual copy from data_ (the data we're serving) into |buf|.
  // Separate from ReadRawData so we can handle async I/O.
  void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read);

  // The actual data we're serving.  NULL until it's been fetched.
  scoped_refptr<RefCountedBytes> data_;
  // The current offset into the data that we're handing off to our
  // callers via the Read interfaces.
  int data_offset_;

  // For async reads, we keep around a pointer to the buffer that
  // we're reading into.
  scoped_refptr<net::IOBuffer> pending_buf_;
  int pending_buf_size_;
  std::string mime_type_;

  DISALLOW_EVIL_CONSTRUCTORS(URLRequestChromeJob);
};

// URLRequestChromeFileJob is a URLRequestJob that acts like a file:// URL
class URLRequestChromeFileJob : public URLRequestFileJob {
 public:
  URLRequestChromeFileJob(URLRequest* request, const FilePath& path);
  virtual ~URLRequestChromeFileJob();

 private:
  DISALLOW_EVIL_CONSTRUCTORS(URLRequestChromeFileJob);
};

void RegisterURLRequestChromeJob() {
  // Being a standard scheme allows us to resolve relative paths. This method
  // is invoked multiple times during testing, so only add the scheme once.
  url_parse::Component url_scheme_component(0, arraysize(kChromeURLScheme) - 1);
  if (!url_util::IsStandard(kChromeURLScheme, arraysize(kChromeURLScheme) - 1,
                            url_scheme_component)) {
    url_util::AddStandardScheme(kChromeURLScheme);
  }

  std::wstring inspector_dir;
  if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
    chrome_url_data_manager.AddFileSource("inspector", inspector_dir);

  URLRequest::RegisterProtocolFactory(kChromeURLScheme,
                                      &ChromeURLDataManager::Factory);
#ifdef CHROME_PERSONALIZATION
  url_util::AddStandardScheme(kPersonalizationScheme);
  URLRequest::RegisterProtocolFactory(kPersonalizationScheme,
                                      &ChromeURLDataManager::Factory);
#endif
}

void UnregisterURLRequestChromeJob() {
  std::wstring inspector_dir;
  if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
    chrome_url_data_manager.RemoveFileSource("inspector");
}

// static
void ChromeURLDataManager::URLToRequest(const GURL& url,
                                        std::string* source_name,
                                        std::string* path) {
#ifdef CHROME_PERSONALIZATION
  DCHECK(url.SchemeIs(kChromeURLScheme) ||
         url.SchemeIs(kPersonalizationScheme));
#else
  DCHECK(url.SchemeIs(kChromeURLScheme));
#endif

  if (!url.is_valid()) {
    NOTREACHED();
    return;
  }

  // Our input looks like: chrome-ui://source_name/extra_bits?foo .
  // So the url's "host" is our source, and everything after the host is
  // the path.
  source_name->assign(url.host());

  const std::string& spec = url.possibly_invalid_spec();
  const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
  int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
  ++offset;  // Skip the slash at the beginning of the path.
  if (offset < static_cast<int>(spec.size()))
    path->assign(spec.substr(offset));
}

// static
bool ChromeURLDataManager::URLToFilePath(const GURL& url,
                                         std::wstring* file_path) {
  // Parse the URL into a request for a source and path.
  std::string source_name;
  std::string relative_path;
  URLToRequest(url, &source_name, &relative_path);

  FileSourceMap::const_iterator i(
      chrome_url_data_manager.file_sources_.find(source_name));
  if (i == chrome_url_data_manager.file_sources_.end())
    return false;

  file_path->assign(i->second);
  file_util::AppendToPath(file_path, UTF8ToWide(relative_path));
  return true;
}

ChromeURLDataManager::ChromeURLDataManager() : next_request_id_(0) { }

ChromeURLDataManager::~ChromeURLDataManager() { }

void ChromeURLDataManager::AddDataSource(scoped_refptr<DataSource> source) {
  // TODO(jackson): A new data source with same name should not clobber the
  // existing one.
  data_sources_[source->source_name()] = source;
}

void ChromeURLDataManager::AddFileSource(const std::string& source_name,
                                         const std::wstring& file_path) {
  DCHECK(file_sources_.count(source_name) == 0);
  file_sources_[source_name] = file_path;
}

void ChromeURLDataManager::RemoveFileSource(const std::string& source_name) {
  DCHECK(file_sources_.count(source_name) == 1);
  file_sources_.erase(source_name);
}

bool ChromeURLDataManager::StartRequest(const GURL& url,
                                        URLRequestChromeJob* job) {
  // Parse the URL into a request for a source and path.
  std::string source_name;
  std::string path;
  URLToRequest(url, &source_name, &path);

  // Look up the data source for the request.
  DataSourceMap::iterator i = data_sources_.find(source_name);
  if (i == data_sources_.end())
    return false;
  DataSource* source = i->second;

  // Save this request so we know where to send the data.
  RequestID request_id = next_request_id_++;
  pending_requests_.insert(std::make_pair(request_id, job));

  // TODO(eroman): would be nicer if the mimetype were set at the same time
  // as the data blob. For now do it here, since NotifyHeadersComplete() is
  // going to get called once we return.
  job->SetMimeType(source->GetMimeType(path));

  // Forward along the request to the data source.
  source->message_loop()->PostTask(FROM_HERE,
      NewRunnableMethod(source, &DataSource::StartDataRequest,
                        path, request_id));
  return true;
}

void ChromeURLDataManager::RemoveRequest(URLRequestChromeJob* job) {
  // Remove the request from our list of pending requests.
  // If/when the source sends the data that was requested, the data will just
  // be thrown away.
  for (PendingRequestMap::iterator i = pending_requests_.begin();
       i != pending_requests_.end(); ++i) {
    if (i->second == job) {
      pending_requests_.erase(i);
      return;
    }
  }
}

void ChromeURLDataManager::DataAvailable(
    RequestID request_id,
    scoped_refptr<RefCountedBytes> bytes) {
  // Forward this data on to the pending URLRequest, if it exists.
  PendingRequestMap::iterator i = pending_requests_.find(request_id);
  if (i != pending_requests_.end()) {
    // We acquire a reference to the job so that it doesn't disappear under the
    // feet of any method invoked here (we could trigger a callback).
    scoped_refptr<URLRequestChromeJob> job = i->second;
    pending_requests_.erase(i);
    job->DataAvailable(bytes);
  }
}

void ChromeURLDataManager::DataSource::SendResponse(
    RequestID request_id,
    RefCountedBytes* bytes) {
  g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
      NewRunnableMethod(&chrome_url_data_manager,
                        &ChromeURLDataManager::DataAvailable,
                        request_id, scoped_refptr<RefCountedBytes>(bytes)));
}

// static
URLRequestJob* ChromeURLDataManager::Factory(URLRequest* request,
                                             const std::string& scheme) {
  // Try first with a file handler
  std::wstring path;
  if (ChromeURLDataManager::URLToFilePath(request->url(), &path))
    return new URLRequestChromeFileJob(request,
                                       FilePath::FromWStringHack(path));

  // Fall back to using a custom handler
  return new URLRequestChromeJob(request);
}

URLRequestChromeJob::URLRequestChromeJob(URLRequest* request)
    : URLRequestJob(request), data_offset_(0) {}

URLRequestChromeJob::~URLRequestChromeJob() {
}

void URLRequestChromeJob::Start() {
  // Start reading asynchronously so that all error reporting and data
  // callbacks happen as they would for network requests.
  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
      this, &URLRequestChromeJob::StartAsync));
}

void URLRequestChromeJob::Kill() {
  chrome_url_data_manager.RemoveRequest(this);
}

bool URLRequestChromeJob::GetMimeType(std::string* mime_type) {
  *mime_type = mime_type_;
  return !mime_type_.empty();
}

void URLRequestChromeJob::DataAvailable(RefCountedBytes* bytes) {
  if (bytes) {
    // The request completed, and we have all the data.
    // Clear any IO pending status.
    SetStatus(URLRequestStatus());

    data_ = bytes;
    int bytes_read;
    if (pending_buf_.get()) {
      CompleteRead(pending_buf_, pending_buf_size_, &bytes_read);
      pending_buf_ = NULL;
      NotifyReadComplete(bytes_read);
    }
  } else {
    // The request failed.
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0));
  }
}

bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size,
                                      int* bytes_read) {
  if (!data_.get()) {
    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
    DCHECK(!pending_buf_.get());
    pending_buf_ = buf;
    pending_buf_size_ = buf_size;
    return false;  // Tell the caller we're still waiting for data.
  }

  // Otherwise, the data is available.
  CompleteRead(buf, buf_size, bytes_read);
  return true;
}

void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size,
                                       int* bytes_read) {
  int remaining = static_cast<int>(data_->data.size()) - data_offset_;
  if (buf_size > remaining)
    buf_size = remaining;
  if (buf_size > 0) {
    memcpy(buf->data(), &data_->data[0] + data_offset_, buf_size);
    data_offset_ += buf_size;
  }
  *bytes_read = buf_size;
}

void URLRequestChromeJob::StartAsync() {
  if (!request_)
    return;

  if (chrome_url_data_manager.StartRequest(request_->url(), this)) {
    NotifyHeadersComplete();
  } else {
    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
                                      net::ERR_INVALID_URL));
  }
}

URLRequestChromeFileJob::URLRequestChromeFileJob(URLRequest* request,
                                                 const FilePath& path)
    : URLRequestFileJob(request, path) {
}

URLRequestChromeFileJob::~URLRequestChromeFileJob() { }

<|endoftext|>