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

#include "chrome/browser/extensions/extension_tabs_module.h"

#include "base/string_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/tab_contents/navigation_entry.h"

// Forward declare static helper functions defined below.
static DictionaryValue* CreateWindowValue(Browser* browser);
static ListValue* CreateTabList(Browser* browser);
static DictionaryValue* CreateTabValue(TabStripModel* tab_strip_model,
                                       int tab_index);
static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
                            int* tab_index);

// ExtensionTabUtil
int ExtensionTabUtil::GetWindowId(const Browser* browser) {
  return browser->session_id().id();
}

int ExtensionTabUtil::GetTabId(const TabContents* tab_contents) {
  return tab_contents->controller().session_id().id();
}

int ExtensionTabUtil::GetWindowIdOfTab(const TabContents* tab_contents) {
  return tab_contents->controller().window_id().id();
}

bool GetWindowsFunction::RunImpl() {
  std::set<int> window_ids;

  // Look for |ids| named parameter as list of id's to fetch.
  if (args_->IsType(Value::TYPE_DICTIONARY)) {
    Value *ids_value;
    if ((!static_cast<DictionaryValue*>(args_)->Get(L"ids", &ids_value)) ||
        (!ids_value->IsType(Value::TYPE_LIST))) {
      DCHECK(false);
      return false;
    }

    ListValue *window_id_list = static_cast<ListValue*>(ids_value);
    for (ListValue::iterator id = window_id_list->begin();
         id != window_id_list->end(); ++id) {
      int window_id;
      if (!(*id)->GetAsInteger(&window_id)) {
        DCHECK(false);
        return false;
      }

      window_ids.insert(window_id);
    }
  }

  // Default to all windows.
  bool all_windows = (window_ids.size() == 0);

  result_.reset(new ListValue());
  for (BrowserList::const_iterator browser = BrowserList::begin();
       browser != BrowserList::end(); ++browser) {
    if (all_windows || (window_ids.find(ExtensionTabUtil::GetWindowId(*browser))
        != window_ids.end())) {
      static_cast<ListValue*>(result_.get())->Append(
        CreateWindowValue(*browser));
    }
  }

  return true;
}

bool GetTabsForWindowFunction::RunImpl() {
  if (!args_->IsType(Value::TYPE_NULL))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  result_.reset(CreateTabList(browser));

  return true;
}

bool CreateTabFunction::RunImpl() {
  // TODO(aa): Do data-driven validation in JS.
  if (!args_->IsType(Value::TYPE_DICTIONARY))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  TabStripModel *tab_strip = browser->tabstrip_model();
  const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);

  // TODO(rafaelw): handle setting remaining tab properties:
  // -windowId
  // -title
  // -favIconUrl

  std::string url;
  args->GetString(L"url", &url);

  // Default to foreground for the new tab. The presence of 'selected' property
  // will override this default.
  bool selected = true;
  args->GetBoolean(L"selected", &selected);

  // If index is specified, honor the value, but keep it bound to
  // 0 <= index <= tab_strip->count()
  int index = -1;
  args->GetInteger(L"index", &index);
  if (index < 0) {
    // Default insert behavior
    index = -1;
  }
  if (index > tab_strip->count()) {
    index = tab_strip->count();
  }

  TabContents* contents = browser->AddTabWithURL(GURL(url), GURL(),
      PageTransition::TYPED, selected, index, NULL);
  index = tab_strip->GetIndexOfTabContents(contents);

  // Return data about the newly created tab.
  if (has_callback())
    result_.reset(CreateTabValue(tab_strip, index));

  return true;
}

bool GetTabFunction::RunImpl() {
  if (!args_->IsType(Value::TYPE_INTEGER))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  args_->GetAsInteger(&tab_id);

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  // TODO(rafaelw): return an error if the tab is not found by |tab_id|
  if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
    return false;

  result_.reset(CreateTabValue(tab_strip, tab_index));
  return true;
}

bool UpdateTabFunction::RunImpl() {
  // TODO(aa): Do data-driven validation in JS.
  if (!args_->IsType(Value::TYPE_DICTIONARY))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
  if (!args->GetInteger(L"id", &tab_id))
    return false;

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  // TODO(rafaelw): return an error if the tab is not found by |tab_id|
  if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
    return false;

  TabContents* tab_contents = tab_strip->GetTabContentsAt(tab_index);
  NavigationController& controller = tab_contents->controller();

  // TODO(rafaelw): handle setting remaining tab properties:
  // -title
  // -favIconUrl

  // Navigate the tab to a new location if the url different.
  std::string url;
  if (args->GetString(L"url", &url)) {
    GURL new_gurl(url);
    if (new_gurl.is_valid()) {
      controller.LoadURL(new_gurl, GURL(), PageTransition::TYPED);
    } else {
      // TODO(rafaelw): return some reasonable error?
    }
  }

  bool selected;
  // TODO(rafaelw): Setting |selected| from js doesn't make much sense.
  // Move tab selection management up to window.
  if (args->GetBoolean(L"selected", &selected) &&
      selected &&
      tab_strip->selected_index() != tab_index) {
    tab_strip->SelectTabContentsAt(tab_index, false);
  }

  return true;
}

bool MoveTabFunction::RunImpl() {
  if (!args_->IsType(Value::TYPE_DICTIONARY))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
  if (!args->GetInteger(L"id", &tab_id))
    return false;

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  // TODO(rafaelw): return an error if the tab is not found by |tab_id|
  if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
    return false;

  // TODO(rafaelw): support moving tabs between windows
  // -windowId

  int new_index;
  DCHECK(args->GetInteger(L"index", &new_index));
  if (new_index < 0) {
    DCHECK(false);
    return false;
  }

  // Clamp move location to the last position.
  if (new_index >= tab_strip->count()) {
    new_index = tab_strip->count() - 1;
  }

  if (new_index != tab_index) {
    tab_strip->MoveTabContentsAt(tab_index, new_index, false);
  }

  return true;
}

bool RemoveTabFunction::RunImpl() {
  // TODO(rafaelw): This should have a callback, but it can't because it could
  // close it's own tab.

  if (!args_->IsType(Value::TYPE_INTEGER))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  if (!args_->GetAsInteger(&tab_id)) {
    return false;
  }

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  if (GetIndexOfTabId(tab_strip, tab_id, &tab_index)) {
    browser->CloseContents(tab_strip->GetTabContentsAt(tab_index));
    return true;
  }

  return false;
}

// static helpers
static DictionaryValue* CreateWindowValue(Browser* browser) {
  DictionaryValue* result = new DictionaryValue();
  result->SetInteger(L"id", ExtensionTabUtil::GetWindowId(browser));
  result->SetBoolean(L"focused", browser->window()->IsActive());
  gfx::Rect bounds = browser->window()->GetNormalBounds();

  // TODO(rafaelw): zIndex ?
  result->SetInteger(L"left", bounds.x());
  result->SetInteger(L"top", bounds.y());
  result->SetInteger(L"width", bounds.width());
  result->SetInteger(L"height", bounds.height());

  result->Set(L"tabs", CreateTabList(browser));

  return result;
}

static ListValue* CreateTabList(Browser* browser) {
  ListValue *tab_list = new ListValue();
  TabStripModel* tab_strip = browser->tabstrip_model();
  for (int i = 0; i < tab_strip->count(); ++i) {
    tab_list->Append(CreateTabValue(tab_strip, i));
  }

  return tab_list;
}

static DictionaryValue* CreateTabValue(TabStripModel* tab_strip,
                                       int tab_index) {
  TabContents* contents = tab_strip->GetTabContentsAt(tab_index);

  DictionaryValue* result = new DictionaryValue();
  result->SetInteger(L"id", ExtensionTabUtil::GetTabId(contents));
  result->SetInteger(L"index", tab_index);
  result->SetInteger(L"windowId", ExtensionTabUtil::GetWindowIdOfTab(contents));
  result->SetString(L"url", contents->GetURL().spec());
  result->SetString(L"title", UTF16ToWide(contents->GetTitle()));
  result->SetBoolean(L"selected", tab_index == tab_strip->selected_index());

  NavigationEntry* entry = contents->controller().GetActiveEntry();
  if (entry) {
    if (entry->favicon().is_valid())
      result->SetString(L"favIconUrl", entry->favicon().url().spec());
  }

  return result;
}

static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
                            int* tab_index) {
  for (int i = 0; i < tab_strip->count(); ++i) {
    TabContents* tab_contents = tab_strip->GetTabContentsAt(i);
    if (tab_contents->controller().session_id().id() == tab_id) {
      *tab_index = i;
      return true;
    }
  }
  return false;
}
<commit_msg>Refactor index value capture outside of DCHECK to fix build failure in release.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_tabs_module.h"

#include "base/string_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/tab_contents/navigation_entry.h"

// Forward declare static helper functions defined below.
static DictionaryValue* CreateWindowValue(Browser* browser);
static ListValue* CreateTabList(Browser* browser);
static DictionaryValue* CreateTabValue(TabStripModel* tab_strip_model,
                                       int tab_index);
