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

#include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/experimental_bluetooth.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_CHROMEOS)
#include "base/memory/ref_counted.h"
#include "base/safe_strerror_posix.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/chromeos/bluetooth/bluetooth_adapter.h"
#include "chrome/browser/chromeos/bluetooth/bluetooth_device.h"
#include "chrome/browser/chromeos/bluetooth/bluetooth_socket.h"
#include "chrome/browser/chromeos/extensions/bluetooth_event_router.h"

#include <errno.h>

using chromeos::BluetoothAdapter;
using chromeos::BluetoothDevice;

namespace {

chromeos::ExtensionBluetoothEventRouter* GetEventRouter(Profile* profile) {
  return profile->GetExtensionService()->bluetooth_event_router();
}

const chromeos::BluetoothAdapter* GetAdapter(Profile* profile) {
  return GetEventRouter(profile)->adapter();
}

chromeos::BluetoothAdapter* GetMutableAdapter(Profile* profile) {
  return GetEventRouter(profile)->GetMutableAdapter();
}

}  // namespace
#endif

namespace {

const char kSocketNotFoundError[] = "Socket not found: invalid socket id";

}  // namespace

namespace Connect = extensions::api::experimental_bluetooth::Connect;
namespace Disconnect = extensions::api::experimental_bluetooth::Disconnect;
namespace GetDevicesWithServiceName =
    extensions::api::experimental_bluetooth::GetDevicesWithServiceName;
namespace GetDevicesWithServiceUUID =
    extensions::api::experimental_bluetooth::GetDevicesWithServiceUUID;
namespace Read = extensions::api::experimental_bluetooth::Read;
namespace Write = extensions::api::experimental_bluetooth::Write;

namespace extensions {
namespace api {

#if defined(OS_CHROMEOS)

bool BluetoothIsAvailableFunction::RunImpl() {
  result_.reset(Value::CreateBooleanValue(GetAdapter(profile())->IsPresent()));
  return true;
}

bool BluetoothIsPoweredFunction::RunImpl() {
  result_.reset(Value::CreateBooleanValue(GetAdapter(profile())->IsPowered()));
  return true;
}

bool BluetoothGetAddressFunction::RunImpl() {
  result_.reset(Value::CreateStringValue(GetAdapter(profile())->address()));
  return true;
}

bool BluetoothGetDevicesWithServiceUUIDFunction::RunImpl() {
  scoped_ptr<GetDevicesWithServiceUUID::Params> params(
      GetDevicesWithServiceUUID::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  const BluetoothAdapter::ConstDeviceList& devices =
      GetAdapter(profile())->GetDevices();
  ListValue* matches = new ListValue;
  for (BluetoothAdapter::ConstDeviceList::const_iterator i =
      devices.begin(); i != devices.end(); ++i) {
    if ((*i)->ProvidesServiceWithUUID(params->uuid)) {
      experimental_bluetooth::Device device;
      device.name = UTF16ToUTF8((*i)->GetName());
      device.address = (*i)->address();
      matches->Append(device.ToValue().release());
    }
  }
  result_.reset(matches);

  return true;
}

BluetoothGetDevicesWithServiceNameFunction::
    BluetoothGetDevicesWithServiceNameFunction() : callbacks_pending_(0) {}

void BluetoothGetDevicesWithServiceNameFunction::AddDeviceIfTrue(
    ListValue* list, const BluetoothDevice* device, bool result) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  if (result) {
    experimental_bluetooth::Device device_result;
    device_result.name = UTF16ToUTF8(device->GetName());
    device_result.address = device->address();
    list->Append(device_result.ToValue().release());
  }

  callbacks_pending_--;
  if (callbacks_pending_ == 0) {
    SendResponse(true);
    Release();  // Added in RunImpl
  }
}

bool BluetoothGetDevicesWithServiceNameFunction::RunImpl() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  ListValue* matches = new ListValue;
  result_.reset(matches);

  BluetoothAdapter::DeviceList devices =
      GetMutableAdapter(profile())->GetDevices();
  if (devices.empty()) {
    SendResponse(true);
    return true;
  }

  callbacks_pending_ = devices.size();
  AddRef();  // Released in AddDeviceIfTrue when callbacks_pending_ == 0

  scoped_ptr<GetDevicesWithServiceName::Params> params(
      GetDevicesWithServiceName::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  for (BluetoothAdapter::DeviceList::iterator i = devices.begin();
      i != devices.end(); ++i) {
    (*i)->ProvidesServiceWithName(params->name,
        base::Bind(&BluetoothGetDevicesWithServiceNameFunction::AddDeviceIfTrue,
                   this,
                   matches,
                   *i));
  }

  return true;
}

void BluetoothConnectFunction::ConnectToServiceCallback(
    const chromeos::BluetoothDevice* device,
    const std::string& service_uuid,
    scoped_refptr<chromeos::BluetoothSocket> socket) {
  if (socket.get()) {
    int socket_id = GetEventRouter(profile())->RegisterSocket(socket);

    experimental_bluetooth::Socket result_socket;
    result_socket.device.address = device->address();
    result_socket.device.name = UTF16ToUTF8(device->GetName());
    result_socket.service_uuid = service_uuid;
    result_socket.id = socket_id;
    result_.reset(result_socket.ToValue().release());
    SendResponse(true);
  } else {
    SendResponse(false);
  }

  Release();  // Added in RunImpl
}

bool BluetoothConnectFunction::RunImpl() {
  scoped_ptr<Connect::Params> params(Connect::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  chromeos::BluetoothDevice* device =
      GetMutableAdapter(profile())->GetDevice(params->device.address);
  if (!device) {
    SendResponse(false);
    return false;
  }

  AddRef();
  device->ConnectToService(params->service,
      base::Bind(&BluetoothConnectFunction::ConnectToServiceCallback,
                 this,
                 device,
                 params->service));
  return true;
}

bool BluetoothDisconnectFunction::RunImpl() {
  scoped_ptr<Disconnect::Params> params(Disconnect::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  return GetEventRouter(profile())->ReleaseSocket(params->socket.id);
}

bool BluetoothReadFunction::Prepare() {
  scoped_ptr<Read::Params> params(Read::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  socket_ = GetEventRouter(profile())->GetSocket(params->socket.id);
  if (socket_.get() == NULL) {
    SetError(kSocketNotFoundError);
    return false;
  }

  success_ = false;
  return true;
}

void BluetoothReadFunction::Work() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  CHECK(socket_.get() != NULL);

  char* all_bytes = NULL;
  ssize_t buffer_size = 0;
  ssize_t total_bytes_read = 0;
  int errsv;
  while (true) {
    buffer_size += 1024;
    all_bytes = static_cast<char*>(realloc(all_bytes, buffer_size));
    CHECK(all_bytes) << "Failed to grow Bluetooth socket buffer";

    // bluetooth sockets are non-blocking, so read until we hit an error
    ssize_t bytes_read = read(socket_->fd(), all_bytes + total_bytes_read,
        buffer_size - total_bytes_read);
    errsv = errno;
    if (bytes_read <= 0)
      break;

    total_bytes_read += bytes_read;
  }

  if (total_bytes_read > 0) {
    success_ = true;
    result_.reset(base::BinaryValue::Create(all_bytes, total_bytes_read));
  } else {
    success_ = (errsv == EAGAIN || errsv == EWOULDBLOCK);
    free(all_bytes);
  }

  if (!success_)
    SetError(safe_strerror(errsv));
}

bool BluetoothReadFunction::Respond() {
  return success_;
}

bool BluetoothWriteFunction::Prepare() {
  // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
  // support is added
  DictionaryValue* socket;
  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &socket));
  int socket_id;
  EXTENSION_FUNCTION_VALIDATE(socket->GetInteger("id", &socket_id));

  socket_ = GetEventRouter(profile())->GetSocket(socket_id);
  if (socket_.get() == NULL) {
    SetError(kSocketNotFoundError);
    return false;
  }

  base::BinaryValue* tmp_data;
  EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &tmp_data));
  data_to_write_ = tmp_data;

  success_ = false;
  return socket_.get() != NULL;
}

void BluetoothWriteFunction::Work() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

  if (socket_.get() == NULL)
    return;

  ssize_t bytes_written = write(socket_->fd(),
      data_to_write_->GetBuffer(), data_to_write_->GetSize());
  int errsv = errno;

  if (bytes_written > 0) {
    result_.reset(Value::CreateIntegerValue(bytes_written));
    success_ = true;
  } else {
    result_.reset(0);
    success_ = (errsv == EAGAIN || errsv == EWOULDBLOCK);
  }

  if (!success_)
    SetError(safe_strerror(errsv));
}

bool BluetoothWriteFunction::Respond() {
  return success_;
}

#else

// -----------------------------------------------------------------------------
// NIY stubs
// -----------------------------------------------------------------------------
bool BluetoothIsAvailableFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothIsPoweredFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetAddressFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetDevicesWithServiceUUIDFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetDevicesWithServiceNameFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothConnectFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothDisconnectFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothReadFunction::Prepare() {
  return true;
}

void BluetoothReadFunction::Work() {
}

bool BluetoothReadFunction::Respond() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothWriteFunction::Prepare() {
  return true;
}

void BluetoothWriteFunction::Work() {
}

bool BluetoothWriteFunction::Respond() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

#endif

BluetoothReadFunction::BluetoothReadFunction() {}
BluetoothReadFunction::~BluetoothReadFunction() {}

BluetoothWriteFunction::BluetoothWriteFunction() {}
BluetoothWriteFunction::~BluetoothWriteFunction() {}

bool BluetoothSetOutOfBandPairingDataFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetOutOfBandPairingDataFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

}  // namespace api
}  // namespace extensions
<commit_msg>Improve errors for the bluetooth.connect API<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/experimental_bluetooth.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_CHROMEOS)
#include "base/memory/ref_counted.h"
#include "base/safe_strerror_posix.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/chromeos/bluetooth/bluetooth_adapter.h"
#include "chrome/browser/chromeos/bluetooth/bluetooth_device.h"
#include "chrome/browser/chromeos/bluetooth/bluetooth_socket.h"
#include "chrome/browser/chromeos/extensions/bluetooth_event_router.h"

