<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/autofill/credit_card_field.h"

#include "base/string16.h"
#include "chrome/browser/autofill/autofill_field.h"

bool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const {
  return false;
}

// static
CreditCardField* CreditCardField::Parse(
    std::vector<AutoFillField*>::const_iterator* iter,
    bool is_ecml) {
  CreditCardField credit_card_field;
  std::vector<AutoFillField*>::const_iterator q = *iter;
  string16 pattern;

  // Credit card fields can appear in many different orders.
  for (int fields = 0; q != *iter; ++fields) {
    // Sometimes the cardholder field is just labeled "name" (e.g. on test page
    // Starbucks - Credit card.html).  Unfortunately this is a dangerously
    // generic word to search for, since it will often match a name (not
    // cardholder name) field before or after credit card fields.  So we search
    // for "name" only when we've already parsed at least one other credit card
    // field and haven't yet parsed the expiration date (which usually appears
    // at the end).
    if (credit_card_field.cardholder_ == NULL) {
      string16 name_pattern;
      if (is_ecml) {
        name_pattern = GetEcmlPattern(kEcmlCardHolder);
      } else {
        if (fields == 0 || credit_card_field.expiration_month_) {
          // at beginning or end
          name_pattern = ASCIIToUTF16("card holder|name on card");
        } else {
          name_pattern = ASCIIToUTF16("name");
        }
      }

      if (ParseText(&q, name_pattern, &credit_card_field.cardholder_)) {
        continue;
      }

      // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html
      // and ExpediaBilling.html in our test suite), recognize separate fields
      // for the cardholder's first and last name if they have the labels "cfnm"
      // and "clnm".
      std::vector<AutoFillField*>::const_iterator p = q;
      AutoFillField* first;
      if (!is_ecml && ParseText(&p, ASCIIToUTF16("^cfnm"), &first) &&
          ParseText(&p, ASCIIToUTF16("^clnm"),
                    &credit_card_field.cardholder_last_)) {
        credit_card_field.cardholder_ = first;
        q = p;
        continue;
      }
    }

    // TODO(jhawkins): Parse the type select control.

    // We look for a card security code before we look for a credit card number
    // and match the general term "number".  The security code has a plethora of
    // names; we've seen "verification #", "verification number",
    // "card identification number" and others listed in the ParseText() call
    // below.
    if (is_ecml) {
      pattern = GetEcmlPattern(kEcmlCardVerification);
    } else {
      pattern = ASCIIToUTF16(
          "verification|card identification|cvn|security code|cvv code|cvc");
    }

    if (credit_card_field.verification_ == NULL &&
        ParseText(&q, pattern, &credit_card_field.verification_)) {
      continue;
    }

    if (is_ecml)
      pattern = GetEcmlPattern(kEcmlCardNumber);
    else
      pattern = ASCIIToUTF16("number|card #|card no.|card_number");

    if (credit_card_field.number_ == NULL && ParseText(&q, pattern,
        &credit_card_field.number_)) {
      continue;
    }

    // "Expiration date" is the most common label here, but some pages have
    // "Expires", "exp. date" or "exp. month" and "exp. year".  We also look for
    // the field names ccmonth and ccyear, which appear on at least 4 of our
    // test pages.
    //
    // -> On at least one page (The China Shop2.html) we find only the labels
    // "month" and "year".  So for now we match these words directly; we'll
    // see if this turns out to be too general.
    //
    // Toolbar Bug 51451: indeed, simply matching "month" is too general for
    //   https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init.
    // Instead, we match only words beginning with "month".
    if (is_ecml)
      pattern = GetEcmlPattern(kEcmlCardExpireMonth);
    else
      pattern = ASCIIToUTF16("expir|exp month|exp date|ccmonth|&month");

    if (!credit_card_field.expiration_month_ ||
        credit_card_field.expiration_month_->IsEmpty() &&
        ParseText(&q, pattern, &credit_card_field.expiration_month_)) {
      if (is_ecml)
        pattern = GetEcmlPattern(kEcmlCardExpireYear);
      else
        pattern = ASCIIToUTF16("|exp|^/|ccyear|year");

      if (!ParseText(&q, pattern, &credit_card_field.expiration_year_)) {
        return NULL;
      }

      continue;
    }

    if (ParseText(&q, GetEcmlPattern(kEcmlCardExpireDay)))
      continue;

    // Some pages (e.g. ExpediaBilling.html) have a "card description"
    // field; we parse this field but ignore it.
    ParseText(&q, ASCIIToUTF16("card description"));
  }

  // On some pages, the user selects a card type using radio buttons
  // (e.g. test page Apple Store Billing.html).  We can't handle that yet,
  // so we treat the card type as optional for now.
  if (credit_card_field.number_ != NULL &&
      credit_card_field.expiration_month_ &&
      !credit_card_field.expiration_month_->IsEmpty()) {
      *iter = q;
      return new CreditCardField(credit_card_field);
  }

  return NULL;
}

CreditCardField::CreditCardField()
    : cardholder_(NULL),
      cardholder_last_(NULL),
      type_(NULL),
      number_(NULL),
      verification_(NULL),
      expiration_month_(NULL),
      expiration_year_(NULL) {
}

CreditCardField::CreditCardField(const CreditCardField& field)
    : cardholder_(field.cardholder_),
      cardholder_last_(field.cardholder_last_),
      type_(field.type_),
      number_(field.number_),
      verification_(field.verification_),
      expiration_month_(field.expiration_month_),
      expiration_year_(field.expiration_year_) {
}
<commit_msg>Fix the ARM build.  Clarify the logic with parentheses.<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/autofill/credit_card_field.h"

#include "base/string16.h"
#include "chrome/browser/autofill/autofill_field.h"

bool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const {
  return false;
}

// static
CreditCardField* CreditCardField::Parse(
    std::vector<AutoFillField*>::const_iterator* iter,
    bool is_ecml) {
  CreditCardField credit_card_field;
  std::vector<AutoFillField*>::const_iterator q = *iter;
  string16 pattern;

  // Credit card fields can appear in many different orders.
  for (int fields = 0; q != *iter; ++fields) {
    // Sometimes the cardholder field is just labeled "name" (e.g. on test page
    // Starbucks - Credit card.html).  Unfortunately this is a dangerously
    // generic word to search for, since it will often match a name (not
    // cardholder name) field before or after credit card fields.  So we search
    // for "name" only when we've already parsed at least one other credit card
    // field and haven't yet parsed the expiration date (which usually appears
    // at the end).
    if (credit_card_field.cardholder_ == NULL) {
      string16 name_pattern;
      if (is_ecml) {
        name_pattern = GetEcmlPattern(kEcmlCardHolder);
      } else {
        if (fields == 0 || credit_card_field.expiration_month_) {
          // at beginning or end
          name_pattern = ASCIIToUTF16("card holder|name on card");
        } else {
          name_pattern = ASCIIToUTF16("name");
        }
      }

      if (ParseText(&q, name_pattern, &credit_card_field.cardholder_)) {
        continue;
      }

      // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html
      // and ExpediaBilling.html in our test suite), recognize separate fields
      // for the cardholder's first and last name if they have the labels "cfnm"
      // and "clnm".
      std::vector<AutoFillField*>::const_iterator p = q;
      AutoFillField* first;
      if (!is_ecml && ParseText(&p, ASCIIToUTF16("^cfnm"), &first) &&
          ParseText(&p, ASCIIToUTF16("^clnm"),
                    &credit_card_field.cardholder_last_)) {
        credit_card_field.cardholder_ = first;
        q = p;
        continue;
      }
    }

    // TODO(jhawkins): Parse the type select control.

    // We look for a card security code before we look for a credit card number
    // and match the general term "number".  The security code has a plethora of
    // names; we've seen "verification #", "verification number",
    // "card identification number" and others listed in the ParseText() call
    // below.
    if (is_ecml) {
      pattern = GetEcmlPattern(kEcmlCardVerification);
    } else {
      pattern = ASCIIToUTF16(
          "verification|card identification|cvn|security code|cvv code|cvc");
    }

    if (credit_card_field.verification_ == NULL &&
        ParseText(&q, pattern, &credit_card_field.verification_)) {
      continue;
    }

    if (is_ecml)
      pattern = GetEcmlPattern(kEcmlCardNumber);
    else
      pattern = ASCIIToUTF16("number|card #|card no.|card_number");

    if (credit_card_field.number_ == NULL && ParseText(&q, pattern,
        &credit_card_field.number_)) {
      continue;
    }

    // "Expiration date" is the most common label here, but some pages have
    // "Expires", "exp. date" or "exp. month" and "exp. year".  We also look for
    // the field names ccmonth and ccyear, which appear on at least 4 of our
    // test pages.
    //
    // -> On at least one page (The China Shop2.html) we find only the labels
    // "month" and "year".  So for now we match these words directly; we'll
    // see if this turns out to be too general.
    //
    // Toolbar Bug 51451: indeed, simply matching "month" is too general for
    //   https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init.
    // Instead, we match only words beginning with "month".
    if (is_ecml)
      pattern = GetEcmlPattern(kEcmlCardExpireMonth);
    else
      pattern = ASCIIToUTF16("expir|exp month|exp date|ccmonth|&month");

    if ((!credit_card_field.expiration_month_ ||
        credit_card_field.expiration_month_->IsEmpty()) &&
        ParseText(&q, pattern, &credit_card_field.expiration_month_)) {
      if (is_ecml)
        pattern = GetEcmlPattern(kEcmlCardExpireYear);
      else
        pattern = ASCIIToUTF16("|exp|^/|ccyear|year");

      if (!ParseText(&q, pattern, &credit_card_field.expiration_year_)) {
        return NULL;
      }

      continue;
    }

    if (ParseText(&q, GetEcmlPattern(kEcmlCardExpireDay)))
      continue;

    // Some pages (e.g. ExpediaBilling.html) have a "card description"
    // field; we parse this field but ignore it.
    ParseText(&q, ASCIIToUTF16("card description"));
  }

  // On some pages, the user selects a card type using radio buttons
  // (e.g. test page Apple Store Billing.html).  We can't handle that yet,
  // so we treat the card type as optional for now.
  if (credit_card_field.number_ != NULL &&
      credit_card_field.expiration_month_ &&
      !credit_card_field.expiration_month_->IsEmpty()) {
      *iter = q;
      return new CreditCardField(credit_card_field);
  }

  return NULL;
}