static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
                            int* tab_index);

// ExtensionTabUtil
int ExtensionTabUtil::GetWindowId(const Browser* browser) {
  return browser->session_id().id();
}

int ExtensionTabUtil::GetTabId(const TabContents* tab_contents) {
  return tab_contents->controller().session_id().id();
}

int ExtensionTabUtil::GetWindowIdOfTab(const TabContents* tab_contents) {
  return tab_contents->controller().window_id().id();
}

bool GetWindowsFunction::RunImpl() {
  std::set<int> window_ids;

  // Look for |ids| named parameter as list of id's to fetch.
  if (args_->IsType(Value::TYPE_DICTIONARY)) {
    Value *ids_value;
    if ((!static_cast<DictionaryValue*>(args_)->Get(L"ids", &ids_value)) ||
        (!ids_value->IsType(Value::TYPE_LIST))) {
      DCHECK(false);
      return false;
    }

    ListValue *window_id_list = static_cast<ListValue*>(ids_value);
    for (ListValue::iterator id = window_id_list->begin();
         id != window_id_list->end(); ++id) {
      int window_id;
      if (!(*id)->GetAsInteger(&window_id)) {
        DCHECK(false);
        return false;
      }

      window_ids.insert(window_id);
    }
  }

  // Default to all windows.
  bool all_windows = (window_ids.size() == 0);

  result_.reset(new ListValue());
  for (BrowserList::const_iterator browser = BrowserList::begin();
       browser != BrowserList::end(); ++browser) {
    if (all_windows || (window_ids.find(ExtensionTabUtil::GetWindowId(*browser))
        != window_ids.end())) {
      static_cast<ListValue*>(result_.get())->Append(
        CreateWindowValue(*browser));
    }
  }

  return true;
}

bool GetTabsForWindowFunction::RunImpl() {
  if (!args_->IsType(Value::TYPE_NULL))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  result_.reset(CreateTabList(browser));

  return true;
}

bool CreateTabFunction::RunImpl() {
  // TODO(aa): Do data-driven validation in JS.
  if (!args_->IsType(Value::TYPE_DICTIONARY))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  TabStripModel *tab_strip = browser->tabstrip_model();
  const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);

  // TODO(rafaelw): handle setting remaining tab properties:
  // -windowId
  // -title
  // -favIconUrl

  std::string url;
  args->GetString(L"url", &url);

  // Default to foreground for the new tab. The presence of 'selected' property
  // will override this default.
  bool selected = true;
  args->GetBoolean(L"selected", &selected);

  // If index is specified, honor the value, but keep it bound to
  // 0 <= index <= tab_strip->count()
  int index = -1;
  args->GetInteger(L"index", &index);
  if (index < 0) {
    // Default insert behavior
    index = -1;
  }
  if (index > tab_strip->count()) {
    index = tab_strip->count();
  }

  TabContents* contents = browser->AddTabWithURL(GURL(url), GURL(),
      PageTransition::TYPED, selected, index, NULL);
  index = tab_strip->GetIndexOfTabContents(contents);

  // Return data about the newly created tab.
  if (has_callback())
    result_.reset(CreateTabValue(tab_strip, index));

  return true;
}

bool GetTabFunction::RunImpl() {
  if (!args_->IsType(Value::TYPE_INTEGER))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  args_->GetAsInteger(&tab_id);

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  // TODO(rafaelw): return an error if the tab is not found by |tab_id|
  if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
    return false;

  result_.reset(CreateTabValue(tab_strip, tab_index));
  return true;
}

bool UpdateTabFunction::RunImpl() {
  // TODO(aa): Do data-driven validation in JS.
  if (!args_->IsType(Value::TYPE_DICTIONARY))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
  if (!args->GetInteger(L"id", &tab_id))
    return false;

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  // TODO(rafaelw): return an error if the tab is not found by |tab_id|
  if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
    return false;

  TabContents* tab_contents = tab_strip->GetTabContentsAt(tab_index);
  NavigationController& controller = tab_contents->controller();

  // TODO(rafaelw): handle setting remaining tab properties:
  // -title
  // -favIconUrl

  // Navigate the tab to a new location if the url different.
  std::string url;
  if (args->GetString(L"url", &url)) {
    GURL new_gurl(url);
    if (new_gurl.is_valid()) {
      controller.LoadURL(new_gurl, GURL(), PageTransition::TYPED);
    } else {
      // TODO(rafaelw): return some reasonable error?
    }
  }

  bool selected;
  // TODO(rafaelw): Setting |selected| from js doesn't make much sense.
  // Move tab selection management up to window.
  if (args->GetBoolean(L"selected", &selected) &&
      selected &&
      tab_strip->selected_index() != tab_index) {
    tab_strip->SelectTabContentsAt(tab_index, false);
  }

  return true;
}

bool MoveTabFunction::RunImpl() {
  if (!args_->IsType(Value::TYPE_DICTIONARY))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
  if (!args->GetInteger(L"id", &tab_id))
    return false;

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  // TODO(rafaelw): return an error if the tab is not found by |tab_id|
  if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
    return false;

  // TODO(rafaelw): support moving tabs between windows
  // -windowId

  int new_index;
  bool found_index = args->GetInteger(L"index", &new_index);
  if (!found_index || new_index < 0) {
    DCHECK(false);
    return false;
  }

  // Clamp move location to the last position.
  if (new_index >= tab_strip->count()) {
    new_index = tab_strip->count() - 1;
  }

  if (new_index != tab_index) {
    tab_strip->MoveTabContentsAt(tab_index, new_index, false);
  }

  return true;
}

bool RemoveTabFunction::RunImpl() {
  // TODO(rafaelw): This should have a callback, but it can't because it could
  // close it's own tab.

  if (!args_->IsType(Value::TYPE_INTEGER))
    return false;

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return false;

  int tab_id;
  if (!args_->GetAsInteger(&tab_id)) {
    return false;
  }

  int tab_index;
  TabStripModel* tab_strip = browser->tabstrip_model();
  if (GetIndexOfTabId(tab_strip, tab_id, &tab_index)) {
    browser->CloseContents(tab_strip->GetTabContentsAt(tab_index));
    return true;
  }

  return false;
}

// static helpers
static DictionaryValue* CreateWindowValue(Browser* browser) {
  DictionaryValue* result = new DictionaryValue();
  result->SetInteger(L"id", ExtensionTabUtil::GetWindowId(browser));
  result->SetBoolean(L"focused", browser->window()->IsActive());
  gfx::Rect bounds = browser->window()->GetNormalBounds();

  // TODO(rafaelw): zIndex ?
  result->SetInteger(L"left", bounds.x());
  result->SetInteger(L"top", bounds.y());
  result->SetInteger(L"width", bounds.width());
  result->SetInteger(L"height", bounds.height());

  result->Set(L"tabs", CreateTabList(browser));

  return result;
}

static ListValue* CreateTabList(Browser* browser) {
  ListValue *tab_list = new ListValue();
  TabStripModel* tab_strip = browser->tabstrip_model();
  for (int i = 0; i < tab_strip->count(); ++i) {
    tab_list->Append(CreateTabValue(tab_strip, i));
  }

  return tab_list;
}

static DictionaryValue* CreateTabValue(TabStripModel* tab_strip,
                                       int tab_index) {
  TabContents* contents = tab_strip->GetTabContentsAt(tab_index);

  DictionaryValue* result = new DictionaryValue();
  result->SetInteger(L"id", ExtensionTabUtil::GetTabId(contents));
  result->SetInteger(L"index", tab_index);
  result->SetInteger(L"windowId", ExtensionTabUtil::GetWindowIdOfTab(contents));
  result->SetString(L"url", contents->GetURL().spec());
  result->SetString(L"title", UTF16ToWide(contents->GetTitle()));
  result->SetBoolean(L"selected", tab_index == tab_strip->selected_index());

  NavigationEntry* entry = contents->controller().GetActiveEntry();
  if (entry) {
    if (entry->favicon().is_valid())
      result->SetString(L"favIconUrl", entry->favicon().url().spec());
  }

  return result;
}

static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
                            int* tab_index) {
  for (int i = 0; i < tab_strip->count(); ++i) {
    TabContents* tab_contents = tab_strip->GetTabContentsAt(i);
    if (tab_contents->controller().session_id().id() == tab_id) {
      *tab_index = i;
      return true;
    }
  }
  return false;
}
<|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 "base/logging.h"
#include "base/task.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/sync/glue/data_type_manager_impl.h"

static const int kStartOrderStart = -1;

namespace {

static const syncable::ModelType kStartOrder[] = {
  syncable::BOOKMARKS,
  syncable::PREFERENCES
};

}  // namespace

namespace browser_sync {

DataTypeManagerImpl::DataTypeManagerImpl(
    const DataTypeController::TypeMap& controllers)
    : controllers_(controllers),
      state_(DataTypeManager::STOPPED),
      current_type_(kStartOrderStart) {
  DCHECK(arraysize(kStartOrder) > 0);
  // Ensure all data type controllers are stopped.
  for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
       it != controllers_.end(); ++it) {
    DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state());
  }
}