#include <errno.h>

using chromeos::BluetoothAdapter;
using chromeos::BluetoothDevice;

namespace {

chromeos::ExtensionBluetoothEventRouter* GetEventRouter(Profile* profile) {
  return profile->GetExtensionService()->bluetooth_event_router();
}

const chromeos::BluetoothAdapter* GetAdapter(Profile* profile) {
  return GetEventRouter(profile)->adapter();
}

chromeos::BluetoothAdapter* GetMutableAdapter(Profile* profile) {
  return GetEventRouter(profile)->GetMutableAdapter();
}

}  // namespace
#endif

namespace {

const char kFailedToConnect[] = "Connection failed";
const char kInvalidDevice[] = "Invalid device";
const char kSocketNotFoundError[] = "Socket not found: invalid socket id";

}  // namespace

namespace Connect = extensions::api::experimental_bluetooth::Connect;
namespace Disconnect = extensions::api::experimental_bluetooth::Disconnect;
namespace GetDevicesWithServiceName =
    extensions::api::experimental_bluetooth::GetDevicesWithServiceName;
namespace GetDevicesWithServiceUUID =
    extensions::api::experimental_bluetooth::GetDevicesWithServiceUUID;
namespace Read = extensions::api::experimental_bluetooth::Read;
namespace Write = extensions::api::experimental_bluetooth::Write;

namespace extensions {
namespace api {

#if defined(OS_CHROMEOS)

bool BluetoothIsAvailableFunction::RunImpl() {
  result_.reset(Value::CreateBooleanValue(GetAdapter(profile())->IsPresent()));
  return true;
}

bool BluetoothIsPoweredFunction::RunImpl() {
  result_.reset(Value::CreateBooleanValue(GetAdapter(profile())->IsPowered()));
  return true;
}

bool BluetoothGetAddressFunction::RunImpl() {
  result_.reset(Value::CreateStringValue(GetAdapter(profile())->address()));
  return true;
}

bool BluetoothGetDevicesWithServiceUUIDFunction::RunImpl() {
  scoped_ptr<GetDevicesWithServiceUUID::Params> params(
      GetDevicesWithServiceUUID::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  const BluetoothAdapter::ConstDeviceList& devices =
      GetAdapter(profile())->GetDevices();
  ListValue* matches = new ListValue;
  for (BluetoothAdapter::ConstDeviceList::const_iterator i =
      devices.begin(); i != devices.end(); ++i) {
    if ((*i)->ProvidesServiceWithUUID(params->uuid)) {
      experimental_bluetooth::Device device;
      device.name = UTF16ToUTF8((*i)->GetName());
      device.address = (*i)->address();
      matches->Append(device.ToValue().release());
    }
  }
  result_.reset(matches);

  return true;
}

BluetoothGetDevicesWithServiceNameFunction::
    BluetoothGetDevicesWithServiceNameFunction() : callbacks_pending_(0) {}

void BluetoothGetDevicesWithServiceNameFunction::AddDeviceIfTrue(
    ListValue* list, const BluetoothDevice* device, bool result) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  if (result) {
    experimental_bluetooth::Device device_result;
    device_result.name = UTF16ToUTF8(device->GetName());
    device_result.address = device->address();
    list->Append(device_result.ToValue().release());
  }

  callbacks_pending_--;
  if (callbacks_pending_ == 0) {
    SendResponse(true);
    Release();  // Added in RunImpl
  }
}

bool BluetoothGetDevicesWithServiceNameFunction::RunImpl() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  ListValue* matches = new ListValue;
  result_.reset(matches);

  BluetoothAdapter::DeviceList devices =
      GetMutableAdapter(profile())->GetDevices();
  if (devices.empty()) {
    SendResponse(true);
    return true;
  }

  callbacks_pending_ = devices.size();
  AddRef();  // Released in AddDeviceIfTrue when callbacks_pending_ == 0

  scoped_ptr<GetDevicesWithServiceName::Params> params(
      GetDevicesWithServiceName::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  for (BluetoothAdapter::DeviceList::iterator i = devices.begin();
      i != devices.end(); ++i) {
    (*i)->ProvidesServiceWithName(params->name,
        base::Bind(&BluetoothGetDevicesWithServiceNameFunction::AddDeviceIfTrue,
                   this,
                   matches,
                   *i));
  }

  return true;
}

void BluetoothConnectFunction::ConnectToServiceCallback(
    const chromeos::BluetoothDevice* device,
    const std::string& service_uuid,
    scoped_refptr<chromeos::BluetoothSocket> socket) {
  if (socket.get()) {
    int socket_id = GetEventRouter(profile())->RegisterSocket(socket);

    experimental_bluetooth::Socket result_socket;
    result_socket.device.address = device->address();
    result_socket.device.name = UTF16ToUTF8(device->GetName());
    result_socket.service_uuid = service_uuid;
    result_socket.id = socket_id;
    result_.reset(result_socket.ToValue().release());
    SendResponse(true);
  } else {
    SetError(kFailedToConnect);
    SendResponse(false);
  }

  Release();  // Added in RunImpl
}

bool BluetoothConnectFunction::RunImpl() {
  scoped_ptr<Connect::Params> params(Connect::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  chromeos::BluetoothDevice* device =
      GetMutableAdapter(profile())->GetDevice(params->device.address);
  if (!device) {
    SendResponse(false);
    SetError(kInvalidDevice);
    return false;
  }

  AddRef();
  device->ConnectToService(params->service,
      base::Bind(&BluetoothConnectFunction::ConnectToServiceCallback,
                 this,
                 device,
                 params->service));
  return true;
}

bool BluetoothDisconnectFunction::RunImpl() {
  scoped_ptr<Disconnect::Params> params(Disconnect::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  return GetEventRouter(profile())->ReleaseSocket(params->socket.id);
}

bool BluetoothReadFunction::Prepare() {
  scoped_ptr<Read::Params> params(Read::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  socket_ = GetEventRouter(profile())->GetSocket(params->socket.id);
  if (socket_.get() == NULL) {
    SetError(kSocketNotFoundError);
    return false;
  }

  success_ = false;
  return true;
}

void BluetoothReadFunction::Work() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  CHECK(socket_.get() != NULL);

  char* all_bytes = NULL;
  ssize_t buffer_size = 0;
  ssize_t total_bytes_read = 0;
  int errsv;
  while (true) {
    buffer_size += 1024;
    all_bytes = static_cast<char*>(realloc(all_bytes, buffer_size));
    CHECK(all_bytes) << "Failed to grow Bluetooth socket buffer";

    // bluetooth sockets are non-blocking, so read until we hit an error
    ssize_t bytes_read = read(socket_->fd(), all_bytes + total_bytes_read,
        buffer_size - total_bytes_read);
    errsv = errno;
    if (bytes_read <= 0)
      break;

    total_bytes_read += bytes_read;
  }

  if (total_bytes_read > 0) {
    success_ = true;
    result_.reset(base::BinaryValue::Create(all_bytes, total_bytes_read));
  } else {
    success_ = (errsv == EAGAIN || errsv == EWOULDBLOCK);
    free(all_bytes);
  }

  if (!success_)
    SetError(safe_strerror(errsv));
}

bool BluetoothReadFunction::Respond() {
  return success_;
}

bool BluetoothWriteFunction::Prepare() {
  // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
  // support is added
  DictionaryValue* socket;
  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &socket));
  int socket_id;
  EXTENSION_FUNCTION_VALIDATE(socket->GetInteger("id", &socket_id));

  socket_ = GetEventRouter(profile())->GetSocket(socket_id);
  if (socket_.get() == NULL) {
    SetError(kSocketNotFoundError);
    return false;
  }

  base::BinaryValue* tmp_data;
  EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &tmp_data));
  data_to_write_ = tmp_data;

  success_ = false;
  return socket_.get() != NULL;
}

void BluetoothWriteFunction::Work() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

  if (socket_.get() == NULL)
    return;

  ssize_t bytes_written = write(socket_->fd(),
      data_to_write_->GetBuffer(), data_to_write_->GetSize());
  int errsv = errno;

  if (bytes_written > 0) {
    result_.reset(Value::CreateIntegerValue(bytes_written));
    success_ = true;
  } else {
    result_.reset(0);
    success_ = (errsv == EAGAIN || errsv == EWOULDBLOCK);
  }

  if (!success_)
    SetError(safe_strerror(errsv));
}

bool BluetoothWriteFunction::Respond() {
  return success_;
}

#else

// -----------------------------------------------------------------------------
// NIY stubs
// -----------------------------------------------------------------------------
bool BluetoothIsAvailableFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothIsPoweredFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetAddressFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetDevicesWithServiceUUIDFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetDevicesWithServiceNameFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothConnectFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothDisconnectFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothReadFunction::Prepare() {
  return true;
}

void BluetoothReadFunction::Work() {
}

bool BluetoothReadFunction::Respond() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothWriteFunction::Prepare() {
  return true;
}

void BluetoothWriteFunction::Work() {
}

bool BluetoothWriteFunction::Respond() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

#endif

BluetoothReadFunction::BluetoothReadFunction() {}
BluetoothReadFunction::~BluetoothReadFunction() {}

BluetoothWriteFunction::BluetoothWriteFunction() {}
BluetoothWriteFunction::~BluetoothWriteFunction() {}

bool BluetoothSetOutOfBandPairingDataFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

bool BluetoothGetOutOfBandPairingDataFunction::RunImpl() {
  NOTREACHED() << "Not implemented yet";
  return false;
}

}  // namespace api
}  // namespace extensions
<|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/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/mock_host_resolver.h"

IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoNoScript) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("incognito").AppendASCII("content_scripts")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));
  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script didn't run.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'Unmodified')",
      &result));
  EXPECT_TRUE(result);
}

IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoYesScript) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  // Load a dummy extension. This just tests that we don't regress a
  // crash fix when multiple incognito- and non-incognito-enabled extensions
  // are mixed.
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("content_scripts").AppendASCII("all_frames")));

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("incognito").AppendASCII("content_scripts")));

  // Dummy extension #2.
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("content_scripts").AppendASCII("isolated_world1")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));
  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script ran.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'modified')",
      &result));
  EXPECT_TRUE(result);
}

// Tests that an extension which is enabled for incognito mode doesn't
// accidentially create and incognito profile.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DontCreateIncognitoProfile) {
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
  ASSERT_TRUE(
      RunExtensionTestIncognito("incognito/enumerate_tabs")) << message_;
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
}

// Tests that the APIs in an incognito-enabled extension work properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Incognito) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Tests that the APIs in an incognito-enabled split-mode extension work
// properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoSplitMode) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  // We need 2 ResultCatchers because we'll be running the same test in both
  // regular and incognito mode.
  ResultCatcher catcher;
  catcher.RestrictToProfile(browser()->profile());
  ResultCatcher catcher_incognito;
  catcher_incognito.RestrictToProfile(
      browser()->profile()->GetOffTheRecordProfile());

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("split")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
  EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
}

// Tests that the APIs in an incognito-disabled extension don't see incognito
// events or callbacks.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoDisabled) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtension(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis_disabled")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Test that opening a popup from an incognito browser window works properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoPopup) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  ResultCatcher catcher;

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("popup")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));
  Browser* incognito_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);

  // Simulate the incognito's browser action being clicked.
  BrowserActionTestUtil(incognito_browser).Press(0);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
<commit_msg>Mark ExtensionApiTest.IncognitoSplitMode flaky on Linux.<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/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/mock_host_resolver.h"

IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoNoScript) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("incognito").AppendASCII("content_scripts")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));
  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script didn't run.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'Unmodified')",
      &result));
  EXPECT_TRUE(result);
}

IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoYesScript) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  // Load a dummy extension. This just tests that we don't regress a
  // crash fix when multiple incognito- and non-incognito-enabled extensions
  // are mixed.
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("content_scripts").AppendASCII("all_frames")));

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("incognito").AppendASCII("content_scripts")));

  // Dummy extension #2.
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
      .AppendASCII("content_scripts").AppendASCII("isolated_world1")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));
  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script ran.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'modified')",
      &result));
  EXPECT_TRUE(result);
}

// Tests that an extension which is enabled for incognito mode doesn't
// accidentially create and incognito profile.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DontCreateIncognitoProfile) {
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
  ASSERT_TRUE(
      RunExtensionTestIncognito("incognito/enumerate_tabs")) << message_;
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
}

// Tests that the APIs in an incognito-enabled extension work properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Incognito) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Crashes flakily on Linux.  http://crbug.com/58270
#if defined(OS_LINUX)
#define MAYBE_IncognitoSplitMode FLAKY_IncognitoSplitMode
#else
#define MAYBE_IncognitoSplitMode IncognitoSplitMode
#endif

// Tests that the APIs in an incognito-enabled split-mode extension work
// properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_IncognitoSplitMode) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  // We need 2 ResultCatchers because we'll be running the same test in both
  // regular and incognito mode.
  ResultCatcher catcher;
  catcher.RestrictToProfile(browser()->profile());
  ResultCatcher catcher_incognito;
  catcher_incognito.RestrictToProfile(
      browser()->profile()->GetOffTheRecordProfile());

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("split")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
  EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
}

// Tests that the APIs in an incognito-disabled extension don't see incognito
// events or callbacks.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoDisabled) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtension(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis_disabled")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Test that opening a popup from an incognito browser window works properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoPopup) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(test_server()->Start());

  ResultCatcher catcher;

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("popup")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
      GURL("http://www.example.com:1337/files/extensions/test_file.html"));
  Browser* incognito_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);

  // Simulate the incognito's browser action being clicked.
  BrowserActionTestUtil(incognito_browser).Press(0);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
<|endoftext|>


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

#include "chrome/browser/ui/views/extensions/shell_window_views.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/common/extensions/extension.h"
#include "ui/views/widget/widget.h"

ShellWindowViews::ShellWindowViews(ExtensionHost* host)
    : ShellWindow(host) {
  host_->view()->SetContainer(this);
  window_ = new views::Widget;
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
  params.delegate = this;
  gfx::Rect bounds(0, 0, 512, 384);
  params.bounds = bounds;
  window_->Init(params);
  window_->Show();
}

ShellWindowViews::~ShellWindowViews() {
}

void ShellWindowViews::Close() {
  window_->Close();
}

void ShellWindowViews::DeleteDelegate() {
  delete this;
}

bool ShellWindowViews::CanResize() const {
  return true;
}

views::View* ShellWindowViews::GetContentsView() {
  return host_->view();
}

string16 ShellWindowViews::GetWindowTitle() const {
  return UTF8ToUTF16(host_->extension()->name());
}

views::Widget* ShellWindowViews::GetWidget() {
  return window_;
}

const views::Widget* ShellWindowViews::GetWidget() const {
  return window_;
}

// static
ShellWindow* ShellWindow::CreateShellWindow(ExtensionHost* host) {
  return new ShellWindowViews(host);
}
<commit_msg>Set windows AppId (for taskbar) for platform apps.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/extensions/shell_window_views.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/common/extensions/extension.h"
#include "ui/views/widget/widget.h"

#if defined(OS_WIN)
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/web_applications/web_app.h"
#include "ui/base/win/shell.h"
#endif // OS_WIN

ShellWindowViews::ShellWindowViews(ExtensionHost* host)
    : ShellWindow(host) {
  host_->view()->SetContainer(this);
  window_ = new views::Widget;
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
  params.delegate = this;
  gfx::Rect bounds(0, 0, 512, 384);
  params.bounds = bounds;
  window_->Init(params);
#if defined(OS_WIN)
  std::string app_name = web_app::GenerateApplicationNameFromExtensionId(
      host_->extension()->id());
  ui::win::SetAppIdForWindow(
      ShellIntegration::GetAppId(UTF8ToWide(app_name),
      host_->profile()->GetPath()),
      GetWidget()->GetTopLevelWidget()->GetNativeWindow());
#endif // OS_WIN
  window_->Show();
}

ShellWindowViews::~ShellWindowViews() {
}

void ShellWindowViews::Close() {
  window_->Close();
}

void ShellWindowViews::DeleteDelegate() {
  delete this;
}

bool ShellWindowViews::CanResize() const {
  return true;
}

views::View* ShellWindowViews::GetContentsView() {
  return host_->view();
}

string16 ShellWindowViews::GetWindowTitle() const {
  return UTF8ToUTF16(host_->extension()->name());
}

views::Widget* ShellWindowViews::GetWidget() {
  return window_;
}

const views::Widget* ShellWindowViews::GetWidget() const {
  return window_;
}

// static
ShellWindow* ShellWindow::CreateShellWindow(ExtensionHost* host) {
  return new ShellWindowViews(host);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: binaryreader.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef CONFIGMGR_BINARYREADER_HXX
#define CONFIGMGR_BINARYREADER_HXX

#include <rtl/ustring.hxx>
#include <osl/file.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/io/XDataInputStream.hpp>

namespace configmgr
{
    // -----------------------------------------------------------------------------
    namespace backend
    {
        namespace css = com::sun::star;

        namespace io   = css::io;
        namespace uno  = css::uno;
        namespace lang = css::lang;

        typedef uno::Reference<lang::XMultiServiceFactory> MultiServiceFactory;
        // -----------------------------------------------------------------------------
        class BinaryReader
        {
            rtl::OUString m_sFileURL;

            uno::Reference<io::XDataInputStream> m_xDataInputStream;
        public:
            explicit BinaryReader (rtl::OUString const & _sFileURL)
            : m_sFileURL(_sFileURL)
            {}

            ~BinaryReader()
            {}

        public:
            bool open()     SAL_THROW( (io::IOException, uno::RuntimeException) );
            void reopen()   SAL_THROW( (io::IOException, uno::RuntimeException) );
            void close()    SAL_THROW( (io::IOException, uno::RuntimeException) );

            typedef uno::Sequence< sal_Int8 >       Binary;
            typedef uno::Sequence< rtl::OUString >  StringList;

            void read(sal_Bool &_nValue)    SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int8 &_nValue)    SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int16 &_nValue)   SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int32 &_nValue)   SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int64 &_nValue)   SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(double &_nValue)      SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(rtl::OUString& _aStr) SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(Binary &_aValue)      SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(StringList &_aValue)  SAL_THROW( (io::IOException, uno::RuntimeException) );

        private:
            inline uno::Reference<io::XDataInputStream> getDataInputStream();
        };
        // --------------------------------------------------------------------------

        bool readSequenceValue (
            BinaryReader      & _rReader,
            uno::Any          & _aValue,
            uno::Type const   & _aElementType) SAL_THROW( (io::IOException, uno::RuntimeException) );

        // --------------------------------------------------------------------------
    }
}
#endif
<commit_msg>INTEGRATION: CWS sb88 (1.7.10); FILE MERGED 2008/06/03 15:29:46 sb 1.7.10.1: #i89553 applied patch by cmc<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: binaryreader.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef CONFIGMGR_BINARYREADER_HXX
#define CONFIGMGR_BINARYREADER_HXX

#include <rtl/ustring.hxx>
#include <osl/file.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/io/XDataInputStream.hpp>

namespace configmgr
{
    // -----------------------------------------------------------------------------
    namespace backend
    {
        namespace css = com::sun::star;

        namespace io   = css::io;
        namespace uno  = css::uno;
        namespace lang = css::lang;

        typedef uno::Reference<lang::XMultiServiceFactory> MultiServiceFactory;
        // -----------------------------------------------------------------------------
        class BinaryReader
        {
            rtl::OUString m_sFileURL;