CreditCardField::CreditCardField()
    : cardholder_(NULL),
      cardholder_last_(NULL),
      type_(NULL),
      number_(NULL),
      verification_(NULL),
      expiration_month_(NULL),
      expiration_year_(NULL) {
}

CreditCardField::CreditCardField(const CreditCardField& field)
    : cardholder_(field.cardholder_),
      cardholder_last_(field.cardholder_last_),
      type_(field.type_),
      number_(field.number_),
      verification_(field.verification_),
      expiration_month_(field.expiration_month_),
      expiration_year_(field.expiration_year_) {
}
<|endoftext|>


<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/chromeos/boot_times_loader.h"

#include <vector>

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/process_util.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/chrome_switches.h"

namespace chromeos {

// Beginning of line we look for that gives version number.
static const char kPrefix[] = "CHROMEOS_RELEASE_DESCRIPTION=";

// File to look for version number in.
static const char kVersionPath[] = "/etc/lsb-release";

// File uptime logs are located in.
static const char kLogPath[] = "/tmp";

BootTimesLoader::BootTimesLoader() : backend_(new Backend()) {
}

BootTimesLoader::Handle BootTimesLoader::GetBootTimes(
    CancelableRequestConsumerBase* consumer,
    BootTimesLoader::GetBootTimesCallback* callback) {
  if (!g_browser_process->file_thread()) {
    // This should only happen if Chrome is shutting down, so we don't do
    // anything.
    return 0;
  }

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kTestType)) {
    // TODO(davemoore) This avoids boottimes for tests. This needs to be
    // replaced with a mock of BootTimesLoader.
    return 0;
  }

  scoped_refptr<CancelableRequest<GetBootTimesCallback> > request(
      new CancelableRequest<GetBootTimesCallback>(callback));
  AddRequest(request, consumer);

  g_browser_process->file_thread()->message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(backend_.get(), &Backend::GetBootTimes, request));
  return request->handle();
}

// Executes command within a shell, allowing IO redirection. Searches
// for a whitespace delimited string prefixed by prefix in the output and
// returns it.
static std::string ExecuteInShell(
    const std::string& command, const std::string& prefix) {
  std::vector<std::string> args;
  args.push_back("/bin/sh");
  args.push_back("-c");
  args.push_back(command);
  CommandLine cmd(args);
  std::string out;

  if (base::GetAppOutput(cmd, &out)) {
    size_t index = out.find(prefix);
    if (index != std::string::npos) {
      size_t value_index = index + prefix.size();
      size_t whitespace_index = out.find(' ', value_index);
      size_t chars_left = std::string::npos;
      if (whitespace_index == std::string::npos)
        whitespace_index = out.find('\n', value_index);
      if (whitespace_index != std::string::npos)
        chars_left = whitespace_index - value_index;
      return out.substr(value_index, chars_left);
    }
  }
  return std::string();
}

// Extracts the uptime value from files located in /tmp, returning the
// value as a double in value.
static bool GetUptime(const std::string& log, double* value) {
  FilePath log_dir(kLogPath);
  FilePath log_file = log_dir.Append(log);
  std::string contents;
  *value = 0.0;
  if (file_util::ReadFileToString(log_file, &contents)) {
    size_t space_index = contents.find(' ');
    size_t chars_left =
        space_index != std::string::npos ? space_index : std::string::npos;
    std::string value_string = contents.substr(0, chars_left);
    return StringToDouble(value_string, value);
  }
  return false;
}

void BootTimesLoader::Backend::GetBootTimes(
    scoped_refptr<GetBootTimesRequest> request) {
  const char* kInitialTSCCommand = "dmesg | grep 'Initial TSC value:'";
  const char* kInitialTSCPrefix = "TSC value: ";
  const char* kClockSpeedCommand = "dmesg | grep -e 'Detected.*processor'";
  const char* kClockSpeedPrefix = "Detected ";
  const char* kPreStartup = "uptime-pre-startup";
  const char* kChromeExec = "uptime-chrome-exec";
  const char* kChromeMain = "uptime-chrome-main";
  const char* kXStarted = "uptime-x-started";
  const char* kLoginPromptReady = "uptime-login-prompt-ready";

  if (request->canceled())
    return;

  // Wait until login_prompt_ready is output.
  FilePath log_dir(kLogPath);
  FilePath log_file = log_dir.Append(kLoginPromptReady);
  while (!file_util::PathExists(log_file)) {
    usleep(500000);
  }

  BootTimes boot_times;
  std::string tsc_value = ExecuteInShell(kInitialTSCCommand, kInitialTSCPrefix);
  std::string speed_value =
      ExecuteInShell(kClockSpeedCommand, kClockSpeedPrefix);
  boot_times.firmware = 0;
  if (!tsc_value.empty() && !speed_value.empty()) {
    int64 tsc = 0;
    double speed = 0;
    if (StringToInt64(tsc_value, &tsc) &&
        StringToDouble(speed_value, &speed) &&
        speed > 0) {
      boot_times.firmware = static_cast<double>(tsc) / (speed * 1000000);
    }
  }
  GetUptime(kPreStartup, &boot_times.pre_startup);
  GetUptime(kXStarted, &boot_times.x_started);
  GetUptime(kChromeExec, &boot_times.chrome_exec);
  GetUptime(kChromeMain, &boot_times.chrome_main);
  GetUptime(kLoginPromptReady, &boot_times.login_prompt_ready);

  request->ForwardResult(
      GetBootTimesCallback::TupleType(request->handle(), boot_times));
}

}  // namespace chromeos
<commit_msg>Make boottime delay not block file thread BUG=None TEST=Boot on ARM...boottimes shouldn't display but chrome should      still work. We will be stating a file every half second though      until /tmp/uptime-login-prompt-ready is emited.<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/chromeos/boot_times_loader.h"

#include <vector>

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/process_util.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/chrome_switches.h"

namespace chromeos {

// File uptime logs are located in.
static const char kLogPath[] = "/tmp";

BootTimesLoader::BootTimesLoader() : backend_(new Backend()) {
}

BootTimesLoader::Handle BootTimesLoader::GetBootTimes(
    CancelableRequestConsumerBase* consumer,
    BootTimesLoader::GetBootTimesCallback* callback) {
  if (!g_browser_process->file_thread()) {
    // This should only happen if Chrome is shutting down, so we don't do
    // anything.
    return 0;
  }

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kTestType)) {
    // TODO(davemoore) This avoids boottimes for tests. This needs to be
    // replaced with a mock of BootTimesLoader.
    return 0;
  }

  scoped_refptr<CancelableRequest<GetBootTimesCallback> > request(
      new CancelableRequest<GetBootTimesCallback>(callback));
  AddRequest(request, consumer);

  g_browser_process->file_thread()->message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(backend_.get(), &Backend::GetBootTimes, request));
  return request->handle();
}

// Executes command within a shell, allowing IO redirection. Searches
// for a whitespace delimited string prefixed by prefix in the output and
// returns it.
static std::string ExecuteInShell(
    const std::string& command, const std::string& prefix) {
  std::vector<std::string> args;
  args.push_back("/bin/sh");
  args.push_back("-c");
  args.push_back(command);
  CommandLine cmd(args);
  std::string out;

  if (base::GetAppOutput(cmd, &out)) {
    size_t index = out.find(prefix);
    if (index != std::string::npos) {
      size_t value_index = index + prefix.size();
      size_t whitespace_index = out.find(' ', value_index);
      size_t chars_left = std::string::npos;
      if (whitespace_index == std::string::npos)
        whitespace_index = out.find('\n', value_index);
      if (whitespace_index != std::string::npos)
        chars_left = whitespace_index - value_index;
      return out.substr(value_index, chars_left);
    }
  }
  return std::string();
}

// Extracts the uptime value from files located in /tmp, returning the
// value as a double in value.
static bool GetUptime(const std::string& log, double* value) {
  FilePath log_dir(kLogPath);
  FilePath log_file = log_dir.Append(log);
  std::string contents;
  *value = 0.0;
  if (file_util::ReadFileToString(log_file, &contents)) {
    size_t space_index = contents.find(' ');
    size_t chars_left =
        space_index != std::string::npos ? space_index : std::string::npos;
    std::string value_string = contents.substr(0, chars_left);
    return StringToDouble(value_string, value);
  }
  return false;
}