void DataTypeManagerImpl::Start(StartCallback* start_callback) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  if (state_ != STOPPED) {
    start_callback->Run(BUSY);
    delete start_callback;
    return;
  }

  state_ = STARTING;
  start_callback_.reset(start_callback);
  current_type_ = kStartOrderStart;
  StartNextType();
}

void DataTypeManagerImpl::StartNextType() {
  // Ensure that the current type has indeed started.
  DCHECK(current_type_ == kStartOrderStart ||
         controllers_[kStartOrder[current_type_]]->state() ==
           DataTypeController::RUNNING);

  // Find the next startable type.
  while (current_type_ < static_cast<int>(arraysize(kStartOrder)) - 1) {
    current_type_++;
    syncable::ModelType type = kStartOrder[current_type_];
    if (IsEnabled(type)) {
      LOG(INFO) << "Starting " << controllers_[type]->name();
      controllers_[type]->Start(
          true,
          NewCallback(this, &DataTypeManagerImpl::TypeStartCallback));
      return;
    }
  }

  // No more startable types found, we must be done.
  DCHECK_EQ(state_, STARTING);
  state_ = STARTED;
  start_callback_->Run(OK);
  start_callback_.reset();
}

void DataTypeManagerImpl::TypeStartCallback(
    DataTypeController::StartResult result) {
  // When the data type controller invokes this callback, it must be
  // on the UI thread.
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));

  // If we reach this callback while stopping, this means that the
  // current data type was stopped while still starting up.  Now that
  // the data type is aborted, we can finish stop.
  if (state_ == STOPPING) {
    FinishStop();
    start_callback_->Run(DataTypeManager::ABORTED);
    start_callback_.reset();
    return;
  }

  // If the type started normally, continue to the next type.
  syncable::ModelType type = kStartOrder[current_type_];
  if (result == DataTypeController::OK ||
      result == DataTypeController::OK_FIRST_RUN) {
    LOG(INFO) << "Started " << controllers_[type]->name();
    StartNextType();
    return;
  }

  // Any other result is a fatal error.  Shut down any types we've
  // managed to start up to this point and pass the result to the
  // callback.
  LOG(INFO) << "Failed " << controllers_[type]->name();
  FinishStop();
  StartResult start_result;
  switch(result) {
    case DataTypeController::ABORTED:
      start_result = DataTypeManager::ABORTED;
      break;
    case DataTypeController::ASSOCIATION_FAILED:
      start_result = DataTypeManager::ASSOCIATION_FAILED;
      break;
    default:
      NOTREACHED();
      break;
  }
  start_callback_->Run(start_result);
  start_callback_.reset();
}

void DataTypeManagerImpl::Stop() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  if (state_ == STOPPED)
    return;

  // If we are currently starting, then the current type is in a
  // partially started state.  Abort the startup of the current type
  // and continue shutdown when the abort completes.
  if (state_ == STARTING) {
    state_ = STOPPING;
    syncable::ModelType type = kStartOrder[current_type_];
    controllers_[type]->Stop();
    return;
  }

  state_ = STOPPING;
  FinishStop();
}

void DataTypeManagerImpl::FinishStop() {
  DCHECK(state_== STARTING || state_ == STOPPING);
  // Simply call the Stop() method on all running data types.
  for (unsigned int i = 0; i < arraysize(kStartOrder); ++i) {
    syncable::ModelType type = kStartOrder[i];
    if (IsRegistered(type) &&
        controllers_[type]->state() == DataTypeController::RUNNING) {
      controllers_[type]->Stop();
      LOG(INFO) << "Stopped " << controllers_[type]->name();
    }
  }
  state_ = STOPPED;
}

bool DataTypeManagerImpl::IsRegistered(syncable::ModelType type) {
  return controllers_.count(type) == 1;
}

bool DataTypeManagerImpl::IsEnabled(syncable::ModelType type) {
  return IsRegistered(type) && controllers_[type]->enabled();
}

}  // namespace browser_sync
<commit_msg>Fix mac build bustage<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 "base/logging.h"
#include "base/task.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/sync/glue/data_type_manager_impl.h"

static const int kStartOrderStart = -1;

namespace {

static const syncable::ModelType kStartOrder[] = {
  syncable::BOOKMARKS,
  syncable::PREFERENCES
};

}  // namespace

namespace browser_sync {

DataTypeManagerImpl::DataTypeManagerImpl(
    const DataTypeController::TypeMap& controllers)
    : controllers_(controllers),
      state_(DataTypeManager::STOPPED),
      current_type_(kStartOrderStart) {
  DCHECK(arraysize(kStartOrder) > 0);
  // Ensure all data type controllers are stopped.
  for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
       it != controllers_.end(); ++it) {
    DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state());
  }
}

void DataTypeManagerImpl::Start(StartCallback* start_callback) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  if (state_ != STOPPED) {
    start_callback->Run(BUSY);
    delete start_callback;
    return;
  }

  state_ = STARTING;
  start_callback_.reset(start_callback);
  current_type_ = kStartOrderStart;
  StartNextType();
}

void DataTypeManagerImpl::StartNextType() {
  // Ensure that the current type has indeed started.
  DCHECK(current_type_ == kStartOrderStart ||
         controllers_[kStartOrder[current_type_]]->state() ==
           DataTypeController::RUNNING);

  // Find the next startable type.
  while (current_type_ < static_cast<int>(arraysize(kStartOrder)) - 1) {
    current_type_++;
    syncable::ModelType type = kStartOrder[current_type_];
    if (IsEnabled(type)) {
      LOG(INFO) << "Starting " << controllers_[type]->name();
      controllers_[type]->Start(
          true,
          NewCallback(this, &DataTypeManagerImpl::TypeStartCallback));
      return;
    }
  }

  // No more startable types found, we must be done.
  DCHECK_EQ(state_, STARTING);
  state_ = STARTED;
  start_callback_->Run(OK);
  start_callback_.reset();
}

void DataTypeManagerImpl::TypeStartCallback(
    DataTypeController::StartResult result) {
  // When the data type controller invokes this callback, it must be
  // on the UI thread.
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));

  // If we reach this callback while stopping, this means that the
  // current data type was stopped while still starting up.  Now that
  // the data type is aborted, we can finish stop.
  if (state_ == STOPPING) {
    FinishStop();
    start_callback_->Run(DataTypeManager::ABORTED);
    start_callback_.reset();
    return;
  }

  // If the type started normally, continue to the next type.
  syncable::ModelType type = kStartOrder[current_type_];
  if (result == DataTypeController::OK ||
      result == DataTypeController::OK_FIRST_RUN) {
    LOG(INFO) << "Started " << controllers_[type]->name();
    StartNextType();
    return;
  }

  // Any other result is a fatal error.  Shut down any types we've
  // managed to start up to this point and pass the result to the
  // callback.
  LOG(INFO) << "Failed " << controllers_[type]->name();
  FinishStop();
  StartResult start_result = DataTypeManager::ABORTED;
  switch(result) {
    case DataTypeController::ABORTED:
      start_result = DataTypeManager::ABORTED;
      break;
    case DataTypeController::ASSOCIATION_FAILED:
      start_result = DataTypeManager::ASSOCIATION_FAILED;
      break;
    default:
      NOTREACHED();
      break;
  }
  start_callback_->Run(start_result);
  start_callback_.reset();
}

void DataTypeManagerImpl::Stop() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  if (state_ == STOPPED)
    return;

  // If we are currently starting, then the current type is in a
  // partially started state.  Abort the startup of the current type
  // and continue shutdown when the abort completes.
  if (state_ == STARTING) {
    state_ = STOPPING;
    syncable::ModelType type = kStartOrder[current_type_];
    controllers_[type]->Stop();
    return;
  }

  state_ = STOPPING;
  FinishStop();
}

void DataTypeManagerImpl::FinishStop() {
  DCHECK(state_== STARTING || state_ == STOPPING);
  // Simply call the Stop() method on all running data types.
  for (unsigned int i = 0; i < arraysize(kStartOrder); ++i) {
    syncable::ModelType type = kStartOrder[i];
    if (IsRegistered(type) &&
        controllers_[type]->state() == DataTypeController::RUNNING) {
      controllers_[type]->Stop();
      LOG(INFO) << "Stopped " << controllers_[type]->name();
    }
  }
  state_ = STOPPED;
}

bool DataTypeManagerImpl::IsRegistered(syncable::ModelType type) {
  return controllers_.count(type) == 1;
}

bool DataTypeManagerImpl::IsEnabled(syncable::ModelType type) {
  return IsRegistered(type) && controllers_[type]->enabled();
}

}  // namespace browser_sync
<|endoftext|>


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

#include "chrome/browser/ui/views/avatar_menu_bubble_view.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/profiles/avatar_menu_model.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"
#include "views/controls/button/image_button.h"