            uno::Reference<io::XDataInputStream> m_xDataInputStream;
        public:
            explicit BinaryReader (rtl::OUString const & _sFileURL)
            : m_sFileURL(_sFileURL)
            {}

            ~BinaryReader()
            {}

        public:
            bool open()     SAL_THROW( (io::IOException, uno::RuntimeException) );

            typedef uno::Sequence< sal_Int8 >       Binary;
            typedef uno::Sequence< rtl::OUString >  StringList;

            void read(sal_Bool &_nValue)    SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int8 &_nValue)    SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int16 &_nValue)   SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int32 &_nValue)   SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(sal_Int64 &_nValue)   SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(double &_nValue)      SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(rtl::OUString& _aStr) SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(Binary &_aValue)      SAL_THROW( (io::IOException, uno::RuntimeException) );
            void read(StringList &_aValue)  SAL_THROW( (io::IOException, uno::RuntimeException) );

        private:
            inline uno::Reference<io::XDataInputStream> getDataInputStream();
        };
        // --------------------------------------------------------------------------

        bool readSequenceValue (
            BinaryReader      & _rReader,
            uno::Any          & _aValue,
            uno::Type const   & _aElementType) SAL_THROW( (io::IOException, uno::RuntimeException) );

        // --------------------------------------------------------------------------
    }
}
#endif
<|endoftext|>


<commit_before>#include "wm.hpp"
#include "output.hpp"
#include "view.hpp"
#include "debug.hpp"
#include "core.hpp"
#include "workspace-manager.hpp"

#include "../view/xdg-shell.hpp"
#include "../view/xdg-shell-v6.hpp"

#include <linux/input.h>
#include "signal-definitions.hpp"

void wayfire_exit::init(wayfire_config*)
{
    key = [](uint32_t key)
    {
        wl_display_terminate(core->display);
    };

    output->add_key(new_static_option("<ctrl> <alt> KEY_BACKSPACE"), &key);
}

void wayfire_close::init(wayfire_config *config)
{
    grab_interface->abilities_mask = WF_ABILITY_GRAB_INPUT;
    auto key = config->get_section("core")
        ->get_option("close_top_view", "<super> KEY_Q | <alt> KEY_FN_F4");

    callback = [=] (wf_activator_source, uint32_t)
    {
        if (!output->activate_plugin(grab_interface))
            return;

        output->deactivate_plugin(grab_interface);
        auto view = output->get_active_view();
        if (view && view->role == WF_VIEW_ROLE_TOPLEVEL) view->close();
    };

    output->add_activator(key, &callback);
}

void wayfire_focus::init(wayfire_config *)
{
    grab_interface->name = "_wf_focus";
    grab_interface->abilities_mask = WF_ABILITY_CHANGE_VIEW_GEOMETRY;

    on_button = [=] (uint32_t button, int x, int y) {
        this->check_focus_surface(core->get_cursor_focus());
    };
    output->add_button(new_static_option("BTN_LEFT"), &on_button);

    on_touch = [=] (int x, int y) {
        this->check_focus_surface(core->get_touch_focus());
    };
    output->add_touch(new_static_option(""), &on_touch);

    on_view_disappear = [=] (signal_data *data) {
        set_last_focus(nullptr);
    };

    on_view_output_change = [=] (signal_data *data)
    {
        if (get_signaled_output(data) != this->output)
            send_done(last_focus); // will also reset last_focus
    };
}

void wayfire_focus::check_focus_surface(wayfire_surface_t* focus)
{
    /* Find the main view */
    auto main_surface = focus ? focus->get_main_surface() : nullptr;
    auto view = main_surface ? core->find_view(main_surface) : nullptr;

    /* Close popups from the lastly focused view */
    if (last_focus != view)
        send_done(last_focus);

    if (!view || !view->is_mapped() || !output->activate_plugin(grab_interface))
        return;

    output->deactivate_plugin(grab_interface);
    view->get_output()->focus_view(view);
    set_last_focus(view);
}

void wayfire_focus::send_done(wayfire_view view)
{
    if (!last_focus)
        return;

    std::vector<wayfire_xdg_popup*> popups;
    std::vector<wayfire_xdg6_popup*> popups_v6;

    /* Do not send done while running */
    last_focus->for_each_surface([&] (wayfire_surface_t* surface, int, int)
    {
        auto popup = dynamic_cast<wayfire_xdg_popup*> (surface);
        auto popup_v6 = dynamic_cast<wayfire_xdg6_popup*> (surface);

        if (popup)
            popups.push_back(popup);
        if (popup_v6)
            popups_v6.push_back(popup_v6);
    });

    for (auto popup : popups)
        popup->send_done();
    for (auto popup : popups_v6)
        popup->send_done();

    set_last_focus(nullptr);
}

void wayfire_focus::set_last_focus(wayfire_view view)
{
    if (last_focus)
    {
        last_focus->disconnect_signal("disappeared", &on_view_disappear);
        last_focus->disconnect_signal("set-output", &on_view_output_change);
    }

    last_focus = view;
    if (last_focus)
    {
        last_focus->connect_signal("disappeared", &on_view_disappear);
        last_focus->connect_signal("set-output", &on_view_output_change);
    }
}

void wayfire_handle_focus_parent::focus_view(wayfire_view view)
{
    last_view = view;
    view->get_output()->bring_to_front(view);
    for (auto child : view->children)
        focus_view(child);
}

void wayfire_handle_focus_parent::init(wayfire_config*)
{
    focus_event = [&] (signal_data *data)
    {
        auto view = get_signaled_view(data);
        if (!view || intercept_recursion)
            return;

        auto to_focus = view;
        while(to_focus->parent)
            to_focus = to_focus->parent;

        focus_view(to_focus);

        /* because output->focus_view() will fire focus-view signal again,
         * we use this flag to know that this is happening and don't fall
         * into the depths of the infinite recursion */
        intercept_recursion = true;
        output->focus_view(last_view);
        intercept_recursion = false;

        /* free shared_ptr reference */
        last_view.reset();
    };
    output->connect_signal("focus-view", &focus_event);
}
<commit_msg>wm: do not allow closing the compositor if output is inhibited<commit_after>#include "wm.hpp"
#include "output.hpp"
#include "view.hpp"
#include "debug.hpp"
#include "core.hpp"
#include "workspace-manager.hpp"

#include "../view/xdg-shell.hpp"
#include "../view/xdg-shell-v6.hpp"
#include "seat/input-inhibit.hpp"

#include <linux/input.h>
#include "signal-definitions.hpp"

void wayfire_exit::init(wayfire_config*)
{
    key = [](uint32_t key)
    {
        if (is_output_inhibited(core->get_active_output()))
            return;

        wl_display_terminate(core->display);
    };

    output->add_key(new_static_option("<ctrl> <alt> KEY_BACKSPACE"), &key);
}

void wayfire_close::init(wayfire_config *config)
{
    grab_interface->abilities_mask = WF_ABILITY_GRAB_INPUT;
    auto key = config->get_section("core")
        ->get_option("close_top_view", "<super> KEY_Q | <alt> KEY_FN_F4");

    callback = [=] (wf_activator_source, uint32_t)
    {
        if (!output->activate_plugin(grab_interface))
            return;

        output->deactivate_plugin(grab_interface);
        auto view = output->get_active_view();
        if (view && view->role == WF_VIEW_ROLE_TOPLEVEL) view->close();
    };

    output->add_activator(key, &callback);
}

void wayfire_focus::init(wayfire_config *)
{
    grab_interface->name = "_wf_focus";
    grab_interface->abilities_mask = WF_ABILITY_CHANGE_VIEW_GEOMETRY;

    on_button = [=] (uint32_t button, int x, int y) {
        this->check_focus_surface(core->get_cursor_focus());
    };
    output->add_button(new_static_option("BTN_LEFT"), &on_button);

    on_touch = [=] (int x, int y) {
        this->check_focus_surface(core->get_touch_focus());
    };
    output->add_touch(new_static_option(""), &on_touch);

    on_view_disappear = [=] (signal_data *data) {
        set_last_focus(nullptr);
    };

    on_view_output_change = [=] (signal_data *data)
    {
        if (get_signaled_output(data) != this->output)
            send_done(last_focus); // will also reset last_focus
    };
}

void wayfire_focus::check_focus_surface(wayfire_surface_t* focus)
{
    /* Find the main view */
    auto main_surface = focus ? focus->get_main_surface() : nullptr;
    auto view = main_surface ? core->find_view(main_surface) : nullptr;

    /* Close popups from the lastly focused view */
    if (last_focus != view)
        send_done(last_focus);

    if (!view || !view->is_mapped() || !output->activate_plugin(grab_interface))
        return;

    output->deactivate_plugin(grab_interface);
    view->get_output()->focus_view(view);
    set_last_focus(view);
}

void wayfire_focus::send_done(wayfire_view view)
{
    if (!last_focus)
        return;

    std::vector<wayfire_xdg_popup*> popups;
    std::vector<wayfire_xdg6_popup*> popups_v6;

    /* Do not send done while running */
    last_focus->for_each_surface([&] (wayfire_surface_t* surface, int, int)
    {
        auto popup = dynamic_cast<wayfire_xdg_popup*> (surface);
        auto popup_v6 = dynamic_cast<wayfire_xdg6_popup*> (surface);

        if (popup)
            popups.push_back(popup);
        if (popup_v6)
            popups_v6.push_back(popup_v6);
    });

    for (auto popup : popups)
        popup->send_done();
    for (auto popup : popups_v6)
        popup->send_done();

    set_last_focus(nullptr);
}

void wayfire_focus::set_last_focus(wayfire_view view)
{
    if (last_focus)
    {
        last_focus->disconnect_signal("disappeared", &on_view_disappear);
        last_focus->disconnect_signal("set-output", &on_view_output_change);
    }

    last_focus = view;
    if (last_focus)
    {
        last_focus->connect_signal("disappeared", &on_view_disappear);
        last_focus->connect_signal("set-output", &on_view_output_change);
    }
}