void BootTimesLoader::Backend::GetBootTimes(
    scoped_refptr<GetBootTimesRequest> request) {
  const char* kInitialTSCCommand = "dmesg | grep 'Initial TSC value:'";
  const char* kInitialTSCPrefix = "TSC value: ";
  const char* kClockSpeedCommand = "dmesg | grep -e 'Detected.*processor'";
  const char* kClockSpeedPrefix = "Detected ";
  const char* kPreStartup = "uptime-pre-startup";
  const char* kChromeExec = "uptime-chrome-exec";
  const char* kChromeMain = "uptime-chrome-main";
  const char* kXStarted = "uptime-x-started";
  const char* kLoginPromptReady = "uptime-login-prompt-ready";

  if (request->canceled())
    return;

  // Wait until login_prompt_ready is output by reposting.
  FilePath log_dir(kLogPath);
  FilePath log_file = log_dir.Append(kLoginPromptReady);
  if (!file_util::PathExists(log_file)) {
    g_browser_process->file_thread()->message_loop()->PostDelayedTask(
        FROM_HERE,
        NewRunnableMethod(this, &Backend::GetBootTimes, request),
        500);
    return;
  }

  BootTimes boot_times;
  std::string tsc_value = ExecuteInShell(kInitialTSCCommand, kInitialTSCPrefix);
  std::string speed_value =
      ExecuteInShell(kClockSpeedCommand, kClockSpeedPrefix);
  boot_times.firmware = 0;
  if (!tsc_value.empty() && !speed_value.empty()) {
    int64 tsc = 0;
    double speed = 0;
    if (StringToInt64(tsc_value, &tsc) &&
        StringToDouble(speed_value, &speed) &&
        speed > 0) {
      boot_times.firmware = static_cast<double>(tsc) / (speed * 1000000);
    }
  }
  GetUptime(kPreStartup, &boot_times.pre_startup);
  GetUptime(kXStarted, &boot_times.x_started);
  GetUptime(kChromeExec, &boot_times.chrome_exec);
  GetUptime(kChromeMain, &boot_times.chrome_main);
  GetUptime(kLoginPromptReady, &boot_times.login_prompt_ready);

  request->ForwardResult(
      GetBootTimesCallback::TupleType(request->handle(), boot_times));
}

}  // namespace chromeos
<|endoftext|>


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

#include "chrome/browser/chromeos/login/login_utils.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/lock.h"
#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
#include "base/time.h"
#include "chrome/browser/browser_init.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/external_cookie_handler.h"
#include "chrome/browser/chromeos/login/cookie_fetcher.h"
#include "chrome/browser/chromeos/login/google_authenticator.h"
#include "chrome/browser/chromeos/login/user_image_downloader.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "googleurl/src/gurl.h"
#include "net/base/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "views/widget/widget_gtk.h"

namespace chromeos {

namespace {

const int kWifiTimeoutInMS = 15000;
static char kIncognitoUser[] = "incognito";

// Prefix for Auth token received from ClientLogin request.
const char kAuthPrefix[] = "Auth=";
// Suffix for Auth token received from ClientLogin request.
const char kAuthSuffix[] = "\n";

// Find Auth token in given response from ClientLogin request.
// Returns the token if found, empty string otherwise.
std::string get_auth_token(const std::string& credentials) {
  size_t auth_start = credentials.find(kAuthPrefix);
  if (auth_start == std::string::npos)
    return std::string();
  auth_start += arraysize(kAuthPrefix) - 1;
  size_t auth_end = credentials.find(kAuthSuffix, auth_start);
  if (auth_end == std::string::npos)
    return std::string();
  return credentials.substr(auth_start, auth_end - auth_start);
}

}  // namespace

class LoginUtilsImpl : public LoginUtils,
                       public NotificationObserver {
 public:
  LoginUtilsImpl() : wifi_connecting_(false) {
    registrar_.Add(
        this,
        NotificationType::LOGIN_USER_CHANGED,
        NotificationService::AllSources());
  }

  virtual bool ShouldWaitForWifi();

  // Invoked after the user has successfully logged in. This launches a browser
  // and does other bookkeeping after logging in.
  virtual void CompleteLogin(const std::string& username,
                             const std::string& credentials);

  // Invoked after the tmpfs is successfully mounted.
  // Launches a browser in the off the record (incognito) mode.
  virtual void CompleteOffTheRecordLogin();

  // Creates and returns the authenticator to use. The caller owns the returned
  // Authenticator and must delete it when done.
  virtual Authenticator* CreateAuthenticator(LoginStatusConsumer* consumer);

  // Used to postpone browser launch via DoBrowserLaunch() if some post
  // login screen is to be shown.
  virtual void EnableBrowserLaunch(bool enable);

  // Returns if browser launch enabled now or not.
  virtual bool IsBrowserLaunchEnabled() const;

  // Returns auth token for 'cp' Contacts service.
  virtual const std::string& GetAuthToken() const { return auth_token_; }

  // NotificationObserver implementation.
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

 private:
  // Attempt to connect to the preferred network if available.
  void ConnectToPreferredNetwork();

  NotificationRegistrar registrar_;
  bool wifi_connecting_;
  base::Time wifi_connect_start_time_;

  // Indicates if DoBrowserLaunch will actually launch the browser or not.
  bool browser_launch_enabled_;

  // Auth token for Contacts service. Received by GoogleAuthenticator as
  // part of ClientLogin response.
  std::string auth_token_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
};

class LoginUtilsWrapper {
 public:
  LoginUtilsWrapper() {}

  LoginUtils* get() {
    AutoLock create(create_lock_);
    if (!ptr_.get())
      reset(new LoginUtilsImpl);
    return ptr_.get();
  }

  void reset(LoginUtils* ptr) {
    ptr_.reset(ptr);
  }

 private:
  Lock create_lock_;
  scoped_ptr<LoginUtils> ptr_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
};

bool LoginUtilsImpl::ShouldWaitForWifi() {
  // If we are connecting to the preferred network,
  // wait kWifiTimeoutInMS until connection is made or failed.
  if (wifi_connecting_) {
    NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
    if (cros->PreferredNetworkConnected()) {
      LOG(INFO) << "Wifi connection successful.";
      return false;
    } else if (cros->PreferredNetworkFailed()) {
      LOG(INFO) << "Wifi connection failed.";
      return false;
    } else {
      base::TimeDelta diff = base::Time::Now() - wifi_connect_start_time_;
      // Keep waiting if we have not timed out yet.
      bool timedout = (diff.InMilliseconds() > kWifiTimeoutInMS);
      if (timedout)
        LOG(INFO) << "Wifi connection timed out.";
      return !timedout;
    }
  }
  return false;
}

void LoginUtilsImpl::CompleteLogin(const std::string& username,
                                   const std::string& credentials) {
  LOG(INFO) << "Completing login for " << username;

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->StartSession(username, "");

  UserManager::Get()->UserLoggedIn(username);
  ConnectToPreferredNetwork();

  // Now launch the initial browser window.
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  // The default profile will have been changed because the ProfileManager
  // will process the notification that the UserManager sends out.
  Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);

  // Take the credentials passed in and try to exchange them for
  // full-fledged Google authentication cookies.  This is
  // best-effort; it's possible that we'll fail due to network
  // troubles or some such.  Either way, |cf| will call
  // DoBrowserLaunch on the UI thread when it's done, and then
  // delete itself.
  CookieFetcher* cf = new CookieFetcher(profile);
  cf->AttemptFetch(credentials);
  auth_token_ = get_auth_token(credentials);
}

void LoginUtilsImpl::CompleteOffTheRecordLogin() {
  LOG(INFO) << "Completing off the record login";

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->StartSession(kIncognitoUser, "");

  // Incognito flag is not set by default.
  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kIncognito);

  UserManager::Get()->OffTheRecordUserLoggedIn();
  ConnectToPreferredNetwork();
  LoginUtils::DoBrowserLaunch(
      ProfileManager::GetDefaultProfile()->GetOffTheRecordProfile());
}

Authenticator* LoginUtilsImpl::CreateAuthenticator(
    LoginStatusConsumer* consumer) {
  return new GoogleAuthenticator(consumer);
}

void LoginUtilsImpl::EnableBrowserLaunch(bool enable) {
  browser_launch_enabled_ = enable;
}

bool LoginUtilsImpl::IsBrowserLaunchEnabled() const {
  return browser_launch_enabled_;
}

void LoginUtilsImpl::Observe(NotificationType type,
                             const NotificationSource& source,
                             const NotificationDetails& details) {
  if (type == NotificationType::LOGIN_USER_CHANGED)
    base::OpenPersistentNSSDB();
}

void LoginUtilsImpl::ConnectToPreferredNetwork() {
  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
  wifi_connecting_ = cros->ConnectToPreferredNetworkIfAvailable();
  if (wifi_connecting_)
    wifi_connect_start_time_ = base::Time::Now();
}

LoginUtils* LoginUtils::Get() {
  return Singleton<LoginUtilsWrapper>::get()->get();
}

void LoginUtils::Set(LoginUtils* mock) {
  Singleton<LoginUtilsWrapper>::get()->reset(mock);
}

void LoginUtils::DoBrowserLaunch(Profile* profile) {
  // If we should wait for wifi connection, post this task with a 100ms delay.
  if (LoginUtils::Get()->ShouldWaitForWifi()) {
    ChromeThread::PostDelayedTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableFunction(&LoginUtils::DoBrowserLaunch, profile), 100);
    return;
  }

  // Browser launch was disabled due to some post login screen.
  if (!LoginUtils::Get()->IsBrowserLaunchEnabled())
    return;

  LOG(INFO) << "Launching browser...";
  BrowserInit browser_init;
  int return_code;
  browser_init.LaunchBrowser(*CommandLine::ForCurrentProcess(),
                             profile,
                             std::wstring(),
                             true,
                             &return_code);
}

}  // namespace chromeos
<commit_msg>Quick fix: initializing member variable. Makes offline login work.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/login_utils.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/lock.h"
#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
#include "base/time.h"
#include "chrome/browser/browser_init.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/external_cookie_handler.h"
#include "chrome/browser/chromeos/login/cookie_fetcher.h"
#include "chrome/browser/chromeos/login/google_authenticator.h"
#include "chrome/browser/chromeos/login/user_image_downloader.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "googleurl/src/gurl.h"
#include "net/base/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "views/widget/widget_gtk.h"