namespace {

const int kBubbleViewMinWidth = 175;
const int kBubbleViewMaxWidth = 800;
const int kItemHeight = 32;
const int kItemMarginY = 8;
const int kIconWidth = 38;
const int kIconMarginX = 6;
const int kEditProfileButtonMarginX = 8;

inline int Round(double x) {
  return static_cast<int>(x + 0.5);
}

gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height,
                                   int dst_x, int dst_y,
                                   int dst_width, int dst_height) {
  int scaled_width;
  int scaled_height;
  if (src_width > src_height) {
    scaled_width = std::min(src_width, dst_width);
    float scale = static_cast<float>(scaled_width) /
                  static_cast<float>(src_width);
    scaled_height = Round(src_height * scale);
  } else {
    scaled_height = std::min(src_height, dst_height);
    float scale = static_cast<float>(scaled_height) /
                  static_cast<float>(src_height);
    scaled_width = Round(src_width * scale);
  }
  int x = dst_x + (dst_width - scaled_width) / 2;
  int y = dst_y + (dst_height - scaled_height) / 2;
  return gfx::Rect(x, y, scaled_width, scaled_height);
}

class ProfileItemView : public views::CustomButton {
 public:
  ProfileItemView(const AvatarMenuModel::Item& item,
                  views::ButtonListener* listener)
      : views::CustomButton(listener),
        item_(item) {
  }

  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();

    // Draw the profile icon on the left.
    SkBitmap profile_icon = item_.icon;
    gfx::Rect profile_icon_rect = GetCenteredAndScaledRect(
        profile_icon.width(), profile_icon.height(),
        0, 0, kIconWidth, height());
    canvas->DrawBitmapInt(profile_icon, 0, 0, profile_icon.width(),
                          profile_icon.height(), profile_icon_rect.x(),
                          profile_icon_rect.y(), profile_icon_rect.width(),
                          profile_icon_rect.height(), false);

    // If this profile is selected then draw a check mark on the bottom right
    // of the profile icon.
    if (item_.active) {
      SkBitmap check_icon = rb.GetImageNamed(IDR_PROFILE_SELECTED);
      int y = profile_icon_rect.bottom() - check_icon.height();
      int x = profile_icon_rect.right() - check_icon.width() + 2;
      canvas->DrawBitmapInt(check_icon, 0, 0, check_icon.width(),
                            check_icon.height(), x, y, check_icon.width(),
                            check_icon.height(), false);
    }

    // Draw the profile name to the right of the profile icon.
    int name_x = profile_icon_rect.right() + kIconMarginX;
    canvas->DrawStringInt(item_.name, rb.GetFont(ResourceBundle::BaseFont),
                          GetNameColor(), name_x, 0, width() - name_x,
                          height());
  }

  virtual gfx::Size GetPreferredSize() OVERRIDE {
    gfx::Font font = ResourceBundle::GetSharedInstance().GetFont(
        ResourceBundle::BaseFont);
    int title_width = font.GetStringWidth(item_.name);
    return gfx::Size(kIconWidth + kIconMarginX + title_width, kItemHeight);
  }

 private:
  SkColor GetNameColor() {
    bool normal = state() != views::CustomButton::BS_PUSHED &&
                  state() != views::CustomButton::BS_HOT;
    if (item_.active)
      return normal ? SkColorSetRGB(30, 30, 30) : SkColorSetRGB(0, 0, 0);
    return normal ? SkColorSetRGB(128, 128, 128) : SkColorSetRGB(64, 64, 64);
  }

  AvatarMenuModel::Item item_;
};

} // namespace

class EditProfileButton : public views::ImageButton {
 public:
  EditProfileButton(size_t profile_index, views::ButtonListener* listener)
    : views::ImageButton(listener),
      profile_index_(profile_index) {
  }

  size_t profile_index() {
    return profile_index_;
  }

 private:
  size_t profile_index_;
};

AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser)
    : add_profile_link_(NULL),
      browser_(browser),
      edit_profile_button_(NULL) {
  avatar_menu_model_.reset(new AvatarMenuModel(
      &g_browser_process->profile_manager()->GetProfileInfoCache(),
      this, browser_));
  // Build the menu for the first time.
  OnAvatarMenuModelChanged(avatar_menu_model_.get());
}

AvatarMenuBubbleView::~AvatarMenuBubbleView() {
}

gfx::Size AvatarMenuBubbleView::GetPreferredSize() {
  int max_width = 0;
  int total_height = 0;
  for (size_t i = 0; i < item_views_.size(); ++i) {
    gfx::Size size = item_views_[i]->GetPreferredSize();
    if (i == edit_profile_button_->profile_index()) {
      size.set_width(size.width() +
                     edit_profile_button_->GetPreferredSize().width() +
                     kEditProfileButtonMarginX);
    }

    max_width = std::max(max_width, size.width());
    total_height += size.height() + kItemMarginY;
  }

  gfx::Size add_profile_size = add_profile_link_->GetPreferredSize();
  max_width = std::max(max_width,
                       add_profile_size.width() +  kIconWidth + kIconMarginX);
  total_height += add_profile_link_->GetPreferredSize().height();

  int total_width = std::min(std::max(max_width, kBubbleViewMinWidth),
                             kBubbleViewMaxWidth);
  return gfx::Size(total_width, total_height);
}

void AvatarMenuBubbleView::Layout() {
  int y = 0;
  for (size_t i = 0; i < item_views_.size(); ++i) {
    views::CustomButton* item_view = item_views_[i];
    int item_height = item_view->GetPreferredSize().height();
    int item_width = width();

    if (i == edit_profile_button_->profile_index()) {
      gfx::Size edit_size = edit_profile_button_->GetPreferredSize();
      edit_profile_button_->SetBounds(width() - edit_size.width(), y,
                                      edit_size.width(), item_height);
      item_width -= edit_size.width() + kEditProfileButtonMarginX;
    }

    item_view->SetBounds(0, y, item_width, item_height);
    y += item_height + kItemMarginY;
  }

  add_profile_link_->SetBounds(kIconWidth + kIconMarginX, y, width(),
                               add_profile_link_->GetPreferredSize().height());
}

void AvatarMenuBubbleView::ButtonPressed(views::Button* sender,
                                         const views::Event& event) {
  if (sender == edit_profile_button_) {
    avatar_menu_model_->EditProfile(edit_profile_button_->profile_index());
  } else {
    for (size_t i = 0; i < item_views_.size(); ++i) {
      if (sender == item_views_[i]) {
        avatar_menu_model_->SwitchToProfile(i);
        break;
      }
    }
  }
}

void AvatarMenuBubbleView::LinkClicked(views::Link* source, int event_flags) {
  DCHECK_EQ(source, add_profile_link_);
  avatar_menu_model_->AddNewProfile();
}

void AvatarMenuBubbleView::BubbleClosing(Bubble* bubble,
                                         bool closed_by_escape) {
}

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

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

void AvatarMenuBubbleView::OnAvatarMenuModelChanged(
    AvatarMenuModel* avatar_menu_model) {
  // Unset all our child view references and call RemoveAllChildViews() which
  // will actually delete them.
  add_profile_link_ = NULL;
  edit_profile_button_ = NULL;
  item_views_.clear();
  RemoveAllChildViews(true);

  for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) {
    const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i);
    ProfileItemView* item_view = new ProfileItemView(item, this);
    item_view->SetAccessibleName(l10n_util::GetStringFUTF16(
        IDS_PROFILES_SWITCH_TO_PROFILE_ACCESSIBLE_NAME, item.name));
    AddChildView(item_view);
    item_views_.push_back(item_view);

    if (item.active) {
      DCHECK(!edit_profile_button_);
      edit_profile_button_ = new EditProfileButton(i, this);
      edit_profile_button_->SetAccessibleName(l10n_util::GetStringFUTF16(
          IDS_PROFILES_CUSTOMIZE_PROFILE_ACCESSIBLE_NAME, item.name));
      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
      edit_profile_button_->SetImage(views::CustomButton::BS_NORMAL,
                                     rb.GetImageNamed(IDR_PROFILE_EDIT));
      edit_profile_button_->SetImage(views::CustomButton::BS_HOT,
                                     rb.GetImageNamed(IDR_PROFILE_EDIT_HOVER));
      edit_profile_button_->SetImage(views::CustomButton::BS_PUSHED,
          rb.GetImageNamed(IDR_PROFILE_EDIT_PRESSED));
      edit_profile_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                                              views::ImageButton::ALIGN_MIDDLE);
      AddChildView(edit_profile_button_);
    }
  }

  add_profile_link_ = new views::Link(UTF16ToWide(
      l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)));
  add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  add_profile_link_->SetNormalColor(SkColorSetRGB(0, 0x79, 0xda));
  AddChildView(add_profile_link_);

  PreferredSizeChanged();
}
<commit_msg>Multi-Profiles: Hook up the new user link<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/avatar_menu_bubble_view.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/profiles/avatar_menu_model.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"
#include "views/controls/button/image_button.h"