void wayfire_handle_focus_parent::focus_view(wayfire_view view)
{
    last_view = view;
    view->get_output()->bring_to_front(view);
    for (auto child : view->children)
        focus_view(child);
}

void wayfire_handle_focus_parent::init(wayfire_config*)
{
    focus_event = [&] (signal_data *data)
    {
        auto view = get_signaled_view(data);
        if (!view || intercept_recursion)
            return;

        auto to_focus = view;
        while(to_focus->parent)
            to_focus = to_focus->parent;

        focus_view(to_focus);

        /* because output->focus_view() will fire focus-view signal again,
         * we use this flag to know that this is happening and don't fall
         * into the depths of the infinite recursion */
        intercept_recursion = true;
        output->focus_view(last_view);
        intercept_recursion = false;

        /* free shared_ptr reference */
        last_view.reset();
    };
    output->connect_signal("focus-view", &focus_event);
}
<|endoftext|>


<commit_before>#include "wm.hpp"
#include "wayfire/output.hpp"
#include "wayfire/view.hpp"
#include "wayfire/core.hpp"
#include "wayfire/workspace-manager.hpp"
#include "wayfire/output-layout.hpp"

#include <wayfire/util/log.hpp>
#include <wayfire/nonstd/wlroots-full.hpp>

#include "../output/output-impl.hpp"
#include "wayfire/signal-definitions.hpp"

#include <linux/input-event-codes.h>

static void idle_shutdown(void *data)
{
    wf::get_core().shutdown();
}

void wayfire_exit::init()
{
    key = [] (const wf::keybinding_t&)
    {
        auto output_impl =
            static_cast<wf::output_impl_t*>(wf::get_core().get_active_output());
        if (output_impl->is_inhibited())
        {
            return false;
        }

        idle_shutdown(nullptr);

        return true;
    };

    // make sure to shut down wayfire if destroying the last
    // nested backend output
    on_output_removed.set_callback([=] (wf::signal_data_t *data)
    {
        auto output = wf::get_signaled_output(data);

        bool is_nested_compositor = wlr_output_is_wl(output->handle);
#if WLR_HAS_X11_BACKEND
        is_nested_compositor |= wlr_output_is_x11(output->handle);
#endif

        int cnt_other_outputs = 0;
        for (auto& wo : wf::get_core().output_layout->get_outputs())
        {
            if ((wo != output) && !wlr_output_is_noop(wo->handle))
            {
                ++cnt_other_outputs;
            }
        }

        if (is_nested_compositor && (cnt_other_outputs == 0))
        {
            wl_event_loop_add_idle(wf::get_core().ev_loop, idle_shutdown, nullptr);
        }
    });

    output->connect_signal("pre-remove", &on_output_removed);
    output->add_key(wf::create_option_string<wf::keybinding_t>(
        "<ctrl> <alt> KEY_BACKSPACE"), &key);
}

void wayfire_exit::fini()
{
    output->rem_binding(&key);
}

void wayfire_close::init()
{
    grab_interface->capabilities = wf::CAPABILITY_GRAB_INPUT;
    wf::option_wrapper_t<wf::activatorbinding_t> key("core/close_top_view");
    callback = [=] (const wf::activator_data_t& ev)
    {
        if (!output->activate_plugin(grab_interface))
        {
            return false;
        }

        output->deactivate_plugin(grab_interface);
        auto view = output->get_active_view();
        if (view && (view->role == wf::VIEW_ROLE_TOPLEVEL))
        {
            view->close();
        }

        return true;
    };

    output->add_activator(key, &callback);
}

void wayfire_close::fini()
{
    output->rem_binding(&callback);
}

void wayfire_focus::init()
{
    grab_interface->name = "_wf_focus";
    grab_interface->capabilities = wf::CAPABILITY_MANAGE_DESKTOP;

    on_wm_focus_request = [=] (wf::signal_data_t *data)
    {
        auto ev = static_cast<wm_focus_request*>(data);
        check_focus_surface(ev->surface);
    };
    output->connect_signal("wm-focus-request", &on_wm_focus_request);

    on_button.set_callback([=] (wf::signal_data_t *data)
    {
        auto ev = static_cast<
            wf::input_event_signal<wlr_event_pointer_button>*>(data);

        if (ev->event->state != WLR_BUTTON_PRESSED)
        {
            return;
        }

        /* focuse_btns->get_value() does not compile */
        wf::option_sptr_t<wf::activatorbinding_t> tmp = focus_btns;
        if ((!focus_modifiers && wf::get_core().get_keyboard_modifiers()) ||
            !tmp->get_value().has_match(wf::buttonbinding_t(0, ev->event->button)))
        {
            return;
        }

        this->check_focus_surface(wf::get_core().get_cursor_focus());
    });
    wf::get_core().connect_signal("pointer_button", &on_button);

    // build touch gesture
    auto on_tap = std::make_unique<wf::touch::touch_action_t>(1, true);
    std::vector<std::unique_ptr<wf::touch::gesture_action_t>> actions;
    actions.emplace_back(std::move(on_tap));
    const auto& on_tap_action = [this] ()
    {
        if (wf::get_core().get_active_output() == this->output)
        {
            this->check_focus_surface(wf::get_core().get_touch_focus());
        }
    };

    this->tap_gesture =
        std::make_unique<wf::touch::gesture_t>(std::move(actions), on_tap_action);
    wf::get_core().add_touch_gesture(tap_gesture);
}

void wayfire_focus::check_focus_surface(wf::surface_interface_t *focus)
{
    /* Find the main view */
    auto main_surface = focus ? focus->get_main_surface() : nullptr;
    auto view = dynamic_cast<wf::view_interface_t*>(main_surface);

    if (!view || !view->is_mapped() || !view->get_keyboard_focus_surface() ||
        !output->activate_plugin(grab_interface))
    {
        return;
    }

    output->deactivate_plugin(grab_interface);
    view->get_output()->focus_view(view->self(), true);
}

void wayfire_focus::fini()
{
    output->rem_binding(&on_button);
    wf::get_core().rem_touch_gesture(tap_gesture);
    output->disconnect_signal("wm-focus-request", &on_wm_focus_request);
}
<commit_msg>core: bring to front on click (#1024)<commit_after>#include "wm.hpp"
#include "wayfire/output.hpp"
#include "wayfire/view.hpp"
#include "wayfire/core.hpp"
#include "wayfire/workspace-manager.hpp"
#include "wayfire/output-layout.hpp"

#include <wayfire/util/log.hpp>
#include <wayfire/nonstd/wlroots-full.hpp>

#include "../output/output-impl.hpp"
#include "wayfire/signal-definitions.hpp"

#include <linux/input-event-codes.h>

static void idle_shutdown(void *data)
{
    wf::get_core().shutdown();
}

void wayfire_exit::init()
{
    key = [] (const wf::keybinding_t&)
    {
        auto output_impl =
            static_cast<wf::output_impl_t*>(wf::get_core().get_active_output());
        if (output_impl->is_inhibited())
        {
            return false;
        }

        idle_shutdown(nullptr);

        return true;
    };

    // make sure to shut down wayfire if destroying the last
    // nested backend output
    on_output_removed.set_callback([=] (wf::signal_data_t *data)
    {
        auto output = wf::get_signaled_output(data);

        bool is_nested_compositor = wlr_output_is_wl(output->handle);
#if WLR_HAS_X11_BACKEND
        is_nested_compositor |= wlr_output_is_x11(output->handle);
#endif

        int cnt_other_outputs = 0;
        for (auto& wo : wf::get_core().output_layout->get_outputs())
        {
            if ((wo != output) && !wlr_output_is_noop(wo->handle))
            {
                ++cnt_other_outputs;
            }
        }

        if (is_nested_compositor && (cnt_other_outputs == 0))
        {
            wl_event_loop_add_idle(wf::get_core().ev_loop, idle_shutdown, nullptr);
        }
    });

    output->connect_signal("pre-remove", &on_output_removed);
    output->add_key(wf::create_option_string<wf::keybinding_t>(
        "<ctrl> <alt> KEY_BACKSPACE"), &key);
}

void wayfire_exit::fini()
{
    output->rem_binding(&key);
}

void wayfire_close::init()
{
    grab_interface->capabilities = wf::CAPABILITY_GRAB_INPUT;
    wf::option_wrapper_t<wf::activatorbinding_t> key("core/close_top_view");
    callback = [=] (const wf::activator_data_t& ev)
    {
        if (!output->activate_plugin(grab_interface))
        {
            return false;
        }

        output->deactivate_plugin(grab_interface);
        auto view = output->get_active_view();
        if (view && (view->role == wf::VIEW_ROLE_TOPLEVEL))
        {
            view->close();
        }

        return true;
    };

    output->add_activator(key, &callback);
}

void wayfire_close::fini()
{
    output->rem_binding(&callback);
}

void wayfire_focus::init()
{
    grab_interface->name = "_wf_focus";
    grab_interface->capabilities = wf::CAPABILITY_MANAGE_DESKTOP;

    on_wm_focus_request = [=] (wf::signal_data_t *data)
    {
        auto ev = static_cast<wm_focus_request*>(data);
        check_focus_surface(ev->surface);
    };
    output->connect_signal("wm-focus-request", &on_wm_focus_request);

    on_button.set_callback([=] (wf::signal_data_t *data)
    {
        auto ev = static_cast<
            wf::input_event_signal<wlr_event_pointer_button>*>(data);

        if (ev->event->state != WLR_BUTTON_PRESSED)
        {
            return;
        }

        /* focuse_btns->get_value() does not compile */
        wf::option_sptr_t<wf::activatorbinding_t> tmp = focus_btns;
        if ((!focus_modifiers && wf::get_core().get_keyboard_modifiers()) ||
            !tmp->get_value().has_match(wf::buttonbinding_t(0, ev->event->button)))
        {
            return;
        }

        this->check_focus_surface(wf::get_core().get_cursor_focus());
    });
    wf::get_core().connect_signal("pointer_button", &on_button);

    // build touch gesture
    auto on_tap = std::make_unique<wf::touch::touch_action_t>(1, true);
    std::vector<std::unique_ptr<wf::touch::gesture_action_t>> actions;
    actions.emplace_back(std::move(on_tap));
    const auto& on_tap_action = [this] ()
    {
        if (wf::get_core().get_active_output() == this->output)
        {
            this->check_focus_surface(wf::get_core().get_touch_focus());
        }
    };

    this->tap_gesture =
        std::make_unique<wf::touch::gesture_t>(std::move(actions), on_tap_action);
    wf::get_core().add_touch_gesture(tap_gesture);
}

void wayfire_focus::check_focus_surface(wf::surface_interface_t *focus)
{
    /* Find the main view */
    auto main_surface = focus ? focus->get_main_surface() : nullptr;
    auto view = dynamic_cast<wf::view_interface_t*>(main_surface);

    if (!view || !view->is_mapped() ||
        !output->can_activate_plugin(grab_interface->capabilities))
    {
        return;
    }

    auto target_wo = view->get_output();
    if (view->get_keyboard_focus_surface())
    {
        target_wo->focus_view(view->self(), true);
    } else
    {
        target_wo->workspace->bring_to_front(view);
    }
}

void wayfire_focus::fini()
{
    output->rem_binding(&on_button);
    wf::get_core().rem_touch_gesture(tap_gesture);
    output->disconnect_signal("wm-focus-request", &on_wm_focus_request);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
**     the names of its contributors may be used to endorse or promote
**     products derived from this software without specific prior written
**     permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/

#include "device.h"
#include "service.h"

#include <qbluetoothaddress.h>
#include <qbluetoothdevicediscoveryagent.h>
#include <qbluetoothlocaldevice.h>
#include <QMenu>
#include <QDebug>

DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent)
:   QDialog(parent), discoveryAgent(new QBluetoothDeviceDiscoveryAgent),
    localDevice(new QBluetoothLocalDevice),
    ui(new Ui_DeviceDiscovery)
{
    ui->setupUi(this);

#if defined (Q_OS_SYMBIAN) || defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
    setWindowState(Qt::WindowFullScreen);
#endif

    connect(ui->inquiryType, SIGNAL(toggled(bool)), this, SLOT(setGeneralUnlimited(bool)));
    connect(ui->scan, SIGNAL(clicked()), this, SLOT(startScan()));

    connect(discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)),
            this, SLOT(addDevice(const QBluetoothDeviceInfo&)));
    connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));

    connect(ui->list, SIGNAL(itemActivated(QListWidgetItem*)),
            this, SLOT(itemActivated(QListWidgetItem*)));

    connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
            this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));

    hostModeStateChanged(localDevice->hostMode());
    // add context menu for devices to be able to pair device
    ui->list->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayPairingMenu(QPoint)));
    connect(localDevice, SIGNAL(pairingFinished(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing))
        , this, SLOT(pairingDone(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing)));

}