namespace chromeos {

namespace {

const int kWifiTimeoutInMS = 15000;
static char kIncognitoUser[] = "incognito";

// Prefix for Auth token received from ClientLogin request.
const char kAuthPrefix[] = "Auth=";
// Suffix for Auth token received from ClientLogin request.
const char kAuthSuffix[] = "\n";

// Find Auth token in given response from ClientLogin request.
// Returns the token if found, empty string otherwise.
std::string get_auth_token(const std::string& credentials) {
  size_t auth_start = credentials.find(kAuthPrefix);
  if (auth_start == std::string::npos)
    return std::string();
  auth_start += arraysize(kAuthPrefix) - 1;
  size_t auth_end = credentials.find(kAuthSuffix, auth_start);
  if (auth_end == std::string::npos)
    return std::string();
  return credentials.substr(auth_start, auth_end - auth_start);
}

}  // namespace

class LoginUtilsImpl : public LoginUtils,
                       public NotificationObserver {
 public:
  LoginUtilsImpl()
      : wifi_connecting_(false),
        browser_launch_enabled_(true) {
    registrar_.Add(
        this,
        NotificationType::LOGIN_USER_CHANGED,
        NotificationService::AllSources());
  }

  virtual bool ShouldWaitForWifi();

  // Invoked after the user has successfully logged in. This launches a browser
  // and does other bookkeeping after logging in.
  virtual void CompleteLogin(const std::string& username,
                             const std::string& credentials);

  // Invoked after the tmpfs is successfully mounted.
  // Launches a browser in the off the record (incognito) mode.
  virtual void CompleteOffTheRecordLogin();

  // Creates and returns the authenticator to use. The caller owns the returned
  // Authenticator and must delete it when done.
  virtual Authenticator* CreateAuthenticator(LoginStatusConsumer* consumer);

  // Used to postpone browser launch via DoBrowserLaunch() if some post
  // login screen is to be shown.
  virtual void EnableBrowserLaunch(bool enable);

  // Returns if browser launch enabled now or not.
  virtual bool IsBrowserLaunchEnabled() const;

  // Returns auth token for 'cp' Contacts service.
  virtual const std::string& GetAuthToken() const { return auth_token_; }

  // NotificationObserver implementation.
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

 private:
  // Attempt to connect to the preferred network if available.
  void ConnectToPreferredNetwork();

  NotificationRegistrar registrar_;
  bool wifi_connecting_;
  base::Time wifi_connect_start_time_;

  // Indicates if DoBrowserLaunch will actually launch the browser or not.
  bool browser_launch_enabled_;

  // Auth token for Contacts service. Received by GoogleAuthenticator as
  // part of ClientLogin response.
  std::string auth_token_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
};

class LoginUtilsWrapper {
 public:
  LoginUtilsWrapper() {}

  LoginUtils* get() {
    AutoLock create(create_lock_);
    if (!ptr_.get())
      reset(new LoginUtilsImpl);
    return ptr_.get();
  }

  void reset(LoginUtils* ptr) {
    ptr_.reset(ptr);
  }

 private:
  Lock create_lock_;
  scoped_ptr<LoginUtils> ptr_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
};

bool LoginUtilsImpl::ShouldWaitForWifi() {
  // If we are connecting to the preferred network,
  // wait kWifiTimeoutInMS until connection is made or failed.
  if (wifi_connecting_) {
    NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
    if (cros->PreferredNetworkConnected()) {
      LOG(INFO) << "Wifi connection successful.";
      return false;
    } else if (cros->PreferredNetworkFailed()) {
      LOG(INFO) << "Wifi connection failed.";
      return false;
    } else {
      base::TimeDelta diff = base::Time::Now() - wifi_connect_start_time_;
      // Keep waiting if we have not timed out yet.
      bool timedout = (diff.InMilliseconds() > kWifiTimeoutInMS);
      if (timedout)
        LOG(INFO) << "Wifi connection timed out.";
      return !timedout;
    }
  }
  return false;
}

void LoginUtilsImpl::CompleteLogin(const std::string& username,
                                   const std::string& credentials) {
  LOG(INFO) << "Completing login for " << username;

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->StartSession(username, "");

  UserManager::Get()->UserLoggedIn(username);
  ConnectToPreferredNetwork();

  // Now launch the initial browser window.
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  // The default profile will have been changed because the ProfileManager
  // will process the notification that the UserManager sends out.
  Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);

  // Take the credentials passed in and try to exchange them for
  // full-fledged Google authentication cookies.  This is
  // best-effort; it's possible that we'll fail due to network
  // troubles or some such.  Either way, |cf| will call
  // DoBrowserLaunch on the UI thread when it's done, and then
  // delete itself.
  CookieFetcher* cf = new CookieFetcher(profile);
  cf->AttemptFetch(credentials);
  auth_token_ = get_auth_token(credentials);
}

void LoginUtilsImpl::CompleteOffTheRecordLogin() {
  LOG(INFO) << "Completing off the record login";

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->StartSession(kIncognitoUser, "");

  // Incognito flag is not set by default.
  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kIncognito);

  UserManager::Get()->OffTheRecordUserLoggedIn();
  ConnectToPreferredNetwork();
  LoginUtils::DoBrowserLaunch(
      ProfileManager::GetDefaultProfile()->GetOffTheRecordProfile());
}

Authenticator* LoginUtilsImpl::CreateAuthenticator(
    LoginStatusConsumer* consumer) {
  return new GoogleAuthenticator(consumer);
}

void LoginUtilsImpl::EnableBrowserLaunch(bool enable) {
  browser_launch_enabled_ = enable;
}

bool LoginUtilsImpl::IsBrowserLaunchEnabled() const {
  return browser_launch_enabled_;
}

void LoginUtilsImpl::Observe(NotificationType type,
                             const NotificationSource& source,
                             const NotificationDetails& details) {
  if (type == NotificationType::LOGIN_USER_CHANGED)
    base::OpenPersistentNSSDB();
}

void LoginUtilsImpl::ConnectToPreferredNetwork() {
  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
  wifi_connecting_ = cros->ConnectToPreferredNetworkIfAvailable();
  if (wifi_connecting_)
    wifi_connect_start_time_ = base::Time::Now();
}

LoginUtils* LoginUtils::Get() {
  return Singleton<LoginUtilsWrapper>::get()->get();
}

void LoginUtils::Set(LoginUtils* mock) {
  Singleton<LoginUtilsWrapper>::get()->reset(mock);
}

void LoginUtils::DoBrowserLaunch(Profile* profile) {
  // If we should wait for wifi connection, post this task with a 100ms delay.
  if (LoginUtils::Get()->ShouldWaitForWifi()) {
    ChromeThread::PostDelayedTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableFunction(&LoginUtils::DoBrowserLaunch, profile), 100);
    return;
  }

  // Browser launch was disabled due to some post login screen.
  if (!LoginUtils::Get()->IsBrowserLaunchEnabled())
    return;

  LOG(INFO) << "Launching browser...";
  BrowserInit browser_init;
  int return_code;
  browser_init.LaunchBrowser(*CommandLine::ForCurrentProcess(),
                             profile,
                             std::wstring(),
                             true,
                             &return_code);
}

}  // namespace chromeos
<|endoftext|>


<commit_before>#include "def_lang/impl/Ptr_Value.h"
#include "def_lang/Value_Selector.h"
#include "def_lang/Serialization.h"
#include "def_lang/IStruct_Type.h"