namespace {

const int kBubbleViewMinWidth = 175;
const int kBubbleViewMaxWidth = 800;
const int kItemHeight = 32;
const int kItemMarginY = 8;
const int kIconWidth = 38;
const int kIconMarginX = 6;
const int kEditProfileButtonMarginX = 8;

inline int Round(double x) {
  return static_cast<int>(x + 0.5);
}

gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height,
                                   int dst_x, int dst_y,
                                   int dst_width, int dst_height) {
  int scaled_width;
  int scaled_height;
  if (src_width > src_height) {
    scaled_width = std::min(src_width, dst_width);
    float scale = static_cast<float>(scaled_width) /
                  static_cast<float>(src_width);
    scaled_height = Round(src_height * scale);
  } else {
    scaled_height = std::min(src_height, dst_height);
    float scale = static_cast<float>(scaled_height) /
                  static_cast<float>(src_height);
    scaled_width = Round(src_width * scale);
  }
  int x = dst_x + (dst_width - scaled_width) / 2;
  int y = dst_y + (dst_height - scaled_height) / 2;
  return gfx::Rect(x, y, scaled_width, scaled_height);
}

class ProfileItemView : public views::CustomButton {
 public:
  ProfileItemView(const AvatarMenuModel::Item& item,
                  views::ButtonListener* listener)
      : views::CustomButton(listener),
        item_(item) {
  }

  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();

    // Draw the profile icon on the left.
    SkBitmap profile_icon = item_.icon;
    gfx::Rect profile_icon_rect = GetCenteredAndScaledRect(
        profile_icon.width(), profile_icon.height(),
        0, 0, kIconWidth, height());
    canvas->DrawBitmapInt(profile_icon, 0, 0, profile_icon.width(),
                          profile_icon.height(), profile_icon_rect.x(),
                          profile_icon_rect.y(), profile_icon_rect.width(),
                          profile_icon_rect.height(), false);

    // If this profile is selected then draw a check mark on the bottom right
    // of the profile icon.
    if (item_.active) {
      SkBitmap check_icon = rb.GetImageNamed(IDR_PROFILE_SELECTED);
      int y = profile_icon_rect.bottom() - check_icon.height();
      int x = profile_icon_rect.right() - check_icon.width() + 2;
      canvas->DrawBitmapInt(check_icon, 0, 0, check_icon.width(),
                            check_icon.height(), x, y, check_icon.width(),
                            check_icon.height(), false);
    }

    // Draw the profile name to the right of the profile icon.
    int name_x = profile_icon_rect.right() + kIconMarginX;
    canvas->DrawStringInt(item_.name, rb.GetFont(ResourceBundle::BaseFont),
                          GetNameColor(), name_x, 0, width() - name_x,
                          height());
  }

  virtual gfx::Size GetPreferredSize() OVERRIDE {
    gfx::Font font = ResourceBundle::GetSharedInstance().GetFont(
        ResourceBundle::BaseFont);
    int title_width = font.GetStringWidth(item_.name);
    return gfx::Size(kIconWidth + kIconMarginX + title_width, kItemHeight);
  }

 private:
  SkColor GetNameColor() {
    bool normal = state() != views::CustomButton::BS_PUSHED &&
                  state() != views::CustomButton::BS_HOT;
    if (item_.active)
      return normal ? SkColorSetRGB(30, 30, 30) : SkColorSetRGB(0, 0, 0);
    return normal ? SkColorSetRGB(128, 128, 128) : SkColorSetRGB(64, 64, 64);
  }

  AvatarMenuModel::Item item_;
};

} // namespace

class EditProfileButton : public views::ImageButton {
 public:
  EditProfileButton(size_t profile_index, views::ButtonListener* listener)
    : views::ImageButton(listener),
      profile_index_(profile_index) {
  }

  size_t profile_index() {
    return profile_index_;
  }

 private:
  size_t profile_index_;
};

AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser)
    : add_profile_link_(NULL),
      browser_(browser),
      edit_profile_button_(NULL) {
  avatar_menu_model_.reset(new AvatarMenuModel(
      &g_browser_process->profile_manager()->GetProfileInfoCache(),
      this, browser_));
  // Build the menu for the first time.
  OnAvatarMenuModelChanged(avatar_menu_model_.get());
}

AvatarMenuBubbleView::~AvatarMenuBubbleView() {
}

gfx::Size AvatarMenuBubbleView::GetPreferredSize() {
  int max_width = 0;
  int total_height = 0;
  for (size_t i = 0; i < item_views_.size(); ++i) {
    gfx::Size size = item_views_[i]->GetPreferredSize();
    if (i == edit_profile_button_->profile_index()) {
      size.set_width(size.width() +
                     edit_profile_button_->GetPreferredSize().width() +
                     kEditProfileButtonMarginX);
    }

    max_width = std::max(max_width, size.width());
    total_height += size.height() + kItemMarginY;
  }

  gfx::Size add_profile_size = add_profile_link_->GetPreferredSize();
  max_width = std::max(max_width,
                       add_profile_size.width() +  kIconWidth + kIconMarginX);
  total_height += add_profile_link_->GetPreferredSize().height();

  int total_width = std::min(std::max(max_width, kBubbleViewMinWidth),
                             kBubbleViewMaxWidth);
  return gfx::Size(total_width, total_height);
}

void AvatarMenuBubbleView::Layout() {
  int y = 0;
  for (size_t i = 0; i < item_views_.size(); ++i) {
    views::CustomButton* item_view = item_views_[i];
    int item_height = item_view->GetPreferredSize().height();
    int item_width = width();

    if (i == edit_profile_button_->profile_index()) {
      gfx::Size edit_size = edit_profile_button_->GetPreferredSize();
      edit_profile_button_->SetBounds(width() - edit_size.width(), y,
                                      edit_size.width(), item_height);
      item_width -= edit_size.width() + kEditProfileButtonMarginX;
    }

    item_view->SetBounds(0, y, item_width, item_height);
    y += item_height + kItemMarginY;
  }

  add_profile_link_->SetBounds(kIconWidth + kIconMarginX, y, width(),
                               add_profile_link_->GetPreferredSize().height());
}

void AvatarMenuBubbleView::ButtonPressed(views::Button* sender,
                                         const views::Event& event) {
  if (sender == edit_profile_button_) {
    avatar_menu_model_->EditProfile(edit_profile_button_->profile_index());
  } else {
    for (size_t i = 0; i < item_views_.size(); ++i) {
      if (sender == item_views_[i]) {
        avatar_menu_model_->SwitchToProfile(i);
        break;
      }
    }
  }
}

void AvatarMenuBubbleView::LinkClicked(views::Link* source, int event_flags) {
  DCHECK_EQ(source, add_profile_link_);
  avatar_menu_model_->AddNewProfile();
}

void AvatarMenuBubbleView::BubbleClosing(Bubble* bubble,
                                         bool closed_by_escape) {
}

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

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

void AvatarMenuBubbleView::OnAvatarMenuModelChanged(
    AvatarMenuModel* avatar_menu_model) {
  // Unset all our child view references and call RemoveAllChildViews() which
  // will actually delete them.
  add_profile_link_ = NULL;
  edit_profile_button_ = NULL;
  item_views_.clear();
  RemoveAllChildViews(true);

  for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) {
    const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i);
    ProfileItemView* item_view = new ProfileItemView(item, this);
    item_view->SetAccessibleName(l10n_util::GetStringFUTF16(
        IDS_PROFILES_SWITCH_TO_PROFILE_ACCESSIBLE_NAME, item.name));
    AddChildView(item_view);
    item_views_.push_back(item_view);

    if (item.active) {
      DCHECK(!edit_profile_button_);
      edit_profile_button_ = new EditProfileButton(i, this);
      edit_profile_button_->SetAccessibleName(l10n_util::GetStringFUTF16(
          IDS_PROFILES_CUSTOMIZE_PROFILE_ACCESSIBLE_NAME, item.name));
      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
      edit_profile_button_->SetImage(views::CustomButton::BS_NORMAL,
                                     rb.GetImageNamed(IDR_PROFILE_EDIT));
      edit_profile_button_->SetImage(views::CustomButton::BS_HOT,
                                     rb.GetImageNamed(IDR_PROFILE_EDIT_HOVER));
      edit_profile_button_->SetImage(views::CustomButton::BS_PUSHED,
          rb.GetImageNamed(IDR_PROFILE_EDIT_PRESSED));
      edit_profile_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                                              views::ImageButton::ALIGN_MIDDLE);
      AddChildView(edit_profile_button_);
    }
  }

  add_profile_link_ = new views::Link(UTF16ToWide(
      l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)));
  add_profile_link_->set_listener(this);
  add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  add_profile_link_->SetNormalColor(SkColorSetRGB(0, 0x79, 0xda));
  AddChildView(add_profile_link_);

  PreferredSizeChanged();
}
<|endoftext|>


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

#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/views/bookmark_context_menu.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/browser/tab_contents/page_navigator.h"
#include "chrome/test/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

#if defined(OS_WIN)
#include "chrome/browser/views/bookmark_bar_view.h"
#endif

namespace {

// PageNavigator implementation that records the URL.
class TestingPageNavigator : public PageNavigator {
 public:
  virtual void OpenURL(const GURL& url,
                       const GURL& referrer,
                       WindowOpenDisposition disposition,
                       PageTransition::Type transition) {
    urls_.push_back(url);
  }