DeviceDiscoveryDialog::~DeviceDiscoveryDialog()
{
    delete discoveryAgent;
}

void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info)
{
    QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
    QList<QListWidgetItem *> items = ui->list->findItems(label, Qt::MatchExactly);
    if(items.empty()) {
        QListWidgetItem *item = new QListWidgetItem(label);
        QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
        if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired )
            item->setTextColor(QColor(Qt::green));

        ui->list->addItem(item);
    }

}

void DeviceDiscoveryDialog::startScan()
{
    discoveryAgent->start();
    ui->scan->setEnabled(false);
    ui->inquiryType->setEnabled(false);
}

void DeviceDiscoveryDialog::scanFinished()
{
    ui->scan->setEnabled(true);
    ui->inquiryType->setEnabled(true);
}

void DeviceDiscoveryDialog::setGeneralUnlimited(bool unlimited)
{
    if (unlimited)
        discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
    else
        discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::LimitedInquiry);
}

void DeviceDiscoveryDialog::itemActivated(QListWidgetItem *item)
{
    QString text = item->text();

    int index = text.indexOf(' ');

    if (index == -1)
        return;

    QBluetoothAddress address(text.left(index));
    QString name(text.mid(index + 1));

    ServiceDiscoveryDialog d(name, address);
    d.exec();
}

void DeviceDiscoveryDialog::on_discoverable_clicked(bool clicked)
{
    if(clicked)
        localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable);
    else
        localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable);
}

void DeviceDiscoveryDialog::on_power_clicked(bool clicked)
{
    if(clicked)
        localDevice->powerOn();
    else
        localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
}

void DeviceDiscoveryDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode)
{
    if(mode != QBluetoothLocalDevice::HostPoweredOff)
        ui->power->setChecked(true);
    else
       ui->power->setChecked( false);

    if(mode == QBluetoothLocalDevice::HostDiscoverable)
        ui->discoverable->setChecked(true);
    else
        ui->discoverable->setChecked(false);

    bool on = !(mode == QBluetoothLocalDevice::HostPoweredOff);

    ui->scan->setEnabled(on);
    ui->discoverable->setEnabled(on);
}
void DeviceDiscoveryDialog::displayPairingMenu(const QPoint &pos)
{
    QMenu menu(this);
    QAction *pairAction = menu.addAction("Pair");
    QAction *removePairAction = menu.addAction("Remove Pairing");
    QAction *chosenAction = menu.exec(ui->list->viewport()->mapToGlobal(pos));
    QListWidgetItem *currentItem = ui->list->currentItem();

    QString text = currentItem->text();
    int index = text.indexOf(' ');
    if (index == -1)
        return;

    QBluetoothAddress address (text.left(index));
    if (chosenAction == pairAction) {
        localDevice->requestPairing(address, QBluetoothLocalDevice::Paired);
    } else if (chosenAction == removePairAction) {
        localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired);
    }
}
void DeviceDiscoveryDialog::pairingDone(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
{
    QList<QListWidgetItem *> items = ui->list->findItems(address.toString(), Qt::MatchContains);

    if (pairing == QBluetoothLocalDevice::Paired || pairing == QBluetoothLocalDevice::AuthorizedPaired ) {
        for (int var = 0; var < items.count(); ++var) {
            QListWidgetItem *item = items.at(var);
            item->setTextColor(QColor(Qt::green));
        }
    } else {
        for (int var = 0; var < items.count(); ++var) {
            QListWidgetItem *item = items.at(var);
            item->setTextColor(QColor(Qt::red));
        }
    }
}
<commit_msg>remove whitespace from device.cpp<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
**     the names of its contributors may be used to endorse or promote
**     products derived from this software without specific prior written
**     permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/

#include "device.h"
#include "service.h"

#include <qbluetoothaddress.h>
#include <qbluetoothdevicediscoveryagent.h>
#include <qbluetoothlocaldevice.h>
#include <QMenu>
#include <QDebug>

DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent)
:   QDialog(parent), discoveryAgent(new QBluetoothDeviceDiscoveryAgent),
    localDevice(new QBluetoothLocalDevice),
    ui(new Ui_DeviceDiscovery)
{
    ui->setupUi(this);

#if defined (Q_OS_SYMBIAN) || defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
    setWindowState(Qt::WindowFullScreen);
#endif

    connect(ui->inquiryType, SIGNAL(toggled(bool)), this, SLOT(setGeneralUnlimited(bool)));
    connect(ui->scan, SIGNAL(clicked()), this, SLOT(startScan()));

    connect(discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)),
            this, SLOT(addDevice(const QBluetoothDeviceInfo&)));
    connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));

    connect(ui->list, SIGNAL(itemActivated(QListWidgetItem*)),
            this, SLOT(itemActivated(QListWidgetItem*)));

    connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
            this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));

    hostModeStateChanged(localDevice->hostMode());
    // add context menu for devices to be able to pair device
    ui->list->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayPairingMenu(QPoint)));
    connect(localDevice, SIGNAL(pairingFinished(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing))
        , this, SLOT(pairingDone(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing)));

}

DeviceDiscoveryDialog::~DeviceDiscoveryDialog()
{
    delete discoveryAgent;
}

void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info)
{
    QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
    QList<QListWidgetItem *> items = ui->list->findItems(label, Qt::MatchExactly);
    if(items.empty()) {
        QListWidgetItem *item = new QListWidgetItem(label);
        QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
        if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired )
            item->setTextColor(QColor(Qt::green));

        ui->list->addItem(item);
    }

}

void DeviceDiscoveryDialog::startScan()
{
    discoveryAgent->start();
    ui->scan->setEnabled(false);
    ui->inquiryType->setEnabled(false);
}

void DeviceDiscoveryDialog::scanFinished()
{
    ui->scan->setEnabled(true);
    ui->inquiryType->setEnabled(true);
}

void DeviceDiscoveryDialog::setGeneralUnlimited(bool unlimited)
{
    if (unlimited)
        discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
    else
        discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::LimitedInquiry);
}

void DeviceDiscoveryDialog::itemActivated(QListWidgetItem *item)
{
    QString text = item->text();

    int index = text.indexOf(' ');

    if (index == -1)
        return;

    QBluetoothAddress address(text.left(index));
    QString name(text.mid(index + 1));

    ServiceDiscoveryDialog d(name, address);
    d.exec();
}

void DeviceDiscoveryDialog::on_discoverable_clicked(bool clicked)
{
    if(clicked)
        localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable);
    else
        localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable);
}

void DeviceDiscoveryDialog::on_power_clicked(bool clicked)
{
    if(clicked)
        localDevice->powerOn();
    else
        localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
}

void DeviceDiscoveryDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode)
{
    if(mode != QBluetoothLocalDevice::HostPoweredOff)
        ui->power->setChecked(true);
    else
       ui->power->setChecked( false);

    if(mode == QBluetoothLocalDevice::HostDiscoverable)
        ui->discoverable->setChecked(true);
    else
        ui->discoverable->setChecked(false);

    bool on = !(mode == QBluetoothLocalDevice::HostPoweredOff);

    ui->scan->setEnabled(on);
    ui->discoverable->setEnabled(on);
}
void DeviceDiscoveryDialog::displayPairingMenu(const QPoint &pos)
{
    QMenu menu(this);
    QAction *pairAction = menu.addAction("Pair");
    QAction *removePairAction = menu.addAction("Remove Pairing");
    QAction *chosenAction = menu.exec(ui->list->viewport()->mapToGlobal(pos));
    QListWidgetItem *currentItem = ui->list->currentItem();

    QString text = currentItem->text();
    int index = text.indexOf(' ');
    if (index == -1)
        return;

    QBluetoothAddress address (text.left(index));
    if (chosenAction == pairAction) {
        localDevice->requestPairing(address, QBluetoothLocalDevice::Paired);
    } else if (chosenAction == removePairAction) {
        localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired);
    }
}
void DeviceDiscoveryDialog::pairingDone(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
{
    QList<QListWidgetItem *> items = ui->list->findItems(address.toString(), Qt::MatchContains);

    if (pairing == QBluetoothLocalDevice::Paired || pairing == QBluetoothLocalDevice::AuthorizedPaired ) {
        for (int var = 0; var < items.count(); ++var) {
            QListWidgetItem *item = items.at(var);
            item->setTextColor(QColor(Qt::green));
        }
    } else {
        for (int var = 0; var < items.count(); ++var) {
            QListWidgetItem *item = items.at(var);
            item->setTextColor(QColor(Qt::red));
        }
    }
}
<|endoftext|>


<commit_before>#include "classes.h"
#include "msvc.h"

#include <sycl.hpp>

#include <chrono>
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using std::string;

extern void compute_org(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_org_openmp(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_org_sp(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_org_sp_openmp(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_sycl_gtx(void* dev, int w, int h, int samps, Ray& cam_, Vec& cx_, Vec& cy_, Vec r_, Vec* c_);

inline double clamp(double x) {
	return x < 0 ? 0 : x>1 ? 1 : x;
}
inline int toInt(double x) {
	return int(pow(clamp(x), 1 / 2.2) * 255 + .5);
}

void to_file(int w, int h, Vec* c, string filename) {
	FILE* f = fopen(filename.c_str(), "w");         // Write image to PPM file.
	fprintf(f, "P3\n%d %d\n%d\n", w, h, 255);
	for(int i = 0; i < w*h; i++) {
		fprintf(f, "%d %d %d\n", toInt(c[i].x), toInt(c[i].y), toInt(c[i].z));
	}
	fclose(f);
}

using time_point = std::chrono::high_resolution_clock::time_point;

auto now = []() {
	return std::chrono::high_resolution_clock::now();
};
auto duration = [](time_point before) {
	static const float to_seconds = 1e-6f;
	return std::chrono::duration_cast<std::chrono::microseconds>(now() - before).count() * to_seconds;
};

struct testInfo {
	using function_ptr = void(*)(void*, int, int, int, Ray&, Vec&, Vec&, Vec, Vec*);
	string name;
	function_ptr test;
	std::unique_ptr<cl::sycl::device> dev;
	float lastTime = 0;

	static decltype(now()) startTime;
	static float totalTime;

	testInfo(string name, function_ptr test, cl::sycl::device* dev = nullptr)
		: name(name), test(test), dev(dev) {}

	testInfo(const testInfo&) = delete;
	testInfo(testInfo&& move)
		: name(std::move(move.name)), test(move.test), dev(std::move(move.dev)) {}
};
decltype(now()) testInfo::startTime = now();
float testInfo::totalTime = 0;

static std::vector<const testInfo> tests;
static Ray cam(Vec(50, 52, 295.6), Vec(0, -0.042612, -1).norm()); // cam pos, dir

bool tester(int w, int h, int samples, Vec& cx, Vec& cy, int iterations, int from, int to) {
	using namespace std;

	cout << "samples per pixel: " << samples << endl;

	Vec r;
	vector<Vec> empty_vectors(w*h, 0);
	vector<Vec> vectors;
	float time;

	for(int ti = from; ti < to; ++ti) {
		auto& t = tests[ti];

		// Quality of Service
		// Prevent the user from waiting too long
		if(t.lastTime > 40) {
			continue;
		}

		cout << "Running test: " << t.name << endl;
		ns_erand::reset();
		try {
			auto start = now();
			for(int i = 0; i < iterations; ++i) {
				vectors = empty_vectors;
				t.test(t.dev.get(), w, h, samples, cam, cx, cy, r, vectors.data());
			}
			time = (duration(start) / (float)iterations);
		}
		catch(cl::sycl::exception& e) {
			cerr << "SYCL error while testing: " << e.what() << endl;
			continue;
		}
		catch(exception& e) {
			cerr << "error while testing: " << e.what() << endl;
			continue;
		}
		cout << "time: " << time << endl;
		//to_file(w, h, vectors.data(), string("image_") + t.name + ".ppm");

		t.lastTime = time;

		testInfo::totalTime = duration(testInfo::startTime);
		if(testInfo::totalTime > 300) {
			cout << "exceeded 5 minute limit, stopping" << endl;
			return false;
		}
	}

	return true;
}

template <class T>
void printInfo(string description, const T& data, int offset = 0) {
	string indent;
	for(int i = 0; i < offset; ++i) {
		indent += '\t';
	}
	std::cout << indent << description << ": " << data << std::endl;
}

void getDevices() {
	using namespace std;

	try {
		using namespace cl::sycl;

		auto platforms = platform::get_platforms();

		int pNum = 0;
		for(auto& p : platforms) {
			cout << "- OpenCL platform " << pNum << ':' << endl;
			++pNum;

			auto openclVersion = p.get_info<info::platform::version>();

			printInfo("name", p.get_info<info::platform::name>(), 1);
			printInfo("vendor", p.get_info<info::platform::vendor>(), 1);
			printInfo("version", openclVersion, 1);
			printInfo("profile", p.get_info<info::platform::profile>(), 1);
			printInfo("extensions", p.get_info<info::platform::extensions>(), 1);

			auto devices = p.get_devices();
			int dNum = 0;

			for(auto& d : devices) {
				cout << "\t-- OpenCL device " << dNum << ':' << endl;

				auto name = d.get_info<info::device::name>();

				printInfo("name", d.get_info<info::device::name>(), 2);
				printInfo("device_type", (cl_device_type)d.get_info<info::device::device_type>(), 2);
				printInfo("vendor", d.get_info<info::device::vendor>(), 2);
				printInfo("device_version", d.get_info<info::device::device_version>(), 2);
				printInfo("driver_version", d.get_info<info::device::driver_version>(), 2);
				printInfo("opencl_version", d.get_info<info::device::opencl_version>(), 2);
				printInfo("single_fp_config", d.get_info<info::device::single_fp_config>(), 2);
				printInfo("double_fp_config", d.get_info<info::device::double_fp_config>(), 2);
				printInfo("profile", d.get_info<info::device::profile>(), 2);
				printInfo("error_correction_support", d.get_info<info::device::error_correction_support>(), 2);
				printInfo("host_unified_memory", d.get_info<info::device::host_unified_memory>(), 2);
				printInfo("max_clock_frequency", d.get_info<info::device::max_clock_frequency>(), 2);
				printInfo("max_compute_units", d.get_info<info::device::max_compute_units>(), 2);
				printInfo("max_work_item_dimensions", d.get_info<info::device::max_work_item_dimensions>(), 2);
				printInfo("max_work_group_size", d.get_info<info::device::max_work_group_size>(), 2);

				printInfo("address_bits", d.get_info<info::device::address_bits>(), 2);
				printInfo("max_mem_alloc_size", d.get_info<info::device::max_mem_alloc_size>(), 2);
				printInfo("global_mem_cache_line_size", d.get_info<info::device::global_mem_cache_line_size>(), 2);
				printInfo("global_mem_cache_size", d.get_info<info::device::global_mem_cache_size>(), 2);
				printInfo("global_mem_size", d.get_info<info::device::global_mem_size>(), 2);
				printInfo("max_constant_buffer_size", d.get_info<info::device::max_constant_buffer_size>(), 2);
				printInfo("max_constant_args", d.get_info<info::device::max_constant_args>(), 2);
				printInfo("local_mem_size", d.get_info<info::device::local_mem_size>(), 2);
				printInfo("extensions", d.get_info<info::device::extensions>(), 2);

				tests.emplace_back(name + ' ' + openclVersion, compute_sycl_gtx, new device(std::move(d)));

				++dNum;
			}
		}
	}
	catch(cl::sycl::exception& e) {
		// TODO
		cout << "OpenCL not available: " << e.what() << endl;
	}
}

int main(int argc, char *argv[]) {
	using namespace std;

	cout << "smallpt SYCL tester" << endl;

	tests.emplace_back("org_single", compute_org_sp);
	tests.emplace_back("openmp_single", compute_org_sp_openmp);
	tests.emplace_back("org", compute_org);
	tests.emplace_back("openmp", compute_org_openmp);

	getDevices();

	int w = 1024;
	int h = 768;
	Vec cx = Vec(w*.5135 / h);
	Vec cy = (cx%cam.d).norm()*.5135;
	auto numTests = tests.size();

	int from = 2;
	int to = numTests;
	if(argc > 1) {
		from = atoi(argv[1]);
		if(argc > 2) {
			to = atoi(argv[2]);
		}
	}

	cout << "Going through tests in range [" << from << ',' << to << ')' << endl;

	if(false) {
		tester(w, h, 1, cx, cy, 1, from, to);
		cout << "Press any key to exit" << endl;
		cin.get();
		return 0;
	}

	// Test suite
	int iterations = 1;
	bool canContinue;

	for(int samples = 5; samples < 10000; samples *= 2) {
		canContinue = tester(w, h, samples, cx, cy, iterations, from, to);
		if(!canContinue) {
			break;
		}
	}

	auto time = duration(testInfo::startTime);
	cout << "total test suite duration: " << time << endl;

	//cout << "Press any key to exit" << endl;
	//cin.get();

	return 0;
}
<commit_msg>smallpt - checking for platform version before adding device to test<commit_after>#include "classes.h"
#include "msvc.h"

#include <sycl.hpp>

#include <chrono>
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using std::string;

extern void compute_org(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_org_openmp(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_org_sp(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_org_sp_openmp(void*, int w, int h, int samps, Ray& cam, Vec& cx, Vec& cy, Vec r, Vec* c);
extern void compute_sycl_gtx(void* dev, int w, int h, int samps, Ray& cam_, Vec& cx_, Vec& cy_, Vec r_, Vec* c_);

inline double clamp(double x) {
	return x < 0 ? 0 : x>1 ? 1 : x;
}
inline int toInt(double x) {
	return int(pow(clamp(x), 1 / 2.2) * 255 + .5);
}

void to_file(int w, int h, Vec* c, string filename) {
	FILE* f = fopen(filename.c_str(), "w");         // Write image to PPM file.
	fprintf(f, "P3\n%d %d\n%d\n", w, h, 255);
	for(int i = 0; i < w*h; i++) {
		fprintf(f, "%d %d %d\n", toInt(c[i].x), toInt(c[i].y), toInt(c[i].z));
	}
	fclose(f);
}

using time_point = std::chrono::high_resolution_clock::time_point;

auto now = []() {
	return std::chrono::high_resolution_clock::now();
};
auto duration = [](time_point before) {
	static const float to_seconds = 1e-6f;
	return std::chrono::duration_cast<std::chrono::microseconds>(now() - before).count() * to_seconds;
};

struct testInfo {
	using function_ptr = void(*)(void*, int, int, int, Ray&, Vec&, Vec&, Vec, Vec*);
	string name;
	function_ptr test;
	std::unique_ptr<cl::sycl::device> dev;
	float lastTime = 0;

	static decltype(now()) startTime;
	static float totalTime;

	testInfo(string name, function_ptr test, cl::sycl::device* dev = nullptr)
		: name(name), test(test), dev(dev) {}

	testInfo(const testInfo&) = delete;
	testInfo(testInfo&& move)
		: name(std::move(move.name)), test(move.test), dev(std::move(move.dev)) {}
};
decltype(now()) testInfo::startTime = now();
float testInfo::totalTime = 0;

static std::vector<const testInfo> tests;
static Ray cam(Vec(50, 52, 295.6), Vec(0, -0.042612, -1).norm()); // cam pos, dir

bool tester(int w, int h, int samples, Vec& cx, Vec& cy, int iterations, int from, int to) {
	using namespace std;

	cout << "samples per pixel: " << samples << endl;

	Vec r;
	vector<Vec> empty_vectors(w*h, 0);
	vector<Vec> vectors;
	float time;

	for(int ti = from; ti < to; ++ti) {
		auto& t = tests[ti];

		// Quality of Service
		// Prevent the user from waiting too long
		if(t.lastTime > 40) {
			continue;
		}

		cout << "Running test: " << t.name << endl;
		ns_erand::reset();
		try {
			auto start = now();
			for(int i = 0; i < iterations; ++i) {
				vectors = empty_vectors;
				t.test(t.dev.get(), w, h, samples, cam, cx, cy, r, vectors.data());
			}
			time = (duration(start) / (float)iterations);
		}
		catch(cl::sycl::exception& e) {
			cerr << "SYCL error while testing: " << e.what() << endl;
			continue;
		}
		catch(exception& e) {
			cerr << "error while testing: " << e.what() << endl;
			continue;
		}
		cout << "time: " << time << endl;
		//to_file(w, h, vectors.data(), string("image_") + t.name + ".ppm");

		t.lastTime = time;

		testInfo::totalTime = duration(testInfo::startTime);
		if(testInfo::totalTime > 300) {
			cout << "exceeded 5 minute limit, stopping" << endl;
			return false;
		}
	}

	return true;
}

struct version {
	int major = 0;
	int minor = 0;

	version(int major, int minor)
		: major(major), minor(minor) {}
	version(const string& v) {
		// https://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clGetPlatformInfo.html
		using namespace std;
		string search("OpenCL");
		auto pos = v.find(search);
		if(pos != string::npos) {
			pos += search.length() + 1;	// Plus one for space
			try {
				major = (int)v.at(pos) - '0';
				minor = (int)v.at(pos + 2) - '0';; // Plus one for dot
			}
			catch(std::exception& e) {}
		}
	}
};

template <class T>
void printInfo(string description, const T& data, int offset = 0) {
	string indent;
	for(int i = 0; i < offset; ++i) {
		indent += '\t';
	}
	std::cout << indent << description << ": " << data << std::endl;
}

void getDevices() {
	using namespace std;

	try {
		using namespace cl::sycl;

		auto platforms = platform::get_platforms();

		version required(1, 2);

		int pNum = 0;
		for(auto& p : platforms) {
			cout << "- OpenCL platform " << pNum << ':' << endl;
			++pNum;

			auto openclVersion = p.get_info<info::platform::version>();

			version platformVersion(openclVersion);

			printInfo("name", p.get_info<info::platform::name>(), 1);
			printInfo("vendor", p.get_info<info::platform::vendor>(), 1);
			printInfo("version", openclVersion, 1);
			printInfo("profile", p.get_info<info::platform::profile>(), 1);
			printInfo("extensions", p.get_info<info::platform::extensions>(), 1);

			auto devices = p.get_devices();
			int dNum = 0;

			for(auto& d : devices) {
				cout << "\t-- OpenCL device " << dNum << ':' << endl;

				auto name = d.get_info<info::device::name>();

				printInfo("name", d.get_info<info::device::name>(), 2);
				printInfo("device_type", (cl_device_type)d.get_info<info::device::device_type>(), 2);
				printInfo("vendor", d.get_info<info::device::vendor>(), 2);
				printInfo("device_version", d.get_info<info::device::device_version>(), 2);
				printInfo("driver_version", d.get_info<info::device::driver_version>(), 2);
				printInfo("opencl_version", d.get_info<info::device::opencl_version>(), 2);
				printInfo("single_fp_config", d.get_info<info::device::single_fp_config>(), 2);
				printInfo("double_fp_config", d.get_info<info::device::double_fp_config>(), 2);
				printInfo("profile", d.get_info<info::device::profile>(), 2);
				printInfo("error_correction_support", d.get_info<info::device::error_correction_support>(), 2);
				printInfo("host_unified_memory", d.get_info<info::device::host_unified_memory>(), 2);
				printInfo("max_clock_frequency", d.get_info<info::device::max_clock_frequency>(), 2);
				printInfo("max_compute_units", d.get_info<info::device::max_compute_units>(), 2);
				printInfo("max_work_item_dimensions", d.get_info<info::device::max_work_item_dimensions>(), 2);
				printInfo("max_work_group_size", d.get_info<info::device::max_work_group_size>(), 2);

				printInfo("address_bits", d.get_info<info::device::address_bits>(), 2);
				printInfo("max_mem_alloc_size", d.get_info<info::device::max_mem_alloc_size>(), 2);
				printInfo("global_mem_cache_line_size", d.get_info<info::device::global_mem_cache_line_size>(), 2);
				printInfo("global_mem_cache_size", d.get_info<info::device::global_mem_cache_size>(), 2);
				printInfo("global_mem_size", d.get_info<info::device::global_mem_size>(), 2);
				printInfo("max_constant_buffer_size", d.get_info<info::device::max_constant_buffer_size>(), 2);
				printInfo("max_constant_args", d.get_info<info::device::max_constant_args>(), 2);
				printInfo("local_mem_size", d.get_info<info::device::local_mem_size>(), 2);
				printInfo("extensions", d.get_info<info::device::extensions>(), 2);

				if(
					platformVersion.major > required.major ||
					(platformVersion.major == required.major && platformVersion.minor >= required.minor)
				) {
					tests.emplace_back(name + ' ' + openclVersion, compute_sycl_gtx, new device(std::move(d)));
				}

				++dNum;
			}
		}
	}
	catch(cl::sycl::exception& e) {
		// TODO
		cout << "OpenCL not available: " << e.what() << endl;
	}
}

int main(int argc, char *argv[]) {
	using namespace std;

	cout << "smallpt SYCL tester" << endl;

	tests.emplace_back("org_single", compute_org_sp);
	tests.emplace_back("openmp_single", compute_org_sp_openmp);
	tests.emplace_back("org", compute_org);
	tests.emplace_back("openmp", compute_org_openmp);

	getDevices();

	int w = 1024;
	int h = 768;
	Vec cx = Vec(w*.5135 / h);
	Vec cy = (cx%cam.d).norm()*.5135;
	auto numTests = tests.size();

	int from = 2;
	int to = numTests;
	if(argc > 1) {
		from = atoi(argv[1]);
		if(argc > 2) {
			to = atoi(argv[2]);
		}
	}

	cout << "Going through tests in range [" << from << ',' << to << ')' << endl;

	if(false) {
		tester(w, h, 1, cx, cy, 1, from, to);
		cout << "Press any key to exit" << endl;
		cin.get();
		return 0;
	}

	// Test suite
	int iterations = 1;
	bool canContinue;

	for(int samples = 5; samples < 10000; samples *= 2) {
		canContinue = tester(w, h, samples, cx, cy, iterations, from, to);
		if(!canContinue) {
			break;
		}
	}

	auto time = duration(testInfo::startTime);
	cout << "total test suite duration: " << time << endl;

	//cout << "Press any key to exit" << endl;
	//cin.get();

	return 0;
}
<|endoftext|>