namespace ts
{

Ptr_Value::Ptr_Value(std::shared_ptr<IPtr_Type const> type)
    : m_type(type)
{
}

Result<bool> Ptr_Value::is_equal(IValue const& other) const
{
    IPtr_Value const* v = dynamic_cast<const IPtr_Value*>(&other);
    if (!v)
    {
        return Error("incompatible values");
    }

    if (get_type() != v->get_type())
    {
        return Error("incompatible types");
    }

    if (get_specialized_type()->get_inner_type() != v->get_specialized_type()->get_inner_type())
    {
        return Error("incompatible inner types");
    }

    //if both are null, then they are equal
    if (get_value() == nullptr && v->get_value() == nullptr)
    {
        return true;
    }

    //if one is null and the other not null, the values are different
    if ((get_value() == nullptr) != (v->get_value() == nullptr))
    {
        return true;
    }

    return get_value()->is_equal(*v->get_value());
}

Result<void> Ptr_Value::copy_assign(IValue const& other)
{
    IPtr_Value const* v = dynamic_cast<const IPtr_Value*>(&other);
    if (!v)
    {
        return Error("incompatible values");
    }

    if (get_type() != v->get_type())
    {
        return Error("incompatible types");
    }

    if (!is_type_allowed(*v->get_specialized_type()->get_inner_type()))
    {
        return Error("Cannot point to type " + v->get_specialized_type()->get_inner_type()->get_symbol_path().to_string());
    }

    if (get_value() == nullptr)
    {
        if (v->get_value() == nullptr)
        {
            return success;
        }
        return set_value(v->get_value()->clone());
    }
    else
    {
        if (v->get_value() == nullptr)
        {
            return set_value(nullptr);
        }
        return get_value()->copy_assign(*v->get_value());
    }
}
Result<void> Ptr_Value::copy_assign(IInitializer const& initializer)
{
    return Error("not implemented");
}

std::shared_ptr<IValue> Ptr_Value::clone() const
{
    return std::make_shared<Ptr_Value>(*this);
}

std::shared_ptr<IType const> Ptr_Value::get_type() const
{
    return m_type;
}

Result<void> Ptr_Value::parse_from_ui_string(std::string const& str)
{
    return Error("Not Supported");
}
Result<std::string> Ptr_Value::get_ui_string() const
{
    return Error("Not Supported");
}

std::shared_ptr<const IValue> Ptr_Value::select(Value_Selector&& selector) const
{
    return const_cast<Ptr_Value*>(this)->select(std::move(selector));
}
std::shared_ptr<IValue> Ptr_Value::select(Value_Selector&& selector)
{
    TS_ASSERT(!selector.empty());
    if (selector.empty())
    {
        return nullptr;
    }

    if (get_value() == nullptr)
    {
        return nullptr;
    }

    return get_value()->select(std::move(selector));
}

std::shared_ptr<IPtr_Type const> Ptr_Value::get_specialized_type() const
{
    return m_type;
}

Result<serialization::Value> Ptr_Value::serialize() const
{
    std::shared_ptr<const IValue> value = get_value();
    if (value)
    {
        serialization::Value sz_value(serialization::Value::Type::OBJECT);
        sz_value.add_object_member("type", serialization::Value(value->get_type()->get_symbol_path().to_string()));
        auto result = value->serialize();
        if (result != success)
        {
            return result;
        }
        sz_value.add_object_member("value", result.extract_payload());
        return std::move(sz_value);
    }
    else
    {
        return serialization::Value(serialization::Value::Type::EMPTY);
    }
}

Result<void> Ptr_Value::deserialize(serialization::Value const& sz_value)
{
    if (sz_value.get_type() == serialization::Value::Type::EMPTY)
    {
        set_value(std::shared_ptr<IValue>());
        return success;
    }

    if (sz_value.get_type() != serialization::Value::Type::OBJECT)
    {
        return Error("Expected object or null value when deserializing");
    }

    TS_ASSERT(false);
    return Error("Not implemented");
}

std::shared_ptr<const IValue> Ptr_Value::get_value() const
{
    return m_value;
}
std::shared_ptr<IValue> Ptr_Value::get_value()
{
    return m_value;
}

Result<void> Ptr_Value::set_value(std::shared_ptr<IValue> value)
{
    if (!value)
    {
        m_value = nullptr;
        return success;
    }

    if (!is_type_allowed(*value->get_type()))
    {
        return Error("Cannot point to type " + value->get_type()->get_symbol_path().to_string());
    }

    m_value = value;
    return success;
}

bool Ptr_Value::is_type_allowed(IType const& type) const
{
    if (get_specialized_type()->get_inner_type().get() == &type)
    {
        return true;
    }

    IStruct_Type const* inner_type = dynamic_cast<IStruct_Type const*>(get_specialized_type()->get_inner_type().get());
    IStruct_Type const* other_type = dynamic_cast<IStruct_Type const*>(&type);

    if (inner_type && other_type)
    {
        return inner_type->is_base_of(*other_type);
    }

    return false;
}

}
<commit_msg>Finished deserialization of the ptr value<commit_after>#include "def_lang/impl/Ptr_Value.h"
#include "def_lang/Value_Selector.h"
#include "def_lang/Serialization.h"
#include "def_lang/IStruct_Type.h"

namespace ts
{

Ptr_Value::Ptr_Value(std::shared_ptr<IPtr_Type const> type)
    : m_type(type)
{
}

Result<bool> Ptr_Value::is_equal(IValue const& other) const
{
    IPtr_Value const* v = dynamic_cast<const IPtr_Value*>(&other);
    if (!v)
    {
        return Error("incompatible values");
    }

    if (get_type() != v->get_type())
    {
        return Error("incompatible types");
    }

    if (get_specialized_type()->get_inner_type() != v->get_specialized_type()->get_inner_type())
    {
        return Error("incompatible inner types");
    }

    //if both are null, then they are equal
    if (get_value() == nullptr && v->get_value() == nullptr)
    {
        return true;
    }

    //if one is null and the other not null, the values are different
    if ((get_value() == nullptr) != (v->get_value() == nullptr))
    {
        return true;
    }

    return get_value()->is_equal(*v->get_value());
}

Result<void> Ptr_Value::copy_assign(IValue const& other)
{
    IPtr_Value const* v = dynamic_cast<const IPtr_Value*>(&other);
    if (!v)
    {
        return Error("incompatible values");
    }

    if (get_type() != v->get_type())
    {
        return Error("incompatible types");
    }

    if (!is_type_allowed(*v->get_specialized_type()->get_inner_type()))
    {
        return Error("Cannot point to type " + v->get_specialized_type()->get_inner_type()->get_symbol_path().to_string());
    }

    if (get_value() == nullptr)
    {
        if (v->get_value() == nullptr)
        {
            return success;
        }
        return set_value(v->get_value()->clone());
    }
    else
    {
        if (v->get_value() == nullptr)
        {
            return set_value(nullptr);
        }
        return get_value()->copy_assign(*v->get_value());
    }
}
Result<void> Ptr_Value::copy_assign(IInitializer const& initializer)
{
    return Error("not implemented");
}

std::shared_ptr<IValue> Ptr_Value::clone() const
{
    return std::make_shared<Ptr_Value>(*this);
}

std::shared_ptr<IType const> Ptr_Value::get_type() const
{
    return m_type;
}

Result<void> Ptr_Value::parse_from_ui_string(std::string const& str)
{
    return Error("Not Supported");
}
Result<std::string> Ptr_Value::get_ui_string() const
{
    return Error("Not Supported");
}

std::shared_ptr<const IValue> Ptr_Value::select(Value_Selector&& selector) const
{
    return const_cast<Ptr_Value*>(this)->select(std::move(selector));
}
std::shared_ptr<IValue> Ptr_Value::select(Value_Selector&& selector)
{
    TS_ASSERT(!selector.empty());
    if (selector.empty())
    {
        return nullptr;
    }

    if (get_value() == nullptr)
    {
        return nullptr;
    }

    return get_value()->select(std::move(selector));
}

std::shared_ptr<IPtr_Type const> Ptr_Value::get_specialized_type() const
{
    return m_type;
}

Result<serialization::Value> Ptr_Value::serialize() const
{
    std::shared_ptr<const IValue> value = get_value();
    if (value)
    {
        serialization::Value sz_value(serialization::Value::Type::OBJECT);
        sz_value.add_object_member("type", serialization::Value(value->get_type()->get_symbol_path().to_string()));
        auto result = value->serialize();
        if (result != success)
        {
            return result;
        }
        sz_value.add_object_member("value", result.extract_payload());
        return std::move(sz_value);
    }
    else
    {
        return serialization::Value(serialization::Value::Type::EMPTY);
    }
}

Result<void> Ptr_Value::deserialize(serialization::Value const& sz_value)
{
    if (sz_value.is_empty())
    {
        set_value(std::shared_ptr<IValue>());
        return success;
    }

    if (!sz_value.is_object())
    {
        return Error("Expected object or null value when deserializing");
    }

    serialization::Value const* type_sz_value = sz_value.find_object_member_by_name("type");
    if (!type_sz_value || !type_sz_value->is_string())
    {
        return Error("Expected 'type' string value when deserializing");
    }

    std::shared_ptr<const IType> type = get_type()->get_parent_scope()->find_specialized_symbol_by_path<const IType>(Symbol_Path(type_sz_value->get_as_string()));
    if (!type)
    {
        return Error("Cannot find type '" + type_sz_value->get_as_string() + "' when deserializing");
    }

    auto result = set_value(type->create_value());
    if (result != success)
    {
        return Error("Cannot create value when deserializing: " + result.error().what());
    }

    serialization::Value const* value_sz_value = sz_value.find_object_member_by_name("value");
    if (!value_sz_value)
    {
        return Error("Expected 'value' when deserializing");
    }

    return get_value()->deserialize(*value_sz_value);
}

std::shared_ptr<const IValue> Ptr_Value::get_value() const
{
    return m_value;
}
std::shared_ptr<IValue> Ptr_Value::get_value()
{
    return m_value;
}

Result<void> Ptr_Value::set_value(std::shared_ptr<IValue> value)
{
    if (!value)
    {
        m_value = nullptr;
        return success;
    }

    if (!is_type_allowed(*value->get_type()))
    {
        return Error("Cannot point to type " + value->get_type()->get_symbol_path().to_string());
    }

    m_value = value;
    return success;
}

bool Ptr_Value::is_type_allowed(IType const& type) const
{
    if (get_specialized_type()->get_inner_type().get() == &type)
    {
        return true;
    }

    IStruct_Type const* inner_type = dynamic_cast<IStruct_Type const*>(get_specialized_type()->get_inner_type().get());
    IStruct_Type const* other_type = dynamic_cast<IStruct_Type const*>(&type);

    if (inner_type && other_type)
    {
        return inner_type->is_base_of(*other_type);
    }

    return false;
}

}
<|endoftext|>


<commit_before>//!
//! @author Yue Wang
//! @date   13 11 2014
//!
//! @ex 41.01
//!     (a) share data between two threads.
//!     (b) use mutex to avoid data race.
//!
//  to compile (on linux)   :
//      g++ -std=c++11 -Wall ex41_01.cpp  -pthread
//!

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