  std::vector<GURL> urls_;
};

}  // namespace

class BookmarkContextMenuTest : public testing::Test {
 public:
  BookmarkContextMenuTest()
      : ui_thread_(ChromeThread::UI, &message_loop_),
        file_thread_(ChromeThread::FILE, &message_loop_),
        model_(NULL) {
  }

  virtual void SetUp() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = true;
#endif

    profile_.reset(new TestingProfile());
    profile_->set_has_history_service(true);
    profile_->CreateBookmarkModel(true);
    profile_->BlockUntilBookmarkModelLoaded();

    model_ = profile_->GetBookmarkModel();

    AddTestData();
  }

  virtual void TearDown() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = false;
#endif

    // Flush the message loop to make Purify happy.
    message_loop_.RunAllPending();
  }

 protected:
  MessageLoopForUI message_loop_;
  ChromeThread ui_thread_;
  ChromeThread file_thread_;
  scoped_ptr<TestingProfile> profile_;
  BookmarkModel* model_;
  TestingPageNavigator navigator_;

 private:
  // Creates the following structure:
  // a
  // F1
  //  f1a
  //  F11
  //   f11a
  // F2
  // F3
  // F4
  //   f4a
  void AddTestData() {
    std::string test_base = "file:///c:/tmp/";

    model_->AddURL(model_->GetBookmarkBarNode(), 0, L"a",
                   GURL(test_base + "a"));
    const BookmarkNode* f1 =
        model_->AddGroup(model_->GetBookmarkBarNode(), 1, L"F1");
    model_->AddURL(f1, 0, L"f1a", GURL(test_base + "f1a"));
    const BookmarkNode* f11 = model_->AddGroup(f1, 1, L"F11");
    model_->AddURL(f11, 0, L"f11a", GURL(test_base + "f11a"));
    model_->AddGroup(model_->GetBookmarkBarNode(), 2, L"F2");
    model_->AddGroup(model_->GetBookmarkBarNode(), 3, L"F3");
    const BookmarkNode* f4 =
        model_->AddGroup(model_->GetBookmarkBarNode(), 4, L"F4");
    model_->AddURL(f4, 0, L"f4a", GURL(test_base + "f4a"));
  }
};

// Tests Deleting from the menu.
TEST_F(BookmarkContextMenuTest, DeleteURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR);
  GURL url = model_->GetBookmarkBarNode()->GetChild(0)->GetURL();
  ASSERT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  // Delete the URL.
  controller.ExecuteCommand(IDS_BOOKMARK_BAR_REMOVE);
  // Model shouldn't have URL anymore.
  ASSERT_FALSE(model_->IsBookmarked(url));
}

// Tests open all on a folder with a couple of bookmarks.
TEST_F(BookmarkContextMenuTest, OpenAll) {
  const BookmarkNode* folder = model_->GetBookmarkBarNode()->GetChild(1);
  bookmark_utils::OpenAll(
      NULL, profile_.get(), &navigator_, folder, NEW_FOREGROUND_TAB);

  // Should have navigated to F1's children.
  ASSERT_EQ(static_cast<size_t>(2), navigator_.urls_.size());
  ASSERT_TRUE(folder->GetChild(0)->GetURL() == navigator_.urls_[0]);
  ASSERT_TRUE(folder->GetChild(1)->GetChild(0)->GetURL() ==
              navigator_.urls_[1]);
}

// Tests the enabled state of the menus when supplied an empty vector.
TEST_F(BookmarkContextMenuTest, EmptyNodes) {
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, model_->other_node(),
      std::vector<const BookmarkNode*>(),
      BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with a single
// url.
TEST_F(BookmarkContextMenuTest, SingleURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// urls.
TEST_F(BookmarkContextMenuTest, MultipleURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(1)->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied an vector with a single
// folder.
TEST_F(BookmarkContextMenuTest, SingleFolder) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(2));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, all of which are empty.
TEST_F(BookmarkContextMenuTest, MultipleEmptyFolders) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(2));
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(3));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, some of which contain URLs.
TEST_F(BookmarkContextMenuTest, MultipleFoldersWithURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(3));
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(4));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of open incognito.
TEST_F(BookmarkContextMenuTest, DisableIncognito) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  profile_->set_off_the_record(true);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
}

// Tests that you can't remove/edit when showing the other node.
TEST_F(BookmarkContextMenuTest, DisabledItemsWithOtherNode) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->other_node());
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0], nodes,
      BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_EDIT));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
}

// Tests the enabled state of the menus when supplied an empty vector and null
// parent.
TEST_F(BookmarkContextMenuTest, EmptyNodesNullParent) {
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, NULL, std::vector<const BookmarkNode*>(),
      BookmarkContextMenuController::BOOKMARK_MANAGER_ORGANIZE_MENU);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

TEST_F(BookmarkContextMenuTest, CutCopyPasteNode) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  BookmarkContextMenu* controller = new BookmarkContextMenu(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_TRUE(controller->IsCommandEnabled(IDS_COPY));
  EXPECT_TRUE(controller->IsCommandEnabled(IDS_CUT));

  // Copy the URL.
  controller->ExecuteCommand(IDS_COPY);

  controller = new BookmarkContextMenu(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR);
  int old_count = model_->GetBookmarkBarNode()->GetChildCount();
  controller->ExecuteCommand(IDS_PASTE);

  ASSERT_TRUE(model_->GetBookmarkBarNode()->GetChild(1)->is_url());
  ASSERT_EQ(old_count + 1, model_->GetBookmarkBarNode()->GetChildCount());
  ASSERT_EQ(model_->GetBookmarkBarNode()->GetChild(0)->GetURL(),
            model_->GetBookmarkBarNode()->GetChild(1)->GetURL());

  controller = new BookmarkContextMenu(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR);
  // Cut the URL.
  controller->ExecuteCommand(IDS_CUT);
  ASSERT_TRUE(model_->GetBookmarkBarNode()->GetChild(0)->is_url());
  ASSERT_TRUE(model_->GetBookmarkBarNode()->GetChild(1)->is_folder());
  ASSERT_EQ(old_count, model_->GetBookmarkBarNode()->GetChildCount());

  delete controller;
}

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

#include "base/scoped_ptr.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/views/bookmark_context_menu.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/browser/tab_contents/page_navigator.h"
#include "chrome/test/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

#if defined(OS_WIN)
#include "chrome/browser/views/bookmark_bar_view.h"
#endif

namespace {

// PageNavigator implementation that records the URL.
class TestingPageNavigator : public PageNavigator {
 public:
  virtual void OpenURL(const GURL& url,
                       const GURL& referrer,
                       WindowOpenDisposition disposition,
                       PageTransition::Type transition) {
    urls_.push_back(url);
  }

  std::vector<GURL> urls_;
};

}  // namespace

class BookmarkContextMenuTest : public testing::Test {
 public:
  BookmarkContextMenuTest()
      : ui_thread_(ChromeThread::UI, &message_loop_),
        file_thread_(ChromeThread::FILE, &message_loop_),
        model_(NULL) {
  }

  virtual void SetUp() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = true;
#endif

    profile_.reset(new TestingProfile());
    profile_->set_has_history_service(true);
    profile_->CreateBookmarkModel(true);
    profile_->BlockUntilBookmarkModelLoaded();

    model_ = profile_->GetBookmarkModel();

    AddTestData();
  }

  virtual void TearDown() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = false;
#endif

    // Flush the message loop to make Purify happy.
    message_loop_.RunAllPending();
  }

 protected:
  MessageLoopForUI message_loop_;
  ChromeThread ui_thread_;
  ChromeThread file_thread_;
  scoped_ptr<TestingProfile> profile_;
  BookmarkModel* model_;
  TestingPageNavigator navigator_;

 private:
  // Creates the following structure:
  // a
  // F1
  //  f1a
  //  F11
  //   f11a
  // F2
  // F3
  // F4
  //   f4a
  void AddTestData() {
    std::string test_base = "file:///c:/tmp/";

    model_->AddURL(model_->GetBookmarkBarNode(), 0, L"a",
                   GURL(test_base + "a"));
    const BookmarkNode* f1 =
        model_->AddGroup(model_->GetBookmarkBarNode(), 1, L"F1");
    model_->AddURL(f1, 0, L"f1a", GURL(test_base + "f1a"));
    const BookmarkNode* f11 = model_->AddGroup(f1, 1, L"F11");
    model_->AddURL(f11, 0, L"f11a", GURL(test_base + "f11a"));
    model_->AddGroup(model_->GetBookmarkBarNode(), 2, L"F2");
    model_->AddGroup(model_->GetBookmarkBarNode(), 3, L"F3");
    const BookmarkNode* f4 =
        model_->AddGroup(model_->GetBookmarkBarNode(), 4, L"F4");
    model_->AddURL(f4, 0, L"f4a", GURL(test_base + "f4a"));
  }
};