using SharedData = std::shared_ptr<std::vector<std::string>>;

void task1(SharedData data, std::mutex* mutex)
{
    std::this_thread::sleep_for(std::chrono::milliseconds{5});

    std::unique_lock<std::mutex> lock{*mutex};
    for(const auto& elem : *data)
        std::cout << "\nfrom task 1 " << elem << " ";
}

void task2(SharedData data, std::mutex* mutex)
{
    std::unique_lock<std::mutex> lock{*mutex};
    data->push_back("pezy--added by task2");
}

int main()
{
    //! data for sharing
    auto data = std::make_shared<std::vector<std::string> >();
    *data = {"alan","moophy","yue wang"};

    //! two threads
    static std::mutex mutex;
    std::thread t1(task1,data,&mutex), t2(task2,data,&mutex);

    t1.join();
    t2.join();
    std::cout << "\n\ndone\n";
}
//! output :

//from task 1 alan
//from task 1 moophy
//from task 1 yue wang
//from task 1 pezy--added by task2

//done
<commit_msg>	deleted:    ch41/ex41_01.cpp<commit_after><|endoftext|>


<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc 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 for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "benchmark.h"
#include "random.h"
#include "../cpuid.h"
#include <cstdio>
#include <cstdlib>

using namespace Vc;

template<typename T, int S> struct KeepResultsHelper { static inline void keep(const T &tmp0) { asm volatile(""::"r"(tmp0)); } };
#ifdef VC_IMPL_SSE
template<typename T> struct KeepResultsHelper<T, 16> { static inline void keep(const T &tmp0) { asm volatile(""::"x"(reinterpret_cast<const __m128 &>(tmp0))); } };
template<typename T> struct KeepResultsHelper<T, 32> { static inline void keep(const T &tmp0) {
    asm volatile(""::"x"(reinterpret_cast<const __m128 &>(tmp0)), "x"(reinterpret_cast<const __m128 *>(&tmp0)[1]));
} };
#endif
#ifdef VC_IMPL_LRBni
template<typename T> struct KeepResultsHelper<T, 64> { static inline void keep(const T &tmp0) {
    asm volatile(""::"x"(reinterpret_cast<const __m128 &>(tmp0)), "x"(reinterpret_cast<const __m128 *>(&tmp0)[1]), "x"(reinterpret_cast<const __m128 *>(&tmp0)[2]), "x"(reinterpret_cast<const __m128 *>(&tmp0)[3]));
} };
#endif

template<typename T> static inline void keepResults(const T &tmp0)
{
    KeepResultsHelper<T, sizeof(T)>::keep(tmp0);
}

template<typename Vector> class DoMemIos
{
    public:
        static void run()
        {
            Benchmark::setColumnData("MemorySize", "half L1");
            run(CpuId::L1Data() / (sizeof(Vector) * 2), 128);
            Benchmark::setColumnData("MemorySize", "L1");
            run(CpuId::L1Data() / (sizeof(Vector) * 1), 128);
            Benchmark::setColumnData("MemorySize", "half L2");
            run(CpuId::L2Data() / (sizeof(Vector) * 2), 32);
            Benchmark::setColumnData("MemorySize", "L2");
            run(CpuId::L2Data() / (sizeof(Vector) * 1), 16);
            if (CpuId::L3Data() > 0) {
                Benchmark::setColumnData("MemorySize", "half L3");
                run(CpuId::L3Data() / (sizeof(Vector) * 2), 2);
                Benchmark::setColumnData("MemorySize", "L3");
                run(CpuId::L3Data() / (sizeof(Vector) * 1), 2);
                Benchmark::setColumnData("MemorySize", "4x L3");
                run(CpuId::L3Data() / sizeof(Vector) * 4, 1);
            } else {
                Benchmark::setColumnData("MemorySize", "4x L2");
                run(CpuId::L2Data() / sizeof(Vector) * 4, 1);
            }
        }
    private:
        static void run(const int Factor, const int Factor2)
        {
            Vector *a = new Vector[Factor];
#ifndef VC_BENCHMARK_NO_MLOCK
            mlock(a, Factor * sizeof(Vector));
#endif

            {
                Benchmark bm("write", sizeof(Vector) * Factor * Factor2, "Byte");
                const Vector foo = PseudoRandom<Vector>::next();
                keepResults(foo);
                for (int i = 0; i < Factor; i += 4) {
                    a[i + 0] = foo;
                    a[i + 1] = foo;
                    a[i + 2] = foo;
                    a[i + 3] = foo;
                }
                while (bm.wantsMoreDataPoints()) {
                    bm.Start();
                    for (int j = 0; j < Factor2; ++j) {
                        keepResults(foo);
                        for (int i = 0; i < Factor; i += 4) {
                            a[i + 0] = foo;
                            a[i + 1] = foo;
                            a[i + 2] = foo;
                            a[i + 3] = foo;
                        }
                    }
                    bm.Stop();
                }
                bm.Print();
            }
            {
                Benchmark timer("r/w", sizeof(Vector) * Factor * Factor2, "Byte");
                const Vector foo = PseudoRandom<Vector>::next();
                while (timer.wantsMoreDataPoints()) {
                    timer.Start();
                    for (int j = 0; j < Factor2; ++j) {
                        keepResults(foo);
                        for (int i = 0; i < Factor; i += 4) {
                            const Vector &tmp0 = a[i + 0]; keepResults(tmp0);
                            a[i + 0] = foo;
                            const Vector &tmp1 = a[i + 1]; keepResults(tmp1);
                            a[i + 1] = foo;
                            const Vector &tmp2 = a[i + 2]; keepResults(tmp2);
                            a[i + 2] = foo;
                            const Vector &tmp3 = a[i + 3]; keepResults(tmp3);
                            a[i + 3] = foo;
                        }
                    }
                    timer.Stop();
                }
                timer.Print();
            }
            {
                Benchmark timer("read", sizeof(Vector) * Factor * Factor2, "Byte");
                while (timer.wantsMoreDataPoints()) {
                    timer.Start();
                    for (int j = 0; j < Factor2; ++j) {
                        for (int i = 0; i < Factor; i += 4) {
                            const Vector &tmp0 = a[i + 0]; keepResults(tmp0);
                            const Vector &tmp1 = a[i + 1]; keepResults(tmp1);
                            const Vector &tmp2 = a[i + 2]; keepResults(tmp2);
                            const Vector &tmp3 = a[i + 3]; keepResults(tmp3);
                        }
                    }
                    timer.Stop();
                }
                timer.Print();
            }
            delete[] a;
        }
};

int bmain()
{
    Benchmark::addColumn("MemorySize");

    DoMemIos<float_v>::run();

    return 0;
}
<commit_msg>test double_v and short_v in memio too<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc 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 for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "benchmark.h"
#include "random.h"
#include "../cpuid.h"
#include <cstdio>
#include <cstdlib>

using namespace Vc;

template<typename T, int S> struct KeepResultsHelper { static inline void keep(const T &tmp0) { asm volatile(""::"r"(tmp0)); } };
#ifdef VC_IMPL_SSE
template<typename T> struct KeepResultsHelper<T, 16> { static inline void keep(const T &tmp0) { asm volatile(""::"x"(reinterpret_cast<const __m128 &>(tmp0))); } };
template<typename T> struct KeepResultsHelper<T, 32> { static inline void keep(const T &tmp0) {
    asm volatile(""::"x"(reinterpret_cast<const __m128 &>(tmp0)), "x"(reinterpret_cast<const __m128 *>(&tmp0)[1]));
} };
#endif
#ifdef VC_IMPL_LRBni
template<typename T> struct KeepResultsHelper<T, 64> { static inline void keep(const T &tmp0) {
    asm volatile(""::"x"(reinterpret_cast<const __m128 &>(tmp0)), "x"(reinterpret_cast<const __m128 *>(&tmp0)[1]), "x"(reinterpret_cast<const __m128 *>(&tmp0)[2]), "x"(reinterpret_cast<const __m128 *>(&tmp0)[3]));
} };
#endif

template<typename T> static inline void keepResults(const T &tmp0)
{
    KeepResultsHelper<T, sizeof(T)>::keep(tmp0);
}