// Tests Deleting from the menu.
TEST_F(BookmarkContextMenuTest, DeleteURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR);
  GURL url = model_->GetBookmarkBarNode()->GetChild(0)->GetURL();
  ASSERT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  // Delete the URL.
  controller.ExecuteCommand(IDS_BOOKMARK_BAR_REMOVE);
  // Model shouldn't have URL anymore.
  ASSERT_FALSE(model_->IsBookmarked(url));
}

// Tests open all on a folder with a couple of bookmarks.
TEST_F(BookmarkContextMenuTest, OpenAll) {
  const BookmarkNode* folder = model_->GetBookmarkBarNode()->GetChild(1);
  bookmark_utils::OpenAll(
      NULL, profile_.get(), &navigator_, folder, NEW_FOREGROUND_TAB);

  // Should have navigated to F1's children.
  ASSERT_EQ(static_cast<size_t>(2), navigator_.urls_.size());
  ASSERT_TRUE(folder->GetChild(0)->GetURL() == navigator_.urls_[0]);
  ASSERT_TRUE(folder->GetChild(1)->GetChild(0)->GetURL() ==
              navigator_.urls_[1]);
}

// Tests the enabled state of the menus when supplied an empty vector.
TEST_F(BookmarkContextMenuTest, EmptyNodes) {
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, model_->other_node(),
      std::vector<const BookmarkNode*>(),
      BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with a single
// url.
TEST_F(BookmarkContextMenuTest, SingleURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// urls.
TEST_F(BookmarkContextMenuTest, MultipleURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(1)->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied an vector with a single
// folder.
TEST_F(BookmarkContextMenuTest, SingleFolder) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(2));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, all of which are empty.
TEST_F(BookmarkContextMenuTest, MultipleEmptyFolders) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(2));
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(3));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, some of which contain URLs.
TEST_F(BookmarkContextMenuTest, MultipleFoldersWithURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(3));
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(4));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of open incognito.
TEST_F(BookmarkContextMenuTest, DisableIncognito) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(),
      nodes, BookmarkContextMenuController::BOOKMARK_BAR);
  profile_->set_off_the_record(true);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
}

// Tests that you can't remove/edit when showing the other node.
TEST_F(BookmarkContextMenuTest, DisabledItemsWithOtherNode) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->other_node());
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, nodes[0], nodes,
      BookmarkContextMenuController::BOOKMARK_BAR);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_EDIT));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
}

// Tests the enabled state of the menus when supplied an empty vector and null
// parent.
TEST_F(BookmarkContextMenuTest, EmptyNodesNullParent) {
  BookmarkContextMenu controller(
      NULL, profile_.get(), NULL, NULL, std::vector<const BookmarkNode*>(),
      BookmarkContextMenuController::BOOKMARK_MANAGER_ORGANIZE_MENU);
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_FALSE(
      controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER));
}

TEST_F(BookmarkContextMenuTest, CutCopyPasteNode) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0));
  scoped_ptr<BookmarkContextMenu> controller(new BookmarkContextMenu(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR));
  EXPECT_TRUE(controller->IsCommandEnabled(IDS_COPY));
  EXPECT_TRUE(controller->IsCommandEnabled(IDS_CUT));

  // Copy the URL.
  controller->ExecuteCommand(IDS_COPY);

  controller.reset(new BookmarkContextMenu(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR));
  int old_count = model_->GetBookmarkBarNode()->GetChildCount();
  controller->ExecuteCommand(IDS_PASTE);

  ASSERT_TRUE(model_->GetBookmarkBarNode()->GetChild(1)->is_url());
  ASSERT_EQ(old_count + 1, model_->GetBookmarkBarNode()->GetChildCount());
  ASSERT_EQ(model_->GetBookmarkBarNode()->GetChild(0)->GetURL(),
            model_->GetBookmarkBarNode()->GetChild(1)->GetURL());

  controller.reset(new BookmarkContextMenu(
      NULL, profile_.get(), NULL, nodes[0]->GetParent(), nodes,
      BookmarkContextMenuController::BOOKMARK_BAR));
  // Cut the URL.
  controller->ExecuteCommand(IDS_CUT);
  ASSERT_TRUE(model_->GetBookmarkBarNode()->GetChild(0)->is_url());
  ASSERT_TRUE(model_->GetBookmarkBarNode()->GetChild(1)->is_folder());
  ASSERT_EQ(old_count, model_->GetBookmarkBarNode()->GetChildCount());
}

<|endoftext|>


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

#include "chrome/test/interactive_ui/view_event_test_base.h"

#include "base/message_loop.h"
#include "chrome/browser/automation/ui_controls.h"
#include "chrome/views/view.h"
#include "chrome/views/window.h"

namespace {

// View subclass that allows you to specify the preferred size.
class TestView : public views::View {
 public:
  TestView() {}

  void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }
  gfx::Size GetPreferredSize() {
    if (!preferred_size_.IsEmpty())
      return preferred_size_;
    return View::GetPreferredSize();
  }

  virtual void Layout() {
    View* child_view = GetChildViewAt(0);
    child_view->SetBounds(0, 0, width(), height());
  }

 private:
  gfx::Size preferred_size_;

  DISALLOW_COPY_AND_ASSIGN(TestView);
};

// Delay in background thread before posting mouse move.
const int kMouseMoveDelayMS = 200;

}  // namespace

// static
void ViewEventTestBase::Done() {
  MessageLoop::current()->Quit();
  // If we're in a nested message loop, as is the case with menus, we need
  // to quit twice. The second quit does that for us.
  MessageLoop::current()->PostDelayedTask(
      FROM_HERE, new MessageLoop::QuitTask(), 0);
}

ViewEventTestBase::ViewEventTestBase() : window_(NULL), content_view_(NULL) { }

void ViewEventTestBase::SetUp() {
  OleInitialize(NULL);
  window_ = views::Window::CreateChromeWindow(NULL, gfx::Rect(), this);
}

void ViewEventTestBase::TearDown() {
  if (window_) {
    DestroyWindow(window_->GetNativeWindow());
    window_ = NULL;
  }
  OleUninitialize();
}

views::View* ViewEventTestBase::GetContentsView() {
  if (!content_view_) {
    // Wrap the real view (as returned by CreateContentsView) in a View so
    // that we can customize the preferred size.
    TestView* test_view = new TestView();
    test_view->set_preferred_size(GetPreferredSize());
    test_view->AddChildView(CreateContentsView());
    content_view_ = test_view;
  }
  return content_view_;
}

void ViewEventTestBase::StartMessageLoopAndRunTest() {
  window_->Show();
  // Make sure the window is the foreground window, otherwise none of the
  // mouse events are going to be targeted correctly.
  SetForegroundWindow(window_->GetNativeWindow());

  // Flush any pending events to make sure we start with a clean slate.
  MessageLoop::current()->RunAllPending();

  // Schedule a task that starts the test. Need to do this as we're going to
  // run the message loop.
  MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      NewRunnableMethod(this, &ViewEventTestBase::DoTestOnMessageLoop), 0);

  MessageLoop::current()->Run();
}

gfx::Size ViewEventTestBase::GetPreferredSize() {
  return gfx::Size();
}

void ViewEventTestBase::ScheduleMouseMoveInBackground(int x, int y) {
  if (!dnd_thread_.get()) {
    dnd_thread_.reset(new base::Thread("mouse-move-thread"));
    dnd_thread_->Start();
  }
  dnd_thread_->message_loop()->PostDelayedTask(
      FROM_HERE, NewRunnableFunction(&ui_controls::SendMouseMove, x, y),
      kMouseMoveDelayMS);
}

void ViewEventTestBase::StopBackgroundThread() {
  dnd_thread_.reset(NULL);
}

void ViewEventTestBase::RunTestMethod(Task* task) {
  StopBackgroundThread();

  scoped_ptr<Task> task_deleter(task);
  task->Run();
  if (HasFatalFailure())
    Done();
}
<commit_msg>fix bustage - file moved<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/interactive_ui/view_event_test_base.h"

#include "base/message_loop.h"
#include "chrome/browser/automation/ui_controls.h"
#include "chrome/views/view.h"
#include "chrome/views/window/window.h"

namespace {

// View subclass that allows you to specify the preferred size.
class TestView : public views::View {
 public:
  TestView() {}

  void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }
  gfx::Size GetPreferredSize() {
    if (!preferred_size_.IsEmpty())
      return preferred_size_;
    return View::GetPreferredSize();
  }

  virtual void Layout() {
    View* child_view = GetChildViewAt(0);
    child_view->SetBounds(0, 0, width(), height());
  }

 private:
  gfx::Size preferred_size_;

  DISALLOW_COPY_AND_ASSIGN(TestView);
};

// Delay in background thread before posting mouse move.
const int kMouseMoveDelayMS = 200;

}  // namespace

// static
void ViewEventTestBase::Done() {
  MessageLoop::current()->Quit();
  // If we're in a nested message loop, as is the case with menus, we need
  // to quit twice. The second quit does that for us.
  MessageLoop::current()->PostDelayedTask(
      FROM_HERE, new MessageLoop::QuitTask(), 0);
}