template<typename Vector> class DoMemIos
{
    public:
        static void run()
        {
            Benchmark::setColumnData("MemorySize", "half L1");
            run(CpuId::L1Data() / (sizeof(Vector) * 2), 128);
            Benchmark::setColumnData("MemorySize", "L1");
            run(CpuId::L1Data() / (sizeof(Vector) * 1), 128);
            Benchmark::setColumnData("MemorySize", "half L2");
            run(CpuId::L2Data() / (sizeof(Vector) * 2), 32);
            Benchmark::setColumnData("MemorySize", "L2");
            run(CpuId::L2Data() / (sizeof(Vector) * 1), 16);
            if (CpuId::L3Data() > 0) {
                Benchmark::setColumnData("MemorySize", "half L3");
                run(CpuId::L3Data() / (sizeof(Vector) * 2), 2);
                Benchmark::setColumnData("MemorySize", "L3");
                run(CpuId::L3Data() / (sizeof(Vector) * 1), 2);
                Benchmark::setColumnData("MemorySize", "4x L3");
                run(CpuId::L3Data() / sizeof(Vector) * 4, 1);
            } else {
                Benchmark::setColumnData("MemorySize", "4x L2");
                run(CpuId::L2Data() / sizeof(Vector) * 4, 1);
            }
        }
    private:
        static void run(const int Factor, const int Factor2)
        {
            Vector *a = new Vector[Factor];
#ifndef VC_BENCHMARK_NO_MLOCK
            mlock(a, Factor * sizeof(Vector));
#endif

            {
                Benchmark bm("write", sizeof(Vector) * Factor * Factor2, "Byte");
                const Vector foo = PseudoRandom<Vector>::next();
                keepResults(foo);
                for (int i = 0; i < Factor; i += 4) {
                    a[i + 0] = foo;
                    a[i + 1] = foo;
                    a[i + 2] = foo;
                    a[i + 3] = foo;
                }
                while (bm.wantsMoreDataPoints()) {
                    bm.Start();
                    for (int j = 0; j < Factor2; ++j) {
                        keepResults(foo);
                        for (int i = 0; i < Factor; i += 4) {
                            a[i + 0] = foo;
                            a[i + 1] = foo;
                            a[i + 2] = foo;
                            a[i + 3] = foo;
                        }
                    }
                    bm.Stop();
                }
                bm.Print();
            }
            {
                Benchmark timer("r/w", sizeof(Vector) * Factor * Factor2, "Byte");
                const Vector foo = PseudoRandom<Vector>::next();
                while (timer.wantsMoreDataPoints()) {
                    timer.Start();
                    for (int j = 0; j < Factor2; ++j) {
                        keepResults(foo);
                        for (int i = 0; i < Factor; i += 4) {
                            const Vector &tmp0 = a[i + 0]; keepResults(tmp0);
                            a[i + 0] = foo;
                            const Vector &tmp1 = a[i + 1]; keepResults(tmp1);
                            a[i + 1] = foo;
                            const Vector &tmp2 = a[i + 2]; keepResults(tmp2);
                            a[i + 2] = foo;
                            const Vector &tmp3 = a[i + 3]; keepResults(tmp3);
                            a[i + 3] = foo;
                        }
                    }
                    timer.Stop();
                }
                timer.Print();
            }
            {
                Benchmark timer("read", sizeof(Vector) * Factor * Factor2, "Byte");
                while (timer.wantsMoreDataPoints()) {
                    timer.Start();
                    for (int j = 0; j < Factor2; ++j) {
                        for (int i = 0; i < Factor; i += 4) {
                            const Vector &tmp0 = a[i + 0]; keepResults(tmp0);
                            const Vector &tmp1 = a[i + 1]; keepResults(tmp1);
                            const Vector &tmp2 = a[i + 2]; keepResults(tmp2);
                            const Vector &tmp3 = a[i + 3]; keepResults(tmp3);
                        }
                    }
                    timer.Stop();
                }
                timer.Print();
            }
            delete[] a;
        }
};

int bmain()
{
    Benchmark::addColumn("MemorySize");
    Benchmark::addColumn("datatype");

    Benchmark::setColumnData("datatype", "double_v");
    DoMemIos<double_v>::run();
    Benchmark::setColumnData("datatype", "float_v");
    DoMemIos<float_v>::run();
    Benchmark::setColumnData("datatype", "short_v");
    DoMemIos<short_v>::run();

    return 0;
}
<|endoftext|>


<commit_before>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    int greatest = 0;
    int value = 0;
    int index = 0;
    int iteration = 0;
    // pushing all the greatest values on each k-elements to the front of the deque
    for (int i = 0; i < n; ) {
        if (index < k) {
            value = arr[i];
            if (value > greatest)
                greatest = value;
            if (index == k - 1) {
                mydeque.push_front(greatest);
                greatest = 0;
                index = 0;
                iteration++;
                i = iteration;
            } else {
                index++;
                i++;
            }
        }
    }
    // pop-ing the greatest values from the back of the deque
    while(mydeque.size() > 0) {
        cout << mydeque.back() << " ";
        mydeque.pop_back();
    }
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<commit_msg>Starts solution for the Deque-STL challenge.<commit_after>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    int greatest = 0;
    int value = 0;
    int index = 0;
    int iteration = 0;
    /*
     * pushing all the greatest values on each k-elements to the front of the deque
     */
    for (int i = 0; i < n; ) {
        if (index < k) {
            value = arr[i];
            if (value > greatest)
                greatest = value;
            if (index == k - 1) {
                mydeque.push_front(greatest);
                greatest = 0;
                index = 0;
                iteration++;
                i = iteration;
            } else {
                index++;
                i++;
            }
        }
    }
    /*
     * pop-ing the greatest values from the back of the deque
     */
    while(mydeque.size() > 0) {
        cout << mydeque.back() << " ";
        mydeque.pop_back();
    }
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "VideoWidget.h"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QVariant>
#include <QObject>
#include <QDebug>

#include <gst/interfaces/xoverlay.h>

#ifdef Q_WS_X11
extern void qt_x11_set_global_double_buffer(bool);
#endif

namespace TelepathyIM
{
    VideoWidget::VideoWidget(GstBus *bus,  QWidget *parent, const QString &name)
        : Communication::VideoWidgetInterface(parent),
          bus_((GstBus *) gst_object_ref(bus)),
          video_overlay_(0),
          video_playback_element_(0),
          video_bin_(0),
          name_(name),
          window_id_(0),
          on_element_added_g_signal_(0),
          on_sync_message_g_signal_(0)

    {
        qDebug() << "VideoWidget " << name << " INIT STARTED";
        setWindowTitle(name);

        // Element notifier init
        notifier_ = fs_element_added_notifier_new();
        on_element_added_g_signal_ = g_signal_connect(notifier_, "element-added", G_CALLBACK(&VideoWidget::OnElementAdded), this);

// UNIX -> autovideosink
#ifdef Q_WS_X11

        qt_x11_set_global_double_buffer(false);

        video_playback_element_ = gst_element_factory_make("autovideosink", name.toStdString().c_str());
        gst_object_ref(video_playback_element_);
        gst_object_sink(video_playback_element_);

        fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));

#endif

// WINDOWS -> autovideosink will chose one of there: glimagesink (best), directdrawsink (possible buffer errors), dshowvideosink (possible buffer errors)
#ifdef Q_WS_WIN

        video_playback_element_ = gst_element_factory_make("glimagesink", 0);
        if (!video_playback_element_)
        {
            qDebug() << "VideoWidget " << name << " CANNOT CREATE video_playback_element_";
            return;
        }

		//if (!video_playback_element_)
		//{
		//	fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));
		//	gst_object_ref(video_playback_element_);
		//	gst_object_sink(video_playback_element_);
		//}
		//else
		//{
			// Video bin init
			const QString video_bin_name = "video_bin_for_" + name;
			video_bin_ = gst_bin_new(video_bin_name.toStdString().c_str());
			if (!video_bin_)
			{
				qDebug() << "VideoWidget " << name << " CANNOT CREATE video_bin_";
				return;
			}

			// Add playback element to video bin
			gst_bin_add(GST_BIN(video_bin_), video_playback_element_);

			// Pad inits
			GstPad *static_sink_pad = gst_element_get_static_pad(video_playback_element_, "sink");
			GstPad *sink_ghost_pad = gst_ghost_pad_new("sink", static_sink_pad);

			// Add bad to video bin
			gst_element_add_pad(GST_ELEMENT(video_bin_), sink_ghost_pad);
			gst_object_unref(G_OBJECT(static_sink_pad));
			gst_object_ref(video_bin_);
			gst_object_sink(video_bin_);

			fs_element_added_notifier_add(notifier_, GST_BIN(video_bin_));
		//}