ViewEventTestBase::ViewEventTestBase() : window_(NULL), content_view_(NULL) { }

void ViewEventTestBase::SetUp() {
  OleInitialize(NULL);
  window_ = views::Window::CreateChromeWindow(NULL, gfx::Rect(), this);
}

void ViewEventTestBase::TearDown() {
  if (window_) {
    DestroyWindow(window_->GetNativeWindow());
    window_ = NULL;
  }
  OleUninitialize();
}

views::View* ViewEventTestBase::GetContentsView() {
  if (!content_view_) {
    // Wrap the real view (as returned by CreateContentsView) in a View so
    // that we can customize the preferred size.
    TestView* test_view = new TestView();
    test_view->set_preferred_size(GetPreferredSize());
    test_view->AddChildView(CreateContentsView());
    content_view_ = test_view;
  }
  return content_view_;
}

void ViewEventTestBase::StartMessageLoopAndRunTest() {
  window_->Show();
  // Make sure the window is the foreground window, otherwise none of the
  // mouse events are going to be targeted correctly.
  SetForegroundWindow(window_->GetNativeWindow());

  // Flush any pending events to make sure we start with a clean slate.
  MessageLoop::current()->RunAllPending();

  // Schedule a task that starts the test. Need to do this as we're going to
  // run the message loop.
  MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      NewRunnableMethod(this, &ViewEventTestBase::DoTestOnMessageLoop), 0);

  MessageLoop::current()->Run();
}

gfx::Size ViewEventTestBase::GetPreferredSize() {
  return gfx::Size();
}

void ViewEventTestBase::ScheduleMouseMoveInBackground(int x, int y) {
  if (!dnd_thread_.get()) {
    dnd_thread_.reset(new base::Thread("mouse-move-thread"));
    dnd_thread_->Start();
  }
  dnd_thread_->message_loop()->PostDelayedTask(
      FROM_HERE, NewRunnableFunction(&ui_controls::SendMouseMove, x, y),
      kMouseMoveDelayMS);
}

void ViewEventTestBase::StopBackgroundThread() {
  dnd_thread_.reset(NULL);
}

void ViewEventTestBase::RunTestMethod(Task* task) {
  StopBackgroundThread();

  scoped_ptr<Task> task_deleter(task);
  task->Run();
  if (HasFatalFailure())
    Done();
}
<|endoftext|>


<commit_before>#pragma once

#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <vector>

#include "core/utils/log.h"

class ThreadPool {
private:
    // Thread safe implementation of a Queue using a std::queue
    template <typename T> class SafeQueue {
    private:
        std::queue<T> m_queue;
        std::mutex m_mutex;

    public:
        SafeQueue() {}
        ~SafeQueue() {}

        bool empty() {
            std::unique_lock<std::mutex> lock(m_mutex);
            return m_queue.empty();
        }

        int size() {
            std::unique_lock<std::mutex> lock(m_mutex);
            return m_queue.size();
        }

        void enqueue(T& t) {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_queue.push(t);
        }

        bool dequeue(T& t) {
            std::unique_lock<std::mutex> lock(m_mutex);
            if(m_queue.empty()) {
                return false;
            }
            t = std::move(m_queue.front());
            m_queue.pop();
            return true;
        }
    };

    class ThreadWorker {
    private:
        unsigned int m_id;
        ThreadPool* m_pool;

    public:
        ThreadWorker(ThreadPool* pool, const unsigned int id, allpix::LogLevel log_level) : m_id(id), m_pool(pool) {
            // Set logging level
            allpix::Log::setReportingLevel(log_level);
        }
        void operator()() {
            std::function<void()> func;
            bool dequeued;
            while(!m_pool->m_shutdown) {
                {
                    std::unique_lock<std::mutex> lock(m_pool->m_conditional_mutex);
                    if(m_pool->m_queue.empty()) {
                        m_pool->m_conditional_lock.wait(lock);
                    }
                    dequeued = m_pool->m_queue.dequeue(func);
                }
                if(dequeued) {
                    func();
                }
            }
        }
    };

    bool m_shutdown;
    SafeQueue<std::function<void()>> m_queue;
    std::vector<std::thread> m_threads;
    std::mutex m_conditional_mutex;
    std::condition_variable m_conditional_lock;

public:
    ThreadPool(const unsigned int n_threads, allpix::LogLevel log_level)
        : m_shutdown(false), m_threads(std::vector<std::thread>(n_threads)) {
        for(unsigned int i = 0; i < m_threads.size(); ++i) {
            m_threads[i] = std::thread(ThreadWorker(this, i, log_level));
        }
    }

    ThreadPool(const ThreadPool&) = delete;
    ThreadPool(ThreadPool&&) = delete;

    ThreadPool& operator=(const ThreadPool&) = delete;
    ThreadPool& operator=(ThreadPool&&) = delete;

    // Waits until threads finish their current task and shutdowns the pool
    void shutdown() {
        m_shutdown = true;
        m_conditional_lock.notify_all();

        for(unsigned int i = 0; i < m_threads.size(); ++i) {
            if(m_threads[i].joinable()) {
                m_threads[i].join();
            }
        }
    }

    // Submit a function to be executed asynchronously by the pool
    template <typename F, typename... Args> auto submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
        // Create a function with bounded parameters ready to execute
        std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        // Encapsulate it into a shared ptr in order to be able to copy construct / assign
        auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);

        // Wrap packaged task into void function
        std::function<void()> wrapper_func = [task_ptr]() { (*task_ptr)(); };

        // Enqueue generic wrapper function
        m_queue.enqueue(wrapper_func);

        // Wake up one thread if its waiting
        m_conditional_lock.notify_one();

        // Return future from promise
        return task_ptr->get_future();
    }
};
<commit_msg>MeshConverter thread pool: fix linting corrections<commit_after>#pragma once

#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <vector>

#include "core/utils/log.h"

class ThreadPool {
private:
    // Thread safe implementation of a Queue using a std::queue
    template <typename T> class SafeQueue {
    private:
        std::queue<T> m_queue;
        std::mutex m_mutex;

    public:
        SafeQueue() = default;
        ~SafeQueue() = default;

        bool empty() {
            std::unique_lock<std::mutex> lock(m_mutex);
            return m_queue.empty();
        }

        int size() {
            std::unique_lock<std::mutex> lock(m_mutex);
            return m_queue.size();
        }

        void enqueue(T& t) {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_queue.push(t);
        }

        bool dequeue(T& t) {
            std::unique_lock<std::mutex> lock(m_mutex);
            if(m_queue.empty()) {
                return false;
            }
            t = std::move(m_queue.front());
            m_queue.pop();
            return true;
        }
    };

    class ThreadWorker {
    private:
        unsigned int m_id;
        ThreadPool* m_pool;

    public:
        ThreadWorker(ThreadPool* pool, const unsigned int id, allpix::LogLevel log_level) : m_id(id), m_pool(pool) {
            // Set logging level
            allpix::Log::setReportingLevel(log_level);
        }
        void operator()() {
            std::function<void()> func;
            bool dequeued;
            while(!m_pool->m_shutdown) {
                {
                    std::unique_lock<std::mutex> lock(m_pool->m_conditional_mutex);
                    if(m_pool->m_queue.empty()) {
                        m_pool->m_conditional_lock.wait(lock);
                    }
                    dequeued = m_pool->m_queue.dequeue(func);
                }
                if(dequeued) {
                    func();
                }
            }
        }
    };

    bool m_shutdown;
    SafeQueue<std::function<void()>> m_queue;
    std::vector<std::thread> m_threads;
    std::mutex m_conditional_mutex;
    std::condition_variable m_conditional_lock;

public:
    ThreadPool(const unsigned int n_threads, allpix::LogLevel log_level)
        : m_shutdown(false), m_threads(std::vector<std::thread>(n_threads)) {
        for(unsigned int i = 0; i < m_threads.size(); ++i) {
            m_threads[i] = std::thread(ThreadWorker(this, i, log_level));
        }
    }

    ThreadPool(const ThreadPool&) = delete;
    ThreadPool(ThreadPool&&) = delete;

    ThreadPool& operator=(const ThreadPool&) = delete;
    ThreadPool& operator=(ThreadPool&&) = delete;

    // Waits until threads finish their current task and shutdowns the pool
    void shutdown() {
        m_shutdown = true;
        m_conditional_lock.notify_all();

        for(auto& thrd : m_threads) {
            if(thrd.joinable()) {
                thrd.join();
            }
        }
    }

    // Submit a function to be executed asynchronously by the pool
    template <typename F, typename... Args> auto submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
        // Create a function with bounded parameters ready to execute
        std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        // Encapsulate it into a shared ptr in order to be able to copy construct / assign
        auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);

        // Wrap packaged task into void function
        std::function<void()> wrapper_func = [task_ptr]() { (*task_ptr)(); };

        // Enqueue generic wrapper function
        m_queue.enqueue(wrapper_func);

        // Wake up one thread if its waiting
        m_conditional_lock.notify_one();

        // Return future from promise
        return task_ptr->get_future();
    }
};
<|endoftext|>