#endif

        gst_bus_enable_sync_message_emission(bus_);
        on_sync_message_g_signal_ = g_signal_connect(bus_, "sync-message", G_CALLBACK(&VideoWidget::OnSyncMessage), this);

        qDebug() << "VideoWidget " << name << " INIT COMPLETE";

        // QWidget properties
        QPalette palette;
        palette.setColor(QPalette::Background, Qt::black);
        palette.setColor(QPalette::Window, Qt::black);
        setPalette(palette);
        setAutoFillBackground(true);
        setAttribute(Qt::WA_NoSystemBackground, true);
        setAttribute(Qt::WA_PaintOnScreen, true);
        resize(322, 240);
        setMinimumSize(322, 240);
    }

    VideoWidget::~VideoWidget()
    {
        if (notifier_)
        {
            fs_element_added_notifier_remove(notifier_, GST_BIN(video_playback_element_));
            g_signal_handler_disconnect(notifier_, on_element_added_g_signal_);
        }
        if (bus_)
            g_signal_handler_disconnect(bus_, on_sync_message_g_signal_);

        if (bus_)
        {
            g_object_unref(bus_);
            bus_ = 0;
        }
        if (video_playback_element_)
        {
            if (GST_BIN(video_playback_element_))
                g_object_unref(video_playback_element_);
            video_playback_element_ = 0;
        }
        if (video_bin_)
        {
            g_object_unref(video_bin_);
            video_bin_ = 0;
        }
        // todo unconnect signals ?
    }

    void VideoWidget::OnElementAdded(FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, VideoWidget *self)
    {
        // If element implements GST_X_OVERLAY interface, set local video_overlay_ to element
        // If true element = the current video sink
        if (!self->video_overlay_ && GST_IS_X_OVERLAY(element))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> Got overlay element, storing";
            self->video_overlay_ = element;
            QMetaObject::invokeMethod(self, "WindowExposed", Qt::QueuedConnection);
        }

        // If element has property force-aspect-ratio set it to true
        // If true element = the current video sink
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "force-aspect-ratio"))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> found 'force-aspect-ratio' from element";
            g_object_set(G_OBJECT(element), "force-aspect-ratio", TRUE, NULL);
        }
    }

    void VideoWidget::OnSyncMessage(GstBus *bus, GstMessage *message, VideoWidget *self)
    {
        // Return if we are not interested in the message content
        if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
            return;
        if (GST_MESSAGE_SRC(message) != (GstObject *)self->video_overlay_)
            return;

        // If message is about preparing xwindow id its from the current video sink
        // and we want to set our own qt widget window id where we want to render video
        const GstStructure *s = gst_message_get_structure(message);
        if (gst_structure_has_name(s, "prepare-xwindow-id") && self->video_overlay_)
        {
            qDebug() << self->name_ << " >> sync-message CALLBACK >> found 'prepare-xwindow-id' from GstMessage";
            QMetaObject::invokeMethod(self, "SetOverlay", Qt::QueuedConnection);
        }
    }

    void VideoWidget::showEvent(QShowEvent *showEvent)
    {
        // Override showEvent so we can set QWidget attributes and set overlay
        qDebug() << name_ << " >> QWidget::showEvent() override called";
        QWidget::showEvent(showEvent);
        SetOverlay();
    }

    void VideoWidget::SetOverlay()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Get window id from this widget and set it for video sink
            // so it renders to our widget id and does not open separate window (that is the default behaviour)
            qDebug() << name_ << " >> SetOverlay() called";
			window_id_ = winId();
            if (window_id_)
            {
                qDebug() << name_ << " >> Giving x overlay widgets window id " << window_id_;
                #ifdef Q_WS_X11
                    QApplication::syncX();
                #endif
                gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(video_overlay_), (gulong)window_id_);
            }
        }
        WindowExposed();
    }

    void VideoWidget::WindowExposed()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Expose the overlay (some sort of update)
            qDebug() << name_ << " >> WindowExposed() called";
            #ifdef Q_WS_X11
                QApplication::syncX();
            #endif
            gst_x_overlay_expose(GST_X_OVERLAY(video_overlay_));
        }
    }

	GstElement *VideoWidget::GetVideoPlaybackElement() const
	{
		if (video_bin_)
			return video_bin_;
		else if (video_playback_element_)
			return video_playback_element_;
		else
			return 0;
	}

    bool VideoWidget::VideoAvailable()
    {
        if (video_overlay_)
            return true;
        else
            return false;
    }

}
<commit_msg>remove unnecessary gst unref call<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "VideoWidget.h"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QVariant>
#include <QObject>
#include <QDebug>

#include <gst/interfaces/xoverlay.h>

#ifdef Q_WS_X11
extern void qt_x11_set_global_double_buffer(bool);
#endif

namespace TelepathyIM
{
    VideoWidget::VideoWidget(GstBus *bus,  QWidget *parent, const QString &name)
        : Communication::VideoWidgetInterface(parent),
          bus_((GstBus *) gst_object_ref(bus)),
          video_overlay_(0),
          video_playback_element_(0),
          video_bin_(0),
          name_(name),
          window_id_(0),
          on_element_added_g_signal_(0),
          on_sync_message_g_signal_(0)

    {
        qDebug() << "VideoWidget " << name << " INIT STARTED";
        setWindowTitle(name);

        // Element notifier init
        notifier_ = fs_element_added_notifier_new();
        on_element_added_g_signal_ = g_signal_connect(notifier_, "element-added", G_CALLBACK(&VideoWidget::OnElementAdded), this);

// UNIX -> autovideosink
#ifdef Q_WS_X11

        qt_x11_set_global_double_buffer(false);

        video_playback_element_ = gst_element_factory_make("autovideosink", name.toStdString().c_str());
        gst_object_ref(video_playback_element_);
        gst_object_sink(video_playback_element_);

        fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));

#endif

// WINDOWS -> autovideosink will chose one of there: glimagesink (best), directdrawsink (possible buffer errors), dshowvideosink (possible buffer errors)
#ifdef Q_WS_WIN

        video_playback_element_ = gst_element_factory_make("glimagesink", 0);
        if (!video_playback_element_)
        {
            qDebug() << "VideoWidget " << name << " CANNOT CREATE video_playback_element_";
            return;
        }

		//if (!video_playback_element_)
		//{
		//	fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));
		//	gst_object_ref(video_playback_element_);
		//	gst_object_sink(video_playback_element_);
		//}
		//else
		//{
			// Video bin init
			const QString video_bin_name = "video_bin_for_" + name;
			video_bin_ = gst_bin_new(video_bin_name.toStdString().c_str());
			if (!video_bin_)
			{
				qDebug() << "VideoWidget " << name << " CANNOT CREATE video_bin_";
				return;
			}

			// Add playback element to video bin
			gst_bin_add(GST_BIN(video_bin_), video_playback_element_);

			// Pad inits
			GstPad *static_sink_pad = gst_element_get_static_pad(video_playback_element_, "sink");
			GstPad *sink_ghost_pad = gst_ghost_pad_new("sink", static_sink_pad);

			// Add bad to video bin
			gst_element_add_pad(GST_ELEMENT(video_bin_), sink_ghost_pad);
			gst_object_unref(G_OBJECT(static_sink_pad));
			gst_object_ref(video_bin_);
			gst_object_sink(video_bin_);

			fs_element_added_notifier_add(notifier_, GST_BIN(video_bin_));
		//}

#endif

        gst_bus_enable_sync_message_emission(bus_);
        on_sync_message_g_signal_ = g_signal_connect(bus_, "sync-message", G_CALLBACK(&VideoWidget::OnSyncMessage), this);

        qDebug() << "VideoWidget " << name << " INIT COMPLETE";

        // QWidget properties
        QPalette palette;
        palette.setColor(QPalette::Background, Qt::black);
        palette.setColor(QPalette::Window, Qt::black);
        setPalette(palette);
        setAutoFillBackground(true);
        setAttribute(Qt::WA_NoSystemBackground, true);
        setAttribute(Qt::WA_PaintOnScreen, true);
        resize(322, 240);
        setMinimumSize(322, 240);
    }

    VideoWidget::~VideoWidget()
    {
        if (notifier_)
        {
            fs_element_added_notifier_remove(notifier_, GST_BIN(video_playback_element_));
            g_signal_handler_disconnect(notifier_, on_element_added_g_signal_);
        }
        if (bus_)
            g_signal_handler_disconnect(bus_, on_sync_message_g_signal_);

        if (bus_)
        {
            g_object_unref(bus_);
            bus_ = 0;
        }
        if (video_playback_element_)
        {
            //if (GST_BIN(video_playback_element_))
            //    g_object_unref(video_playback_element_);
            video_playback_element_ = 0;
        }
        if (video_bin_)
        {
            g_object_unref(video_bin_);
            video_bin_ = 0;
        }
        // todo unconnect signals ?
    }

    void VideoWidget::OnElementAdded(FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, VideoWidget *self)
    {
        // If element implements GST_X_OVERLAY interface, set local video_overlay_ to element
        // If true element = the current video sink
        if (!self->video_overlay_ && GST_IS_X_OVERLAY(element))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> Got overlay element, storing";
            self->video_overlay_ = element;
            QMetaObject::invokeMethod(self, "WindowExposed", Qt::QueuedConnection);
        }

        // If element has property force-aspect-ratio set it to true
        // If true element = the current video sink
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "force-aspect-ratio"))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> found 'force-aspect-ratio' from element";
            g_object_set(G_OBJECT(element), "force-aspect-ratio", TRUE, NULL);
        }
    }

    void VideoWidget::OnSyncMessage(GstBus *bus, GstMessage *message, VideoWidget *self)
    {
        // Return if we are not interested in the message content
        if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
            return;
        if (GST_MESSAGE_SRC(message) != (GstObject *)self->video_overlay_)
            return;

        // If message is about preparing xwindow id its from the current video sink
        // and we want to set our own qt widget window id where we want to render video
        const GstStructure *s = gst_message_get_structure(message);
        if (gst_structure_has_name(s, "prepare-xwindow-id") && self->video_overlay_)
        {
            qDebug() << self->name_ << " >> sync-message CALLBACK >> found 'prepare-xwindow-id' from GstMessage";
            QMetaObject::invokeMethod(self, "SetOverlay", Qt::QueuedConnection);
        }
    }

    void VideoWidget::showEvent(QShowEvent *showEvent)
    {
        // Override showEvent so we can set QWidget attributes and set overlay
        qDebug() << name_ << " >> QWidget::showEvent() override called";
        QWidget::showEvent(showEvent);
        SetOverlay();
    }

    void VideoWidget::SetOverlay()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Get window id from this widget and set it for video sink
            // so it renders to our widget id and does not open separate window (that is the default behaviour)
            qDebug() << name_ << " >> SetOverlay() called";
			window_id_ = winId();
            if (window_id_)
            {
                qDebug() << name_ << " >> Giving x overlay widgets window id " << window_id_;
                #ifdef Q_WS_X11
                    QApplication::syncX();
                #endif
                gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(video_overlay_), (gulong)window_id_);
            }
        }
        WindowExposed();
    }

    void VideoWidget::WindowExposed()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Expose the overlay (some sort of update)
            qDebug() << name_ << " >> WindowExposed() called";
            #ifdef Q_WS_X11
                QApplication::syncX();
            #endif
            gst_x_overlay_expose(GST_X_OVERLAY(video_overlay_));
        }
    }

	GstElement *VideoWidget::GetVideoPlaybackElement() const
	{
		if (video_bin_)
			return video_bin_;
		else if (video_playback_element_)
			return video_playback_element_;
		else
			return 0;
	}

    bool VideoWidget::VideoAvailable()
    {
        if (video_overlay_)
            return true;
        else
            return false;
    }

}
<|endoftext|>