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

#include <algorithm>

#include "base/logging.h"
#include "base/rand_util.h"
#include "base/stl_util-inl.h"
#include "chrome/browser/autofill/autofill_xml_parser.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "net/http/http_response_headers.h"

#define DISABLED_REQUEST_URL "http://disabled"

#if defined(GOOGLE_CHROME_BUILD)
#include "chrome/browser/autofill/internal/autofill_download_internal.h"
#else
#define AUTO_FILL_QUERY_SERVER_REQUEST_URL DISABLED_REQUEST_URL
#define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL DISABLED_REQUEST_URL
#define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "SOMESERVER/"
#endif

struct AutoFillDownloadManager::FormRequestData {
  std::vector<std::string> form_signatures;
  AutoFillRequestType request_type;
};

AutoFillDownloadManager::AutoFillDownloadManager(Profile* profile)
    : profile_(profile),
      observer_(NULL),
      next_query_request_(base::Time::Now()),
      next_upload_request_(base::Time::Now()),
      positive_upload_rate_(0),
      negative_upload_rate_(0),
      fetcher_id_for_unittest_(0),
      is_testing_(false) {
  // |profile_| could be NULL in some unit-tests.
  if (profile_) {
    PrefService* preferences = profile_->GetPrefs();
    positive_upload_rate_ =
        preferences->GetReal(prefs::kAutoFillPositiveUploadRate);
    negative_upload_rate_ =
        preferences->GetReal(prefs::kAutoFillNegativeUploadRate);
  }
}

AutoFillDownloadManager::~AutoFillDownloadManager() {
  STLDeleteContainerPairFirstPointers(url_fetchers_.begin(),
                                      url_fetchers_.end());
}

void AutoFillDownloadManager::SetObserver(
    AutoFillDownloadManager::Observer *observer) {
  if (observer) {
    DCHECK(!observer_);
    observer_ = observer;
  } else {
    observer_ = NULL;
  }
}

bool AutoFillDownloadManager::StartQueryRequest(
    const ScopedVector<FormStructure>& forms) {
  if (next_query_request_ > base::Time::Now()) {
    // We are in back-off mode: do not do the request.
    return false;
  }
  std::string form_xml;
  FormRequestData request_data;
  if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
                                         &form_xml))
    return false;

  request_data.request_type = AutoFillDownloadManager::REQUEST_QUERY;

  return StartRequest(form_xml, request_data);
}

bool AutoFillDownloadManager::StartUploadRequest(
    const FormStructure& form, bool form_was_matched) {
  if (next_upload_request_ > base::Time::Now()) {
    // We are in back-off mode: do not do the request.
    return false;
  }

  // Check if we need to upload form.
  double upload_rate = form_was_matched ? GetPositiveUploadRate() :
                                          GetNegativeUploadRate();
  if (base::RandDouble() > upload_rate) {
    VLOG(1) << "AutoFillDownloadManager: Upload request is ignored";
    // If we ever need notification that upload was skipped, add it here.
    return false;
  }
  std::string form_xml;
  if (!form.EncodeUploadRequest(form_was_matched, &form_xml))
    return false;

  FormRequestData request_data;
  request_data.form_signatures.push_back(form.FormSignature());
  request_data.request_type = AutoFillDownloadManager::REQUEST_UPLOAD;

  return StartRequest(form_xml, request_data);
}

bool AutoFillDownloadManager::CancelRequest(
    const std::string& form_signature,
    AutoFillDownloadManager::AutoFillRequestType request_type) {
  for (std::map<URLFetcher *, FormRequestData>::iterator it =
       url_fetchers_.begin();
       it != url_fetchers_.end();
       ++it) {
    if (std::find(it->second.form_signatures.begin(),
        it->second.form_signatures.end(), form_signature) !=
        it->second.form_signatures.end() &&
        it->second.request_type == request_type) {
      delete it->first;
      url_fetchers_.erase(it);
      return true;
    }
  }
  return false;
}

double AutoFillDownloadManager::GetPositiveUploadRate() const {
  return positive_upload_rate_;
}

double AutoFillDownloadManager::GetNegativeUploadRate() const {
  return negative_upload_rate_;
}

void AutoFillDownloadManager::SetPositiveUploadRate(double rate) {
  if (rate == positive_upload_rate_)
    return;
  positive_upload_rate_ = rate;
  DCHECK_GE(rate, 0.0);
  DCHECK_LE(rate, 1.0);
  DCHECK(profile_);
  PrefService* preferences = profile_->GetPrefs();
  preferences->SetReal(prefs::kAutoFillPositiveUploadRate, rate);
}

void AutoFillDownloadManager::SetNegativeUploadRate(double rate) {
  if (rate == negative_upload_rate_)
    return;
  negative_upload_rate_ = rate;
  DCHECK_GE(rate, 0.0);
  DCHECK_LE(rate, 1.0);
  DCHECK(profile_);
  PrefService* preferences = profile_->GetPrefs();
  preferences->SetReal(prefs::kAutoFillNegativeUploadRate, rate);
}

bool AutoFillDownloadManager::StartRequest(
    const std::string& form_xml,
    const FormRequestData& request_data) {
  std::string request_url;
  if (request_data.request_type == AutoFillDownloadManager::REQUEST_QUERY)
    request_url = AUTO_FILL_QUERY_SERVER_REQUEST_URL;
  else
    request_url = AUTO_FILL_UPLOAD_SERVER_REQUEST_URL;

  if (!request_url.compare(DISABLED_REQUEST_URL) && !is_testing_) {
    // We have it disabled - return true as if it succeeded, but do nothing.
    return true;
  }

  // Id is ignored for regular chrome, in unit test id's for fake fetcher
  // factory will be 0, 1, 2, ...
  URLFetcher *fetcher = URLFetcher::Create(fetcher_id_for_unittest_++,
                                           GURL(request_url),
                                           URLFetcher::POST,
                                           this);
  url_fetchers_[fetcher] = request_data;
  fetcher->set_automatically_retry_on_5xx(false);
  fetcher->set_request_context(Profile::GetDefaultRequestContext());
  fetcher->set_upload_data("text/plain", form_xml);
  fetcher->Start();
  return true;
}

void AutoFillDownloadManager::OnURLFetchComplete(const URLFetcher* source,
                                                 const GURL& url,
                                                 const URLRequestStatus& status,
                                                 int response_code,
                                                 const ResponseCookies& cookies,
                                                 const std::string& data) {
  std::map<URLFetcher *, FormRequestData>::iterator it =
      url_fetchers_.find(const_cast<URLFetcher*>(source));
  if (it == url_fetchers_.end()) {
    // Looks like crash on Mac is possibly caused with callback entering here
    // with unknown fetcher when network is refreshed.
    return;
  }
  std::string type_of_request(
      it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY ?
          "query" : "upload");
  const int kHttpResponseOk = 200;
  const int kHttpInternalServerError = 500;
  const int kHttpBadGateway = 502;
  const int kHttpServiceUnavailable = 503;

  CHECK(it->second.form_signatures.size());
  if (response_code != kHttpResponseOk) {
    bool back_off = false;
    std::string server_header;
    switch (response_code) {
      case kHttpBadGateway:
        if (!source->response_headers()->EnumerateHeader(NULL, "server",
                                                         &server_header) ||
            StartsWithASCII(server_header.c_str(),
                            AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER,
                            false) != 0)
          break;
        // Bad getaway was received from AutoFill servers. Fall through to back
        // off.
      case kHttpInternalServerError:
      case kHttpServiceUnavailable:
        back_off = true;
        break;
    }

    if (back_off) {
      base::Time back_off_time(base::Time::Now() + source->backoff_delay());
      if (it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY) {
        next_query_request_ = back_off_time;
      } else {
        next_upload_request_ = back_off_time;
      }
    }

    LOG(WARNING) << "AutoFillDownloadManager: " << type_of_request
                 << " request has failed with response" << response_code;
    if (observer_) {
      observer_->OnHeuristicsRequestError(it->second.form_signatures[0],
                                          it->second.request_type,
                                          response_code);
    }
  } else {
    VLOG(1) << "AutoFillDownloadManager: " << type_of_request
            << " request has succeeded";
    if (it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY) {
      if (observer_)
        observer_->OnLoadedAutoFillHeuristics(data);
    } else {
      double new_positive_upload_rate = 0;
      double new_negative_upload_rate = 0;
      AutoFillUploadXmlParser parse_handler(&new_positive_upload_rate,
                                            &new_negative_upload_rate);
      buzz::XmlParser parser(&parse_handler);
      parser.Parse(data.data(), data.length(), true);
      if (parse_handler.succeeded()) {
        SetPositiveUploadRate(new_positive_upload_rate);
        SetNegativeUploadRate(new_negative_upload_rate);
      }

      if (observer_)
        observer_->OnUploadedAutoFillHeuristics(it->second.form_signatures[0]);
    }
  }
  delete it->first;
  url_fetchers_.erase(it);
}

<commit_msg>Fix a small typo in AutoFillDownloadManager::OnURLFetchComplete.<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/autofill/autofill_download.h"

#include <algorithm>
#include <vector>

#include "base/logging.h"
#include "base/rand_util.h"
#include "base/stl_util-inl.h"
#include "chrome/browser/autofill/autofill_xml_parser.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "net/http/http_response_headers.h"

#define DISABLED_REQUEST_URL "http://disabled"

#if defined(GOOGLE_CHROME_BUILD)
#include "chrome/browser/autofill/internal/autofill_download_internal.h"
#else
#define AUTO_FILL_QUERY_SERVER_REQUEST_URL DISABLED_REQUEST_URL
#define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL DISABLED_REQUEST_URL
#define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "SOMESERVER/"
#endif

struct AutoFillDownloadManager::FormRequestData {
  std::vector<std::string> form_signatures;
  AutoFillRequestType request_type;
};

AutoFillDownloadManager::AutoFillDownloadManager(Profile* profile)
    : profile_(profile),
      observer_(NULL),
      next_query_request_(base::Time::Now()),
      next_upload_request_(base::Time::Now()),
      positive_upload_rate_(0),
      negative_upload_rate_(0),
      fetcher_id_for_unittest_(0),
      is_testing_(false) {
  // |profile_| could be NULL in some unit-tests.
  if (profile_) {
    PrefService* preferences = profile_->GetPrefs();
    positive_upload_rate_ =
        preferences->GetReal(prefs::kAutoFillPositiveUploadRate);
    negative_upload_rate_ =
        preferences->GetReal(prefs::kAutoFillNegativeUploadRate);
  }
}

AutoFillDownloadManager::~AutoFillDownloadManager() {
  STLDeleteContainerPairFirstPointers(url_fetchers_.begin(),
                                      url_fetchers_.end());
}

void AutoFillDownloadManager::SetObserver(
    AutoFillDownloadManager::Observer *observer) {
  if (observer) {
    DCHECK(!observer_);
    observer_ = observer;
  } else {
    observer_ = NULL;
  }
}

bool AutoFillDownloadManager::StartQueryRequest(
    const ScopedVector<FormStructure>& forms) {
  if (next_query_request_ > base::Time::Now()) {
    // We are in back-off mode: do not do the request.
    return false;
  }
  std::string form_xml;
  FormRequestData request_data;
  if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
                                         &form_xml))
    return false;

  request_data.request_type = AutoFillDownloadManager::REQUEST_QUERY;

  return StartRequest(form_xml, request_data);
}

bool AutoFillDownloadManager::StartUploadRequest(
    const FormStructure& form, bool form_was_matched) {
  if (next_upload_request_ > base::Time::Now()) {
    // We are in back-off mode: do not do the request.
    return false;
  }

  // Check if we need to upload form.
  double upload_rate = form_was_matched ? GetPositiveUploadRate() :
                                          GetNegativeUploadRate();
  if (base::RandDouble() > upload_rate) {
    VLOG(1) << "AutoFillDownloadManager: Upload request is ignored";
    // If we ever need notification that upload was skipped, add it here.
    return false;
  }
  std::string form_xml;
  if (!form.EncodeUploadRequest(form_was_matched, &form_xml))
    return false;

  FormRequestData request_data;
  request_data.form_signatures.push_back(form.FormSignature());
  request_data.request_type = AutoFillDownloadManager::REQUEST_UPLOAD;

  return StartRequest(form_xml, request_data);
}

bool AutoFillDownloadManager::CancelRequest(
    const std::string& form_signature,
    AutoFillDownloadManager::AutoFillRequestType request_type) {
  for (std::map<URLFetcher *, FormRequestData>::iterator it =
       url_fetchers_.begin();
       it != url_fetchers_.end();
       ++it) {
    if (std::find(it->second.form_signatures.begin(),
        it->second.form_signatures.end(), form_signature) !=
        it->second.form_signatures.end() &&
        it->second.request_type == request_type) {
      delete it->first;
      url_fetchers_.erase(it);
      return true;
    }
  }
  return false;
}

double AutoFillDownloadManager::GetPositiveUploadRate() const {
  return positive_upload_rate_;
}

double AutoFillDownloadManager::GetNegativeUploadRate() const {
  return negative_upload_rate_;
}

void AutoFillDownloadManager::SetPositiveUploadRate(double rate) {
  if (rate == positive_upload_rate_)
    return;
  positive_upload_rate_ = rate;
  DCHECK_GE(rate, 0.0);
  DCHECK_LE(rate, 1.0);
  DCHECK(profile_);
  PrefService* preferences = profile_->GetPrefs();
  preferences->SetReal(prefs::kAutoFillPositiveUploadRate, rate);
}

void AutoFillDownloadManager::SetNegativeUploadRate(double rate) {
  if (rate == negative_upload_rate_)
    return;
  negative_upload_rate_ = rate;
  DCHECK_GE(rate, 0.0);
  DCHECK_LE(rate, 1.0);
  DCHECK(profile_);
  PrefService* preferences = profile_->GetPrefs();
  preferences->SetReal(prefs::kAutoFillNegativeUploadRate, rate);
}

bool AutoFillDownloadManager::StartRequest(
    const std::string& form_xml,
    const FormRequestData& request_data) {
  std::string request_url;
  if (request_data.request_type == AutoFillDownloadManager::REQUEST_QUERY)
    request_url = AUTO_FILL_QUERY_SERVER_REQUEST_URL;
  else
    request_url = AUTO_FILL_UPLOAD_SERVER_REQUEST_URL;

  if (!request_url.compare(DISABLED_REQUEST_URL) && !is_testing_) {
    // We have it disabled - return true as if it succeeded, but do nothing.
    return true;
  }

  // Id is ignored for regular chrome, in unit test id's for fake fetcher
  // factory will be 0, 1, 2, ...
  URLFetcher *fetcher = URLFetcher::Create(fetcher_id_for_unittest_++,
                                           GURL(request_url),
                                           URLFetcher::POST,
                                           this);
  url_fetchers_[fetcher] = request_data;
  fetcher->set_automatically_retry_on_5xx(false);
  fetcher->set_request_context(Profile::GetDefaultRequestContext());
  fetcher->set_upload_data("text/plain", form_xml);
  fetcher->Start();
  return true;
}

void AutoFillDownloadManager::OnURLFetchComplete(const URLFetcher* source,
                                                 const GURL& url,
                                                 const URLRequestStatus& status,
                                                 int response_code,
                                                 const ResponseCookies& cookies,
                                                 const std::string& data) {
  std::map<URLFetcher *, FormRequestData>::iterator it =
      url_fetchers_.find(const_cast<URLFetcher*>(source));
  if (it == url_fetchers_.end()) {
    // Looks like crash on Mac is possibly caused with callback entering here
    // with unknown fetcher when network is refreshed.
    return;
  }
  std::string type_of_request(
      it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY ?
          "query" : "upload");
  const int kHttpResponseOk = 200;
  const int kHttpInternalServerError = 500;
  const int kHttpBadGateway = 502;
  const int kHttpServiceUnavailable = 503;

  CHECK(it->second.form_signatures.size());
  if (response_code != kHttpResponseOk) {
    bool back_off = false;
    std::string server_header;
    switch (response_code) {
      case kHttpBadGateway:
        if (!source->response_headers()->EnumerateHeader(NULL, "server",
                                                         &server_header) ||
            StartsWithASCII(server_header.c_str(),
                            AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER,
                            false) != 0)
          break;
        // Bad getaway was received from AutoFill servers. Fall through to back
        // off.
      case kHttpInternalServerError:
      case kHttpServiceUnavailable:
        back_off = true;
        break;
    }

    if (back_off) {
      base::Time back_off_time(base::Time::Now() + source->backoff_delay());
      if (it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY) {
        next_query_request_ = back_off_time;
      } else {
        next_upload_request_ = back_off_time;
      }
    }

    LOG(WARNING) << "AutoFillDownloadManager: " << type_of_request
                 << " request has failed with response " << response_code;
    if (observer_) {
      observer_->OnHeuristicsRequestError(it->second.form_signatures[0],
                                          it->second.request_type,
                                          response_code);
    }
  } else {
    VLOG(1) << "AutoFillDownloadManager: " << type_of_request
            << " request has succeeded";
    if (it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY) {
      if (observer_)
        observer_->OnLoadedAutoFillHeuristics(data);
    } else {
      double new_positive_upload_rate = 0;
      double new_negative_upload_rate = 0;
      AutoFillUploadXmlParser parse_handler(&new_positive_upload_rate,
                                            &new_negative_upload_rate);
      buzz::XmlParser parser(&parse_handler);
      parser.Parse(data.data(), data.length(), true);
      if (parse_handler.succeeded()) {
        SetPositiveUploadRate(new_positive_upload_rate);
        SetNegativeUploadRate(new_negative_upload_rate);
      }

      if (observer_)
        observer_->OnUploadedAutoFillHeuristics(it->second.form_signatures[0]);
    }
  }
  delete it->first;
  url_fetchers_.erase(it);
}
<|endoftext|>


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

#include "base/file_path.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/page_transition_types.h"
#include "testing/gtest/include/gtest/gtest.h"

using content::NavigationController;
using content::OpenURLParams;
using content::Referrer;

namespace {

void SimulateRendererCrash(Browser* browser) {
  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
      content::NotificationService::AllSources());
  browser->OpenURL(OpenURLParams(
      GURL(chrome::kChromeUICrashURL), Referrer(), CURRENT_TAB,
      content::PAGE_TRANSITION_TYPED, false));
  observer.Wait();
}

}  // namespace

class CrashRecoveryBrowserTest : public InProcessBrowserTest {
};

// Test that reload works after a crash.
// Disabled, http://crbug.com/29331 , http://crbug.com/69637 .
IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, Reload) {
  // The title of the active tab should change each time this URL is loaded.
  GURL url(
      "data:text/html,<script>document.title=new Date().valueOf()</script>");
  ui_test_utils::NavigateToURL(browser(), url);

  string16 title_before_crash;
  string16 title_after_crash;

  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_before_crash));
  SimulateRendererCrash(browser());
  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::Source<NavigationController>(
          &chrome::GetActiveWebContents(browser())->GetController()));
  chrome::Reload(browser(), CURRENT_TAB);
  observer.Wait();
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_after_crash));
  EXPECT_NE(title_before_crash, title_after_crash);
}

// Tests that loading a crashed page in a new tab correctly updates the title.
// There was an earlier bug (1270510) in process-per-site in which the max page
// ID of the RenderProcessHost was stale, so the NavigationEntry in the new tab
// was not committed.  This prevents regression of that bug.
// http://crbug.com/57158 - Times out sometimes on all platforms.
#if defined(OS_LINUX)
// http://crbug.com/144278 - failing on linux
#define MAYBE_LoadInNewTab DISABLED_LoadInNewTab
#else
#define MAYBE_LoadInNewTab LoadInNewTab
#endif

IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, MAYBE_LoadInNewTab) {
  const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html");

  ui_test_utils::NavigateToURL(browser(),
      ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
                                FilePath(kTitle2File)));

  string16 title_before_crash;
  string16 title_after_crash;

  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_before_crash));
  SimulateRendererCrash(browser());
  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::Source<NavigationController>(
          &chrome::GetActiveWebContents(browser())->GetController()));
  chrome::Reload(browser(), CURRENT_TAB);
  observer.Wait();
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_after_crash));
  EXPECT_EQ(title_before_crash, title_after_crash);
}
<commit_msg>Undisable CrashRecoveryBrowserTest.LoadInNewTab, should be OK now.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_path.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/page_transition_types.h"
#include "testing/gtest/include/gtest/gtest.h"

using content::NavigationController;
using content::OpenURLParams;
using content::Referrer;

namespace {

void SimulateRendererCrash(Browser* browser) {
  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
      content::NotificationService::AllSources());
  browser->OpenURL(OpenURLParams(
      GURL(chrome::kChromeUICrashURL), Referrer(), CURRENT_TAB,
      content::PAGE_TRANSITION_TYPED, false));
  observer.Wait();
}

}  // namespace

class CrashRecoveryBrowserTest : public InProcessBrowserTest {
};

// Test that reload works after a crash.
// Disabled, http://crbug.com/29331 , http://crbug.com/69637 .
IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, Reload) {
  // The title of the active tab should change each time this URL is loaded.
  GURL url(
      "data:text/html,<script>document.title=new Date().valueOf()</script>");
  ui_test_utils::NavigateToURL(browser(), url);

  string16 title_before_crash;
  string16 title_after_crash;

  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_before_crash));
  SimulateRendererCrash(browser());
  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::Source<NavigationController>(
          &chrome::GetActiveWebContents(browser())->GetController()));
  chrome::Reload(browser(), CURRENT_TAB);
  observer.Wait();
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_after_crash));
  EXPECT_NE(title_before_crash, title_after_crash);
}

// Tests that loading a crashed page in a new tab correctly updates the title.
// There was an earlier bug (1270510) in process-per-site in which the max page
// ID of the RenderProcessHost was stale, so the NavigationEntry in the new tab
// was not committed.  This prevents regression of that bug.
IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, LoadInNewTab) {
  const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html");

  ui_test_utils::NavigateToURL(browser(),
      ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
                                FilePath(kTitle2File)));

  string16 title_before_crash;
  string16 title_after_crash;

  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_before_crash));
  SimulateRendererCrash(browser());
  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::Source<NavigationController>(
          &chrome::GetActiveWebContents(browser())->GetController()));
  chrome::Reload(browser(), CURRENT_TAB);
  observer.Wait();
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                &title_after_crash));
  EXPECT_EQ(title_before_crash, title_after_crash);
}
<|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/dom_ui/dom_ui_theme_source.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/theme_provider.h"
#include "base/gfx/png_encoder.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "base/time.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/theme_resources_util.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/gurl.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

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

// Path for the New Tab CSS. When we get more than a few of these, we should
// use a resource map rather than hard-coded strings.
static const char* kNewTabCSSPath = "css/newtab.css";

static string16 SkColorToRGBAString(SkColor color) {
  return WideToUTF16(l10n_util::GetStringF(IDS_RGBA_CSS_FORMAT_STRING,
      IntToWString(SkColorGetR(color)),
      IntToWString(SkColorGetG(color)),
      IntToWString(SkColorGetB(color)),
      DoubleToWString(SkColorGetA(color) / 255.0)));
}

static std::string StripQueryParams(const std::string& path) {
  GURL path_url = GURL(std::string(chrome::kChromeUIScheme) + "://" +
                       std::string(chrome::kChromeUIThemePath) + "/" + path);
  return path_url.path().substr(1);  // path() always includes a leading '/'.
}

////////////////////////////////////////////////////////////////////////////////
// DOMUIThemeSource, public:

DOMUIThemeSource::DOMUIThemeSource(Profile* profile)
    : DataSource(chrome::kChromeUIThemePath, MessageLoop::current()),
      profile_(profile) {
}

void DOMUIThemeSource::StartDataRequest(const std::string& path,
                                        int request_id) {
  // Our path may include cachebuster arguments, so trim them off.
  std::string uncached_path = StripQueryParams(path);

  if (strcmp(uncached_path.c_str(), kNewTabCSSPath) == 0) {
    SendNewTabCSS(request_id);
    return;
  } else {
    int resource_id = ThemeResourcesUtil::GetId(uncached_path);
    if (resource_id != -1) {
      SendThemeBitmap(request_id, resource_id);
      return;
    }
  }
  // We don't have any data to send back.
  SendResponse(request_id, NULL);
}

std::string DOMUIThemeSource::GetMimeType(const std::string& path) const {
  std::string uncached_path = StripQueryParams(path);

  if (strcmp(uncached_path.c_str(), kNewTabCSSPath) == 0)
    return "text/css";
  return "image/png";
}

void DOMUIThemeSource::SendResponse(int request_id, RefCountedBytes* data) {
  ChromeURLDataManager::DataSource::SendResponse(request_id, data);
}

////////////////////////////////////////////////////////////////////////////////
// DOMUIThemeSource, private:

void DOMUIThemeSource::SendNewTabCSS(int request_id) {
  ThemeProvider* tp = profile_->GetThemeProvider();
  DCHECK(tp);

  // Get our theme colors
  SkColor color_background =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_BACKGROUND);
  SkColor color_text = tp->GetColor(BrowserThemeProvider::COLOR_NTP_TEXT);
  SkColor color_link = tp->GetColor(BrowserThemeProvider::COLOR_NTP_LINK);
  SkColor color_section =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_SECTION);
  SkColor color_section_text =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_SECTION_TEXT);
  SkColor color_section_link =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_SECTION_LINK);

  // Generate a lighter color.
  skia::HSL section_lighter;
  skia::SkColorToHSL(color_section, section_lighter);
  section_lighter.l += (1 - section_lighter.l) * 0.33;
  SkColor color_section_lighter =
      skia::HSLToSkColor(SkColorGetA(color_section), section_lighter);

  // Generate the replacements.
  std::vector<string16> subst;
  // A second list of replacements, each of which must be in $$x format,
  // where x is a digit from 1-9.
  std::vector<string16> subst2;

  // Cache-buster for background.
  subst.push_back(UTF8ToUTF16(IntToString(static_cast<int>(
      base::Time::Now().ToDoubleT()))));  // $1

  // Colors.
  subst.push_back(SkColorToRGBAString(color_background));  // $2
  subst.push_back(UTF8ToUTF16(GetNewTabBackgroundCSS(false)));  // $3
  subst.push_back(UTF8ToUTF16(GetNewTabBackgroundCSS(true)));  // $4
  subst.push_back(UTF8ToUTF16(GetNewTabBackgroundTilingCSS()));  // $5
  subst.push_back(SkColorToRGBAString(color_section));  // $6
  subst.push_back(SkColorToRGBAString(color_section_lighter));  // $7
  subst.push_back(SkColorToRGBAString(color_text));  // $8
  subst.push_back(SkColorToRGBAString(color_link));  // $9

  subst2.push_back(SkColorToRGBAString(color_section_text));  // $$1
  subst2.push_back(SkColorToRGBAString(color_section_link));  // $$2

  // Get our template.
  static const StringPiece new_tab_theme_css(
      ResourceBundle::GetSharedInstance().GetRawDataResource(
      IDR_NEW_TAB_THEME_CSS));

  // Create the string from our template and the replacements.
  string16 format_string = ASCIIToUTF16(new_tab_theme_css.as_string());
  const std::string css_string = UTF16ToASCII(ReplaceStringPlaceholders(
      format_string, subst, NULL));
  const std::string css_string2 =  UTF16ToASCII(ReplaceStringPlaceholders(
      ASCIIToUTF16(css_string), subst2, NULL));

  // Convert to a format appropriate for sending.
  scoped_refptr<RefCountedBytes> css_bytes(new RefCountedBytes);
  css_bytes->data.resize(css_string2.size());
  std::copy(css_string2.begin(), css_string2.end(), css_bytes->data.begin());

  // Send.
  SendResponse(request_id, css_bytes);
}

void DOMUIThemeSource::SendThemeBitmap(int request_id, int resource_id) {
  ThemeProvider* tp = profile_->GetThemeProvider();
  DCHECK(tp);

  std::vector<unsigned char> png_bytes;
  if (tp->GetRawData(resource_id, &png_bytes)) {
    scoped_refptr<RefCountedBytes> image_data =
        new RefCountedBytes(png_bytes);
    SendResponse(request_id, image_data);
  } else {
    SendResponse(request_id, NULL);
  }
}

std::string DOMUIThemeSource::GetNewTabBackgroundCSS(bool bar_attached) {
  int alignment;
  profile_->GetThemeProvider()->GetDisplayProperty(
      BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &alignment);

  if (bar_attached)
    return BrowserThemeProvider::AlignmentToString(alignment);

  // The bar is detached, so we must offset the background by the bar size
  // if it's a top-aligned bar.
#if defined(OS_WIN)
  int offset = BookmarkBarView::kNewtabBarHeight;
#else
  int offset = 0;
#endif

  // TODO(glen): This is a quick workaround to hide the notused.png image when
  // no image is provided - we don't have time right now to figure out why
  // this is painting as white.
  // http://crbug.com/17593
  if (!profile_->GetThemeProvider()->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
    return "-64px";
  }

  if (alignment & BrowserThemeProvider::ALIGN_TOP) {
    if (alignment & BrowserThemeProvider::ALIGN_LEFT)
      return "0% " + IntToString(-offset) + "px";
    else if (alignment & BrowserThemeProvider::ALIGN_RIGHT)
      return "100% " + IntToString(-offset) + "px";
    return "center " + IntToString(-offset) + "px";
  }
  return BrowserThemeProvider::AlignmentToString(alignment);
}

std::string DOMUIThemeSource::GetNewTabBackgroundTilingCSS() {
  int repeat_mode;
  profile_->GetThemeProvider()->GetDisplayProperty(
      BrowserThemeProvider::NTP_BACKGROUND_TILING, &repeat_mode);
  return BrowserThemeProvider::TilingToString(repeat_mode);
}

<commit_msg>Use the theme ID as as the cache-buster, making subsequent NNTP loads much faster.<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/dom_ui/dom_ui_theme_source.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/theme_provider.h"
#include "base/gfx/png_encoder.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "base/time.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/theme_resources_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/gurl.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

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

// Path for the New Tab CSS. When we get more than a few of these, we should
// use a resource map rather than hard-coded strings.
static const char* kNewTabCSSPath = "css/newtab.css";

static string16 SkColorToRGBAString(SkColor color) {
  return WideToUTF16(l10n_util::GetStringF(IDS_RGBA_CSS_FORMAT_STRING,
      IntToWString(SkColorGetR(color)),
      IntToWString(SkColorGetG(color)),
      IntToWString(SkColorGetB(color)),
      DoubleToWString(SkColorGetA(color) / 255.0)));
}

static std::string StripQueryParams(const std::string& path) {
  GURL path_url = GURL(std::string(chrome::kChromeUIScheme) + "://" +
                       std::string(chrome::kChromeUIThemePath) + "/" + path);
  return path_url.path().substr(1);  // path() always includes a leading '/'.
}

////////////////////////////////////////////////////////////////////////////////
// DOMUIThemeSource, public:

DOMUIThemeSource::DOMUIThemeSource(Profile* profile)
    : DataSource(chrome::kChromeUIThemePath, MessageLoop::current()),
      profile_(profile) {
}

void DOMUIThemeSource::StartDataRequest(const std::string& path,
                                        int request_id) {
  // Our path may include cachebuster arguments, so trim them off.
  std::string uncached_path = StripQueryParams(path);

  if (strcmp(uncached_path.c_str(), kNewTabCSSPath) == 0) {
    SendNewTabCSS(request_id);
    return;
  } else {
    int resource_id = ThemeResourcesUtil::GetId(uncached_path);
    if (resource_id != -1) {
      SendThemeBitmap(request_id, resource_id);
      return;
    }
  }
  // We don't have any data to send back.
  SendResponse(request_id, NULL);
}

std::string DOMUIThemeSource::GetMimeType(const std::string& path) const {
  std::string uncached_path = StripQueryParams(path);

  if (strcmp(uncached_path.c_str(), kNewTabCSSPath) == 0)
    return "text/css";
  return "image/png";
}

void DOMUIThemeSource::SendResponse(int request_id, RefCountedBytes* data) {
  ChromeURLDataManager::DataSource::SendResponse(request_id, data);
}

////////////////////////////////////////////////////////////////////////////////
// DOMUIThemeSource, private:

void DOMUIThemeSource::SendNewTabCSS(int request_id) {
  ThemeProvider* tp = profile_->GetThemeProvider();
  DCHECK(tp);

  // Get our theme colors
  SkColor color_background =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_BACKGROUND);
  SkColor color_text = tp->GetColor(BrowserThemeProvider::COLOR_NTP_TEXT);
  SkColor color_link = tp->GetColor(BrowserThemeProvider::COLOR_NTP_LINK);
  SkColor color_section =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_SECTION);
  SkColor color_section_text =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_SECTION_TEXT);
  SkColor color_section_link =
      tp->GetColor(BrowserThemeProvider::COLOR_NTP_SECTION_LINK);

  // Generate a lighter color.
  skia::HSL section_lighter;
  skia::SkColorToHSL(color_section, section_lighter);
  section_lighter.l += (1 - section_lighter.l) * 0.33;
  SkColor color_section_lighter =
      skia::HSLToSkColor(SkColorGetA(color_section), section_lighter);

  // Generate the replacements.
  std::vector<string16> subst;
  // A second list of replacements, each of which must be in $$x format,
  // where x is a digit from 1-9.
  std::vector<string16> subst2;

  // Cache-buster for background.
  subst.push_back(WideToUTF16(
      profile_->GetPrefs()->GetString(prefs::kCurrentThemeID)));  // $1

  // Colors.
  subst.push_back(SkColorToRGBAString(color_background));  // $2
  subst.push_back(UTF8ToUTF16(GetNewTabBackgroundCSS(false)));  // $3
  subst.push_back(UTF8ToUTF16(GetNewTabBackgroundCSS(true)));  // $4
  subst.push_back(UTF8ToUTF16(GetNewTabBackgroundTilingCSS()));  // $5
  subst.push_back(SkColorToRGBAString(color_section));  // $6
  subst.push_back(SkColorToRGBAString(color_section_lighter));  // $7
  subst.push_back(SkColorToRGBAString(color_text));  // $8
  subst.push_back(SkColorToRGBAString(color_link));  // $9

  subst2.push_back(SkColorToRGBAString(color_section_text));  // $$1
  subst2.push_back(SkColorToRGBAString(color_section_link));  // $$2

  // Get our template.
  static const StringPiece new_tab_theme_css(
      ResourceBundle::GetSharedInstance().GetRawDataResource(
      IDR_NEW_TAB_THEME_CSS));

  // Create the string from our template and the replacements.
  string16 format_string = ASCIIToUTF16(new_tab_theme_css.as_string());
  const std::string css_string = UTF16ToASCII(ReplaceStringPlaceholders(
      format_string, subst, NULL));
  const std::string css_string2 =  UTF16ToASCII(ReplaceStringPlaceholders(
      ASCIIToUTF16(css_string), subst2, NULL));

  // Convert to a format appropriate for sending.
  scoped_refptr<RefCountedBytes> css_bytes(new RefCountedBytes);
  css_bytes->data.resize(css_string2.size());
  std::copy(css_string2.begin(), css_string2.end(), css_bytes->data.begin());

  // Send.
  SendResponse(request_id, css_bytes);
}

void DOMUIThemeSource::SendThemeBitmap(int request_id, int resource_id) {
  ThemeProvider* tp = profile_->GetThemeProvider();
  DCHECK(tp);

  std::vector<unsigned char> png_bytes;
  if (tp->GetRawData(resource_id, &png_bytes)) {
    scoped_refptr<RefCountedBytes> image_data =
        new RefCountedBytes(png_bytes);
    SendResponse(request_id, image_data);
  } else {
    SendResponse(request_id, NULL);
  }
}

std::string DOMUIThemeSource::GetNewTabBackgroundCSS(bool bar_attached) {
  int alignment;
  profile_->GetThemeProvider()->GetDisplayProperty(
      BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &alignment);

  if (bar_attached)
    return BrowserThemeProvider::AlignmentToString(alignment);

  // The bar is detached, so we must offset the background by the bar size
  // if it's a top-aligned bar.
#if defined(OS_WIN)
  int offset = BookmarkBarView::kNewtabBarHeight;
#else
  int offset = 0;
#endif

  // TODO(glen): This is a quick workaround to hide the notused.png image when
  // no image is provided - we don't have time right now to figure out why
  // this is painting as white.
  // http://crbug.com/17593
  if (!profile_->GetThemeProvider()->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
    return "-64px";
  }

  if (alignment & BrowserThemeProvider::ALIGN_TOP) {
    if (alignment & BrowserThemeProvider::ALIGN_LEFT)
      return "0% " + IntToString(-offset) + "px";
    else if (alignment & BrowserThemeProvider::ALIGN_RIGHT)
      return "100% " + IntToString(-offset) + "px";
    return "center " + IntToString(-offset) + "px";
  }
  return BrowserThemeProvider::AlignmentToString(alignment);
}

std::string DOMUIThemeSource::GetNewTabBackgroundTilingCSS() {
  int repeat_mode;
  profile_->GetThemeProvider()->GetDisplayProperty(
      BrowserThemeProvider::NTP_BACKGROUND_TILING, &repeat_mode);
  return BrowserThemeProvider::TilingToString(repeat_mode);
}

<|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/gtk/constrained_window_gtk.h"

#include <gdk/gdkkeysyms.h>

#include "chrome/browser/browser_list.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view_gtk.h"

ConstrainedWindowGtk::ConstrainedWindowGtk(
    TabContents* owner, ConstrainedWindowGtkDelegate* delegate)
    : owner_(owner),
      delegate_(delegate),
      visible_(false),
      accel_group_(gtk_accel_group_new()) {
  DCHECK(owner);
  DCHECK(delegate);
  GtkWidget* dialog = delegate->GetWidgetRoot();

  // Unlike other users of CreateBorderBin, we need a dedicated frame around
  // our "window".
  GtkWidget* ebox = gtk_event_box_new();
  GtkWidget* frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder,
      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder);
  gtk_container_add(GTK_CONTAINER(alignment), dialog);
  gtk_container_add(GTK_CONTAINER(frame), alignment);
  gtk_container_add(GTK_CONTAINER(ebox), frame);
  border_.Own(ebox);
  ConnectAccelerators();
}

ConstrainedWindowGtk::~ConstrainedWindowGtk() {
  border_.Destroy();

  gtk_accel_group_disconnect_key(accel_group_, GDK_Escape,
                                 static_cast<GdkModifierType>(0));
  gtk_window_remove_accel_group(
      GTK_WINDOW(ContainingView()->GetTopLevelNativeWindow()),
      accel_group_);
  g_object_unref(accel_group_);
}

void ConstrainedWindowGtk::ShowConstrainedWindow() {
  gtk_widget_show_all(border_.get());

  // We collaborate with TabContentsViewGtk and stick ourselves in the
  // TabContentsViewGtk's floating container.
  ContainingView()->AttachConstrainedWindow(this);

  visible_ = true;
}

void ConstrainedWindowGtk::CloseConstrainedWindow() {
  if (visible_)
    ContainingView()->RemoveConstrainedWindow(this);
  delegate_->DeleteDelegate();
  owner_->WillClose(this);

  delete this;
}

TabContentsViewGtk* ConstrainedWindowGtk::ContainingView() {
  return static_cast<TabContentsViewGtk*>(owner_->view());
}

void ConstrainedWindowGtk::ConnectAccelerators() {
  gtk_accel_group_connect(accel_group_,
                          GDK_Escape, static_cast<GdkModifierType>(0),
                          static_cast<GtkAccelFlags>(0),
                          g_cclosure_new(G_CALLBACK(OnEscapeThunk),
                                         this, NULL));
  gtk_window_add_accel_group(
      GTK_WINDOW(ContainingView()->GetTopLevelNativeWindow()),
      accel_group_);
}

gboolean ConstrainedWindowGtk::OnEscape() {
  // Handle this accelerator only if this is on the currently selected tab.
  Browser* browser = BrowserList::GetLastActive();
  if (!browser || browser->GetSelectedTabContents() != owner_)
    return FALSE;

  CloseConstrainedWindow();
  return TRUE;
}

// static
ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog(
    TabContents* parent,
    ConstrainedWindowGtkDelegate* delegate) {
  return new ConstrainedWindowGtk(parent, delegate);
}

<commit_msg>Fix for LoginPromptTesti.CancelRedundantAuths and related tests on linux views.<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/gtk/constrained_window_gtk.h"

#include <gdk/gdkkeysyms.h>

#include "chrome/browser/browser_list.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view_gtk.h"

ConstrainedWindowGtk::ConstrainedWindowGtk(
    TabContents* owner, ConstrainedWindowGtkDelegate* delegate)
    : owner_(owner),
      delegate_(delegate),
      visible_(false),
      accel_group_(gtk_accel_group_new()) {
  DCHECK(owner);
  DCHECK(delegate);
  GtkWidget* dialog = delegate->GetWidgetRoot();

  // Unlike other users of CreateBorderBin, we need a dedicated frame around
  // our "window".
  GtkWidget* ebox = gtk_event_box_new();
  GtkWidget* frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder,
      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder);
  gtk_container_add(GTK_CONTAINER(alignment), dialog);
  gtk_container_add(GTK_CONTAINER(frame), alignment);
  gtk_container_add(GTK_CONTAINER(ebox), frame);
  border_.Own(ebox);
  ConnectAccelerators();
}

ConstrainedWindowGtk::~ConstrainedWindowGtk() {
  border_.Destroy();

  gtk_accel_group_disconnect_key(accel_group_, GDK_Escape,
                                 static_cast<GdkModifierType>(0));
  if (ContainingView() && ContainingView()->GetTopLevelNativeWindow()) {
    gtk_window_remove_accel_group(
        GTK_WINDOW(ContainingView()->GetTopLevelNativeWindow()),
        accel_group_);
  }
  g_object_unref(accel_group_);
}

void ConstrainedWindowGtk::ShowConstrainedWindow() {
  gtk_widget_show_all(border_.get());

  // We collaborate with TabContentsViewGtk and stick ourselves in the
  // TabContentsViewGtk's floating container.
  ContainingView()->AttachConstrainedWindow(this);

  visible_ = true;
}

void ConstrainedWindowGtk::CloseConstrainedWindow() {
  if (visible_)
    ContainingView()->RemoveConstrainedWindow(this);
  delegate_->DeleteDelegate();
  owner_->WillClose(this);

  delete this;
}

TabContentsViewGtk* ConstrainedWindowGtk::ContainingView() {
  return static_cast<TabContentsViewGtk*>(owner_->view());
}

void ConstrainedWindowGtk::ConnectAccelerators() {
  gtk_accel_group_connect(accel_group_,
                          GDK_Escape, static_cast<GdkModifierType>(0),
                          static_cast<GtkAccelFlags>(0),
                          g_cclosure_new(G_CALLBACK(OnEscapeThunk),
                                         this, NULL));
  gtk_window_add_accel_group(
      GTK_WINDOW(ContainingView()->GetTopLevelNativeWindow()),
      accel_group_);
}

gboolean ConstrainedWindowGtk::OnEscape() {
  // Handle this accelerator only if this is on the currently selected tab.
  Browser* browser = BrowserList::GetLastActive();
  if (!browser || browser->GetSelectedTabContents() != owner_)
    return FALSE;

  CloseConstrainedWindow();
  return TRUE;
}

// static
ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog(
    TabContents* parent,
    ConstrainedWindowGtkDelegate* delegate) {
  return new ConstrainedWindowGtk(parent, delegate);
}

<|endoftext|>


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

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

#include "base/basictypes.h"
#include "chrome/app/chrome_command_ids.h"
#include "ui/base/events.h"

namespace chrome {

// NOTE: Keep this list in the same (mostly-alphabetical) order as
// the Windows accelerators in ../../app/chrome_dll.rc.
// Do not use Ctrl-Alt as a shortcut modifier, as it is used by i18n keyboards:
// http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx
const AcceleratorMapping kAcceleratorMap[] = {
  { ui::VKEY_LEFT, ui::EF_ALT_DOWN, IDC_BACK },
  { ui::VKEY_BACK, ui::EF_NONE, IDC_BACK },
  { ui::VKEY_D, ui::EF_CONTROL_DOWN, IDC_BOOKMARK_PAGE },
  { ui::VKEY_D, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_BOOKMARK_ALL_TABS },
  { ui::VKEY_W, ui::EF_CONTROL_DOWN, IDC_CLOSE_TAB },
  { ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW },
  { ui::VKEY_F, ui::EF_CONTROL_DOWN, IDC_FIND },
  { ui::VKEY_G, ui::EF_CONTROL_DOWN, IDC_FIND_NEXT },
  { ui::VKEY_G, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_FIND_PREVIOUS },
  { ui::VKEY_D, ui::EF_ALT_DOWN, IDC_FOCUS_LOCATION },
  { ui::VKEY_L, ui::EF_CONTROL_DOWN, IDC_FOCUS_LOCATION },
  { ui::VKEY_K, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH },
  { ui::VKEY_E, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH },
  { ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_TOOLBAR },
  { ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_BOOKMARKS },
  { ui::VKEY_RIGHT, ui::EF_ALT_DOWN, IDC_FORWARD },
  { ui::VKEY_BACK, ui::EF_SHIFT_DOWN, IDC_FORWARD },
  { ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS },
  { ui::VKEY_F12, ui::EF_NONE, IDC_DEV_TOOLS },
  { ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_DEV_TOOLS_CONSOLE },
  { ui::VKEY_C, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_DEV_TOOLS_INSPECT },
  { ui::VKEY_P, ui::EF_CONTROL_DOWN, IDC_PRINT},
  { ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ADVANCED_PRINT},
  { ui::VKEY_R, ui::EF_CONTROL_DOWN, IDC_RELOAD },
  { ui::VKEY_R, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_HOME, ui::EF_ALT_DOWN, IDC_HOME },
  { ui::VKEY_S, ui::EF_CONTROL_DOWN, IDC_SAVE_PAGE },
  { ui::VKEY_9, ui::EF_CONTROL_DOWN, IDC_SELECT_LAST_TAB },
  { ui::VKEY_NUMPAD9, ui::EF_CONTROL_DOWN, IDC_SELECT_LAST_TAB },
  { ui::VKEY_TAB, ui::EF_CONTROL_DOWN, IDC_SELECT_NEXT_TAB },
  { ui::VKEY_NEXT, ui::EF_CONTROL_DOWN, IDC_SELECT_NEXT_TAB },
  { ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_SELECT_PREVIOUS_TAB },
  { ui::VKEY_PRIOR, ui::EF_CONTROL_DOWN, IDC_SELECT_PREVIOUS_TAB },
  { ui::VKEY_1, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_0 },
  { ui::VKEY_NUMPAD1, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_0 },
  { ui::VKEY_2, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_1 },
  { ui::VKEY_NUMPAD2, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_1 },
  { ui::VKEY_3, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_2 },
  { ui::VKEY_NUMPAD3, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_2 },
  { ui::VKEY_4, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_3 },
  { ui::VKEY_NUMPAD4, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_3 },
  { ui::VKEY_5, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_4 },
  { ui::VKEY_NUMPAD5, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_4 },
  { ui::VKEY_6, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_5 },
  { ui::VKEY_NUMPAD6, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_5 },
  { ui::VKEY_7, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_6 },
  { ui::VKEY_NUMPAD7, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_6 },
  { ui::VKEY_8, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_7 },
  { ui::VKEY_NUMPAD8, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_7 },
  { ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_SHOW_BOOKMARK_BAR },
  { ui::VKEY_O, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_SHOW_BOOKMARK_MANAGER },
  { ui::VKEY_J, ui::EF_CONTROL_DOWN, IDC_SHOW_DOWNLOADS },
  { ui::VKEY_H, ui::EF_CONTROL_DOWN, IDC_SHOW_HISTORY },
  { ui::VKEY_F, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
  { ui::VKEY_E, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
  { ui::VKEY_ESCAPE, ui::EF_NONE, IDC_STOP },
  { ui::VKEY_OEM_PERIOD, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_TOGGLE_SPEECH_INPUT },
  { ui::VKEY_U, ui::EF_CONTROL_DOWN, IDC_VIEW_SOURCE },
  { ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
  { ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_ZOOM_MINUS },
  { ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
  { ui::VKEY_0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
  { ui::VKEY_NUMPAD0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
  { ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
  { ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
  { ui::VKEY_ADD, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },

  // Platform-specific key maps.
#if defined(OS_CHROMEOS)
  // On Chrome OS, VKEY_BROWSER_SEARCH is handled in Ash.
  { ui::VKEY_BROWSER_BACK, ui::EF_NONE, IDC_BACK },
  { ui::VKEY_F1, ui::EF_NONE, IDC_BACK },
  { ui::VKEY_BACK, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_CLEAR_BROWSING_DATA },
  { ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FEEDBACK },
  { ui::VKEY_BROWSER_FORWARD, ui::EF_NONE, IDC_FORWARD },
  { ui::VKEY_F2, ui::EF_NONE, IDC_FORWARD },
  { ui::VKEY_F4, ui::EF_NONE, IDC_FULLSCREEN },
  { ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN, IDC_HELP_PAGE_VIA_KEYBOARD },
  { ui::VKEY_OEM_2, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_HELP_PAGE_VIA_KEYBOARD },
  { ui::VKEY_BROWSER_HOME, ui::EF_NONE, IDC_HOME },
  { ui::VKEY_BROWSER_REFRESH, ui::EF_NONE, IDC_RELOAD },
  { ui::VKEY_F3, ui::EF_NONE, IDC_RELOAD },
  { ui::VKEY_F3, ui::EF_CONTROL_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_F3, ui::EF_SHIFT_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_BROWSER_FAVORITES, ui::EF_NONE, IDC_SHOW_BOOKMARK_MANAGER },
  { ui::VKEY_BROWSER_STOP, ui::EF_NONE, IDC_STOP },
#else  // OS_CHROMEOS
  { ui::VKEY_DELETE, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_CLEAR_BROWSING_DATA },
  { ui::VKEY_F4, ui::EF_CONTROL_DOWN, IDC_CLOSE_TAB },
  { ui::VKEY_F4, ui::EF_ALT_DOWN, IDC_CLOSE_WINDOW },
  { ui::VKEY_F3, ui::EF_NONE, IDC_FIND_NEXT },
  { ui::VKEY_F3, ui::EF_SHIFT_DOWN, IDC_FIND_PREVIOUS },
  { ui::VKEY_F10, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_LMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_MENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_RMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_F6, ui::EF_NONE, IDC_FOCUS_NEXT_PANE },
  { ui::VKEY_F6, ui::EF_SHIFT_DOWN, IDC_FOCUS_PREVIOUS_PANE },
  // On Windows, all VKEY_BROWSER_* keys except VKEY_BROWSER_SEARCH are handled
  // via WM_APPCOMMAND.
  { ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, IDC_FOCUS_SEARCH },
  { ui::VKEY_F11, ui::EF_NONE, IDC_FULLSCREEN },
  { ui::VKEY_F1, ui::EF_NONE, IDC_HELP_PAGE_VIA_KEYBOARD },
  { ui::VKEY_F5, ui::EF_NONE, IDC_RELOAD },
  { ui::VKEY_F5, ui::EF_CONTROL_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_F5, ui::EF_SHIFT_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_SHOW_AVATAR_MENU},
#endif  // OS_CHROMEOS
#if !defined(USE_ASH)
  { ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_EXIT },
  { ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_NEW_INCOGNITO_WINDOW },
  { ui::VKEY_T, ui::EF_CONTROL_DOWN, IDC_NEW_TAB },
  { ui::VKEY_N, ui::EF_CONTROL_DOWN, IDC_NEW_WINDOW },
  { ui::VKEY_O, ui::EF_CONTROL_DOWN, IDC_OPEN_FILE },
  { ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_RESTORE_TAB },
  { ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, IDC_TASK_MANAGER },
#endif
};

const size_t kAcceleratorMapLength = arraysize(kAcceleratorMap);

}  // namespace chrome
<commit_msg>Fix a test break due to crrev.com/146530<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

#include "base/basictypes.h"
#include "chrome/app/chrome_command_ids.h"
#include "ui/base/events.h"

namespace chrome {

// NOTE: Keep this list in the same (mostly-alphabetical) order as
// the Windows accelerators in ../../app/chrome_dll.rc.
// Do not use Ctrl-Alt as a shortcut modifier, as it is used by i18n keyboards:
// http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx
const AcceleratorMapping kAcceleratorMap[] = {
  { ui::VKEY_LEFT, ui::EF_ALT_DOWN, IDC_BACK },
  { ui::VKEY_BACK, ui::EF_NONE, IDC_BACK },
  { ui::VKEY_D, ui::EF_CONTROL_DOWN, IDC_BOOKMARK_PAGE },
  { ui::VKEY_D, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_BOOKMARK_ALL_TABS },
  { ui::VKEY_W, ui::EF_CONTROL_DOWN, IDC_CLOSE_TAB },
  { ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW },
  { ui::VKEY_F, ui::EF_CONTROL_DOWN, IDC_FIND },
  { ui::VKEY_G, ui::EF_CONTROL_DOWN, IDC_FIND_NEXT },
  { ui::VKEY_G, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_FIND_PREVIOUS },
  { ui::VKEY_D, ui::EF_ALT_DOWN, IDC_FOCUS_LOCATION },
  { ui::VKEY_L, ui::EF_CONTROL_DOWN, IDC_FOCUS_LOCATION },
  { ui::VKEY_K, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH },
  { ui::VKEY_E, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH },
  { ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_TOOLBAR },
  { ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_BOOKMARKS },
  { ui::VKEY_RIGHT, ui::EF_ALT_DOWN, IDC_FORWARD },
  { ui::VKEY_BACK, ui::EF_SHIFT_DOWN, IDC_FORWARD },
  { ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS },
  { ui::VKEY_F12, ui::EF_NONE, IDC_DEV_TOOLS },
  { ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_DEV_TOOLS_CONSOLE },
  { ui::VKEY_C, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_DEV_TOOLS_INSPECT },
  { ui::VKEY_P, ui::EF_CONTROL_DOWN, IDC_PRINT},
  { ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ADVANCED_PRINT},
  { ui::VKEY_R, ui::EF_CONTROL_DOWN, IDC_RELOAD },
  { ui::VKEY_R, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_HOME, ui::EF_ALT_DOWN, IDC_HOME },
  { ui::VKEY_S, ui::EF_CONTROL_DOWN, IDC_SAVE_PAGE },
  { ui::VKEY_9, ui::EF_CONTROL_DOWN, IDC_SELECT_LAST_TAB },
  { ui::VKEY_NUMPAD9, ui::EF_CONTROL_DOWN, IDC_SELECT_LAST_TAB },
  { ui::VKEY_TAB, ui::EF_CONTROL_DOWN, IDC_SELECT_NEXT_TAB },
  { ui::VKEY_NEXT, ui::EF_CONTROL_DOWN, IDC_SELECT_NEXT_TAB },
  { ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_SELECT_PREVIOUS_TAB },
  { ui::VKEY_PRIOR, ui::EF_CONTROL_DOWN, IDC_SELECT_PREVIOUS_TAB },
  { ui::VKEY_1, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_0 },
  { ui::VKEY_NUMPAD1, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_0 },
  { ui::VKEY_2, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_1 },
  { ui::VKEY_NUMPAD2, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_1 },
  { ui::VKEY_3, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_2 },
  { ui::VKEY_NUMPAD3, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_2 },
  { ui::VKEY_4, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_3 },
  { ui::VKEY_NUMPAD4, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_3 },
  { ui::VKEY_5, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_4 },
  { ui::VKEY_NUMPAD5, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_4 },
  { ui::VKEY_6, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_5 },
  { ui::VKEY_NUMPAD6, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_5 },
  { ui::VKEY_7, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_6 },
  { ui::VKEY_NUMPAD7, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_6 },
  { ui::VKEY_8, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_7 },
  { ui::VKEY_NUMPAD8, ui::EF_CONTROL_DOWN, IDC_SELECT_TAB_7 },
  { ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_SHOW_BOOKMARK_BAR },
  { ui::VKEY_O, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_SHOW_BOOKMARK_MANAGER },
  { ui::VKEY_J, ui::EF_CONTROL_DOWN, IDC_SHOW_DOWNLOADS },
  { ui::VKEY_H, ui::EF_CONTROL_DOWN, IDC_SHOW_HISTORY },
  { ui::VKEY_F, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
  { ui::VKEY_E, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
  { ui::VKEY_ESCAPE, ui::EF_NONE, IDC_STOP },
  { ui::VKEY_OEM_PERIOD, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_TOGGLE_SPEECH_INPUT },
  { ui::VKEY_U, ui::EF_CONTROL_DOWN, IDC_VIEW_SOURCE },
  { ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
  { ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_ZOOM_MINUS },
  { ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
  { ui::VKEY_0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
  { ui::VKEY_NUMPAD0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
  { ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
  { ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
  { ui::VKEY_ADD, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },

  // Platform-specific key maps.
#if defined(OS_CHROMEOS)
  // On Chrome OS, VKEY_BROWSER_SEARCH is handled in Ash.
  { ui::VKEY_BROWSER_BACK, ui::EF_NONE, IDC_BACK },
  { ui::VKEY_F1, ui::EF_NONE, IDC_BACK },
  { ui::VKEY_BACK, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_CLEAR_BROWSING_DATA },
  { ui::VKEY_BROWSER_FORWARD, ui::EF_NONE, IDC_FORWARD },
  { ui::VKEY_F2, ui::EF_NONE, IDC_FORWARD },
  { ui::VKEY_F4, ui::EF_NONE, IDC_FULLSCREEN },
  { ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN, IDC_HELP_PAGE_VIA_KEYBOARD },
  { ui::VKEY_OEM_2, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_HELP_PAGE_VIA_KEYBOARD },
  { ui::VKEY_BROWSER_HOME, ui::EF_NONE, IDC_HOME },
  { ui::VKEY_BROWSER_REFRESH, ui::EF_NONE, IDC_RELOAD },
  { ui::VKEY_F3, ui::EF_NONE, IDC_RELOAD },
  { ui::VKEY_F3, ui::EF_CONTROL_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_F3, ui::EF_SHIFT_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_BROWSER_FAVORITES, ui::EF_NONE, IDC_SHOW_BOOKMARK_MANAGER },
  { ui::VKEY_BROWSER_STOP, ui::EF_NONE, IDC_STOP },
#else  // OS_CHROMEOS
  { ui::VKEY_DELETE, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_CLEAR_BROWSING_DATA },
  { ui::VKEY_F4, ui::EF_CONTROL_DOWN, IDC_CLOSE_TAB },
  { ui::VKEY_F4, ui::EF_ALT_DOWN, IDC_CLOSE_WINDOW },
  { ui::VKEY_F3, ui::EF_NONE, IDC_FIND_NEXT },
  { ui::VKEY_F3, ui::EF_SHIFT_DOWN, IDC_FIND_PREVIOUS },
  { ui::VKEY_F10, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_LMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_MENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_RMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
  { ui::VKEY_F6, ui::EF_NONE, IDC_FOCUS_NEXT_PANE },
  { ui::VKEY_F6, ui::EF_SHIFT_DOWN, IDC_FOCUS_PREVIOUS_PANE },
  // On Windows, all VKEY_BROWSER_* keys except VKEY_BROWSER_SEARCH are handled
  // via WM_APPCOMMAND.
  { ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, IDC_FOCUS_SEARCH },
  { ui::VKEY_F11, ui::EF_NONE, IDC_FULLSCREEN },
  { ui::VKEY_F1, ui::EF_NONE, IDC_HELP_PAGE_VIA_KEYBOARD },
  { ui::VKEY_F5, ui::EF_NONE, IDC_RELOAD },
  { ui::VKEY_F5, ui::EF_CONTROL_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_F5, ui::EF_SHIFT_DOWN, IDC_RELOAD_IGNORING_CACHE },
  { ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_SHOW_AVATAR_MENU},
#endif  // OS_CHROMEOS
#if !defined(USE_ASH)
  { ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FEEDBACK },
  { ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_EXIT },
  { ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
    IDC_NEW_INCOGNITO_WINDOW },
  { ui::VKEY_T, ui::EF_CONTROL_DOWN, IDC_NEW_TAB },
  { ui::VKEY_N, ui::EF_CONTROL_DOWN, IDC_NEW_WINDOW },
  { ui::VKEY_O, ui::EF_CONTROL_DOWN, IDC_OPEN_FILE },
  { ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_RESTORE_TAB },
  { ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, IDC_TASK_MANAGER },
#endif
};

const size_t kAcceleratorMapLength = arraysize(kAcceleratorMap);

}  // namespace chrome
<|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/renderer/media/video_renderer_impl.h"

VideoRendererImpl::VideoRendererImpl(WebMediaPlayerDelegateImpl* delegate)
    : delegate_(delegate),
      last_converted_frame_(NULL) {
}

bool VideoRendererImpl::OnInitialize(size_t width, size_t height) {
  video_size_.SetSize(width, height);
  bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height);
  if (bitmap_.allocPixels(NULL, NULL)) {
    bitmap_.eraseRGB(0x00, 0x00, 0x00);
    return true;
  }
  NOTREACHED();
  return false;
}

void VideoRendererImpl::OnPaintNeeded() {
  delegate_->PostRepaintTask();
}

// This method is always called on the renderer's thread.
void VideoRendererImpl::Paint(skia::PlatformCanvas* canvas,
                              const gfx::Rect& dest_rect) {
  scoped_refptr<media::VideoFrame> video_frame;
  GetCurrentFrame(&video_frame);
  if (video_frame.get()) {
    CopyToCurrentFrame(video_frame);
    video_frame = NULL;
  }
  SkMatrix matrix;
  matrix.setTranslate(static_cast<SkScalar>(dest_rect.x()),
                      static_cast<SkScalar>(dest_rect.y()));
  if (dest_rect.width()  != video_size_.width() ||
      dest_rect.height() != video_size_.height()) {
    matrix.preScale(
        static_cast<SkScalar>(dest_rect.width()  / video_size_.width()),
        static_cast<SkScalar>(dest_rect.height() / video_size_.height()));
  }
  canvas->drawBitmapMatrix(bitmap_, matrix, NULL);
}

void VideoRendererImpl::CopyToCurrentFrame(media::VideoFrame* video_frame) {
  base::TimeDelta timestamp = video_frame->GetTimestamp();
  if (video_frame != last_converted_frame_ ||
      timestamp != last_converted_timestamp_) {
    last_converted_frame_ = video_frame;
    last_converted_timestamp_ = timestamp;
    media::VideoSurface frame_in;
    if (video_frame->Lock(&frame_in)) {
      // TODO(ralphl):  Actually do the color space conversion here!
      // This is temporary code to set the bits of the current_frame_ to
      // blue.
      bitmap_.eraseRGB(0x00, 0x00, 0xFF);
      video_frame->Unlock();
    } else {
      NOTREACHED();
    }
  }
}
<commit_msg>The video renderer actually color converts.  This is the last change that should be required to actually get the renderer to display frames. Review URL: http://codereview.chromium.org/43051<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/renderer/media/video_renderer_impl.h"
#include "media/base/yuv_convert.h"

VideoRendererImpl::VideoRendererImpl(WebMediaPlayerDelegateImpl* delegate)
    : delegate_(delegate),
      last_converted_frame_(NULL) {
}

bool VideoRendererImpl::OnInitialize(size_t width, size_t height) {
  video_size_.SetSize(width, height);
  bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height);
  if (bitmap_.allocPixels(NULL, NULL)) {
    bitmap_.eraseRGB(0x00, 0x00, 0x00);
    return true;
  }
  NOTREACHED();
  return false;
}

void VideoRendererImpl::OnPaintNeeded() {
  delegate_->PostRepaintTask();
}

// This method is always called on the renderer's thread.
void VideoRendererImpl::Paint(skia::PlatformCanvas* canvas,
                              const gfx::Rect& dest_rect) {
  scoped_refptr<media::VideoFrame> video_frame;
  GetCurrentFrame(&video_frame);
  if (video_frame.get()) {
    CopyToCurrentFrame(video_frame);
    video_frame = NULL;
  }
  SkMatrix matrix;
  matrix.setTranslate(static_cast<SkScalar>(dest_rect.x()),
                      static_cast<SkScalar>(dest_rect.y()));
  if (dest_rect.width()  != video_size_.width() ||
      dest_rect.height() != video_size_.height()) {
    matrix.preScale(
        static_cast<SkScalar>(dest_rect.width()  / video_size_.width()),
        static_cast<SkScalar>(dest_rect.height() / video_size_.height()));
  }
  canvas->drawBitmapMatrix(bitmap_, matrix, NULL);
}

void VideoRendererImpl::CopyToCurrentFrame(media::VideoFrame* video_frame) {
  base::TimeDelta timestamp = video_frame->GetTimestamp();
  if (video_frame != last_converted_frame_ ||
      timestamp != last_converted_timestamp_) {
    last_converted_frame_ = video_frame;
    last_converted_timestamp_ = timestamp;
    media::VideoSurface frame_in;
    if (video_frame->Lock(&frame_in)) {
      // TODO(hclam): Support more video formats than just YV12.
      DCHECK(frame_in.format == media::VideoSurface::YV12);
      DCHECK(frame_in.strides[media::VideoSurface::kUPlane] ==
             frame_in.strides[media::VideoSurface::kVPlane]);
      DCHECK(frame_in.planes == media::VideoSurface::kNumYUVPlanes);
      bitmap_.lockPixels();
      media::ConvertYV12ToRGB32(frame_in.data[media::VideoSurface::kYPlane],
                                frame_in.data[media::VideoSurface::kUPlane],
                                frame_in.data[media::VideoSurface::kVPlane],
                                static_cast<uint8*>(bitmap_.getPixels()),
                                frame_in.width,
                                frame_in.height,
                                frame_in.strides[media::VideoSurface::kYPlane],
                                frame_in.strides[media::VideoSurface::kUPlane],
                                bitmap_.rowBytes());
      bitmap_.unlockPixels();
      video_frame->Unlock();
    } else {
      NOTREACHED();
    }
  }
}
<|endoftext|>


<commit_before>#include "GLFWApplication.h"

#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

using namespace agl;

GLFWApplication* agl::currentApp;

#include "begincbackdecl.h"
// Thanks learnopengl.com!
void APIENTRY glDebugOutput(GLenum source,
                            GLenum type,
                            GLuint id,
                            GLenum severity,
                            GLsizei length,
                            const GLchar *message,
                            const void *userParam) {
  // ignore non-significant error/warning codes
  if (id == 131169 || id == 131185 || id == 131218 || id == 131204) return;
  std::cout << "---------------" << std::endl;
  std::cout << "Debug message (" << id << "): " <<  message << std::endl;
  switch (source) {
    case GL_DEBUG_SOURCE_API:             std::cout << "Source: API"; break;
    case GL_DEBUG_SOURCE_WINDOW_SYSTEM:   std::cout << "Source: Window System"; break;
    case GL_DEBUG_SOURCE_SHADER_COMPILER: std::cout << "Source: Shader Compiler"; break;
    case GL_DEBUG_SOURCE_THIRD_PARTY:     std::cout << "Source: Third Party"; break;
    case GL_DEBUG_SOURCE_APPLICATION:     std::cout << "Source: Application"; break;
    case GL_DEBUG_SOURCE_OTHER:           std::cout << "Source: Other"; break;
  }
	std::cout << std::endl;
  switch (type) {
    case GL_DEBUG_TYPE_ERROR:               std::cout << "Type: Error"; break;
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: std::cout << "Type: Deprecated Behaviour"; break;
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:  std::cout << "Type: Undefined Behaviour"; break;
    case GL_DEBUG_TYPE_PORTABILITY:         std::cout << "Type: Portability"; break;
    case GL_DEBUG_TYPE_PERFORMANCE:         std::cout << "Type: Performance"; break;
    case GL_DEBUG_TYPE_MARKER:              std::cout << "Type: Marker"; break;
    case GL_DEBUG_TYPE_PUSH_GROUP:          std::cout << "Type: Push Group"; break;
    case GL_DEBUG_TYPE_POP_GROUP:           std::cout << "Type: Pop Group"; break;
    case GL_DEBUG_TYPE_OTHER:               std::cout << "Type: Other"; break;
  }
	std::cout << std::endl;
  switch (severity) {
    case GL_DEBUG_SEVERITY_HIGH:         std::cout << "Severity: high"; break;
    case GL_DEBUG_SEVERITY_MEDIUM:       std::cout << "Severity: medium"; break;
    case GL_DEBUG_SEVERITY_LOW:          std::cout << "Severity: low"; break;
    case GL_DEBUG_SEVERITY_NOTIFICATION: std::cout << "Severity: notification"; break;
  }
	std::cout << std::endl;
  std::cout << std::endl;
}
#include "endcbackdecl.h"

GLFWApplication::GLFWApplication(
	int width,
	int height,
	int actualWidth,
	int actualHeight,
	const char* title,
	int glMajor,
	int glMinor,
	bool debug,
  int maxFPS
	) {
	// Set actual width and height of window to whatever
	// you're working on if not set
	if (actualWidth == 0) actualWidth = width;
	if (actualHeight == 0) actualHeight = height;
	currInRF = 0;
	rollingFPS = 60;
	cumulDelta = 0;
	w = width;
	h = height;
  aw = actualWidth;
  ah = actualHeight;
  mfps = maxFPS;
	projection = glm::scale(projection, glm::vec3(1.0f / width, 1.0f / height, 1));
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glMajor);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glMinor);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
	glfwWindowHint(GLFW_SAMPLES, 4);
	window = glfwCreateWindow(actualWidth, actualHeight, title, nullptr, nullptr);
	if (window == nullptr) {
		glfwTerminate();
		throw u8"Failed to create GLFW window";
	}
	glfwMakeContextCurrent(window);
	glewExperimental = GL_TRUE;
	if (glewInit() != GLEW_OK) {
		throw u8"Failed to initialise GLEW";
	}
	glGetError();
	if (debug) {
		glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
		GLint flags;
		glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
		if (flags & GL_CONTEXT_FLAG_DEBUG_BIT || glMajor >= 5 || (glMajor == 4 && glMinor >= 3)) {
		    // initialise debug output
				glEnable(GL_DEBUG_OUTPUT);
		    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
		    glDebugMessageCallback(glDebugOutput, nullptr);
		    glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
		} else {
			std::cout << "Warning: requested debug output but we can't do it\n";
		}
	}
	glViewport(0, 0, width, height);
	glEnable(GL_MULTISAMPLE);
	glfwSetKeyCallback(window, keyCallback);
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glfwSetCursorPosCallback(window, mouseCallback);
	setVSyncEnable(false);
}

#ifdef __WIN32
#include <windows.h>
inline void wait(double t) {
  Sleep((int) (t * 1000));
}
#else
#include <time.h>
inline void wait(double t) {
  struct timespec rqtp;
  rqtp.tv_sec = (int) (t / 1000000000);
  rqtp.tv_nsec = (int) (t * 1000000000) % 1000000000;
  nanosleep(&rqtp, nullptr);
}
#endif

#define WAITING_DISTANCE 0.5
#define THRESH 0.002

void GLFWApplication::start() {
	currentTime = glfwGetTime();
	initialise();
	while (!glfwWindowShouldClose(window)) {
		GLdouble prevTime = currentTime;
		currentTime = glfwGetTime();
		// Keep at slightly more than maxFPS so FPS doesn't dip below as often
		double goal = prevTime + 0.999 / mfps;
    		  while (currentTime < goal) {
    		  currentTime = glfwGetTime();
    		  double diff = goal - currentTime;
    		  if (diff < THRESH) wait(WAITING_DISTANCE * diff);
    		}
		delta = currentTime - prevTime;
		fps = 1.0 / delta;
		cumulDelta += delta;
		++currInRF;
		if (cumulDelta >= FPS_UPDATE_PERIOD) {
			rollingFPS = currInRF / cumulDelta;
			currInRF = 0;
			cumulDelta = 0;
		}
		currentApp = this;
		glfwWaitEvents();
		readKeys();
		tick();
		glfwSwapBuffers(window);
		glFinish();
	}
	delete this;
}

GLFWApplication::~GLFWApplication() {
}

void GLFWApplication::initialise() {
	return;
}

void GLFWApplication::tick() {
	return;
}

void GLFWApplication::readKeys() {
	return;
}

bool GLFWApplication::testKey(int code) {
	return (keys[code >> 6] >> (code & 63)) & 1;
}

void GLFWApplication::setVSyncEnable(bool enable) {
	glfwSwapInterval(enable);
}

void GLFWApplication::setKey(int code) {
	keys[code >> 6] |= (1LL << (code & 63));
}

void GLFWApplication::resetKey(int code) {
	keys[code >> 6] &= ~(1LL << (code & 63));
}

#include "begincbackdecl.h"

void agl::keyCallback(GLFWwindow* window, int key, int scancode, int action, int mode) {
	if (action == GLFW_PRESS) currentApp->setKey(key);
	else if (action == GLFW_RELEASE) currentApp->resetKey(key);
}

void GLFWApplication::onMouse(double xpos, double ypos) {
	return;
}

void agl::mouseCallback(GLFWwindow* window, double xpos, double ypos) {
	currentApp->onMouse(xpos, ypos);
}

#include "endcbackdecl.h"
<commit_msg>Revert to glfwPollEvents.<commit_after>#include "GLFWApplication.h"

#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

using namespace agl;

GLFWApplication* agl::currentApp;

#include "begincbackdecl.h"
// Thanks learnopengl.com!
void APIENTRY glDebugOutput(GLenum source,
                            GLenum type,
                            GLuint id,
                            GLenum severity,
                            GLsizei length,
                            const GLchar *message,
                            const void *userParam) {
  // ignore non-significant error/warning codes
  if (id == 131169 || id == 131185 || id == 131218 || id == 131204) return;
  std::cout << "---------------" << std::endl;
  std::cout << "Debug message (" << id << "): " <<  message << std::endl;
  switch (source) {
    case GL_DEBUG_SOURCE_API:             std::cout << "Source: API"; break;
    case GL_DEBUG_SOURCE_WINDOW_SYSTEM:   std::cout << "Source: Window System"; break;
    case GL_DEBUG_SOURCE_SHADER_COMPILER: std::cout << "Source: Shader Compiler"; break;
    case GL_DEBUG_SOURCE_THIRD_PARTY:     std::cout << "Source: Third Party"; break;
    case GL_DEBUG_SOURCE_APPLICATION:     std::cout << "Source: Application"; break;
    case GL_DEBUG_SOURCE_OTHER:           std::cout << "Source: Other"; break;
  }
	std::cout << std::endl;
  switch (type) {
    case GL_DEBUG_TYPE_ERROR:               std::cout << "Type: Error"; break;
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: std::cout << "Type: Deprecated Behaviour"; break;
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:  std::cout << "Type: Undefined Behaviour"; break;
    case GL_DEBUG_TYPE_PORTABILITY:         std::cout << "Type: Portability"; break;
    case GL_DEBUG_TYPE_PERFORMANCE:         std::cout << "Type: Performance"; break;
    case GL_DEBUG_TYPE_MARKER:              std::cout << "Type: Marker"; break;
    case GL_DEBUG_TYPE_PUSH_GROUP:          std::cout << "Type: Push Group"; break;
    case GL_DEBUG_TYPE_POP_GROUP:           std::cout << "Type: Pop Group"; break;
    case GL_DEBUG_TYPE_OTHER:               std::cout << "Type: Other"; break;
  }
	std::cout << std::endl;
  switch (severity) {
    case GL_DEBUG_SEVERITY_HIGH:         std::cout << "Severity: high"; break;
    case GL_DEBUG_SEVERITY_MEDIUM:       std::cout << "Severity: medium"; break;
    case GL_DEBUG_SEVERITY_LOW:          std::cout << "Severity: low"; break;
    case GL_DEBUG_SEVERITY_NOTIFICATION: std::cout << "Severity: notification"; break;
  }
	std::cout << std::endl;
  std::cout << std::endl;
}
#include "endcbackdecl.h"

GLFWApplication::GLFWApplication(
	int width,
	int height,
	int actualWidth,
	int actualHeight,
	const char* title,
	int glMajor,
	int glMinor,
	bool debug,
  int maxFPS
	) {
	// Set actual width and height of window to whatever
	// you're working on if not set
	if (actualWidth == 0) actualWidth = width;
	if (actualHeight == 0) actualHeight = height;
	currInRF = 0;
	rollingFPS = 60;
	cumulDelta = 0;
	w = width;
	h = height;
  aw = actualWidth;
  ah = actualHeight;
  mfps = maxFPS;
	projection = glm::scale(projection, glm::vec3(1.0f / width, 1.0f / height, 1));
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glMajor);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glMinor);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
	glfwWindowHint(GLFW_SAMPLES, 4);
	window = glfwCreateWindow(actualWidth, actualHeight, title, nullptr, nullptr);
	if (window == nullptr) {
		glfwTerminate();
		throw u8"Failed to create GLFW window";
	}
	glfwMakeContextCurrent(window);
	glewExperimental = GL_TRUE;
	if (glewInit() != GLEW_OK) {
		throw u8"Failed to initialise GLEW";
	}
	glGetError();
	if (debug) {
		glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
		GLint flags;
		glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
		if (flags & GL_CONTEXT_FLAG_DEBUG_BIT || glMajor >= 5 || (glMajor == 4 && glMinor >= 3)) {
		    // initialise debug output
				glEnable(GL_DEBUG_OUTPUT);
		    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
		    glDebugMessageCallback(glDebugOutput, nullptr);
		    glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
		} else {
			std::cout << "Warning: requested debug output but we can't do it\n";
		}
	}
	glViewport(0, 0, width, height);
	glEnable(GL_MULTISAMPLE);
	glfwSetKeyCallback(window, keyCallback);
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glfwSetCursorPosCallback(window, mouseCallback);
	setVSyncEnable(false);
}

#ifdef __WIN32
#include <windows.h>
inline void wait(double t) {
  Sleep((int) (t * 1000));
}
#else
#include <time.h>
inline void wait(double t) {
  struct timespec rqtp;
  rqtp.tv_sec = (int) (t / 1000000000);
  rqtp.tv_nsec = (int) (t * 1000000000) % 1000000000;
  nanosleep(&rqtp, nullptr);
}
#endif

#define WAITING_DISTANCE 0.5
#define THRESH 0.002

void GLFWApplication::start() {
	currentTime = glfwGetTime();
	initialise();
	while (!glfwWindowShouldClose(window)) {
		GLdouble prevTime = currentTime;
		currentTime = glfwGetTime();
		// Keep at slightly more than maxFPS so FPS doesn't dip below as often
		double goal = prevTime + 0.999 / mfps;
    		  while (currentTime < goal) {
    		  currentTime = glfwGetTime();
    		  double diff = goal - currentTime;
    		  if (diff < THRESH) wait(WAITING_DISTANCE * diff);
    		}
		delta = currentTime - prevTime;
		fps = 1.0 / delta;
		cumulDelta += delta;
		++currInRF;
		if (cumulDelta >= FPS_UPDATE_PERIOD) {
			rollingFPS = currInRF / cumulDelta;
			currInRF = 0;
			cumulDelta = 0;
		}
		currentApp = this;
		glfwPollEvents();
		readKeys();
		tick();
		glfwSwapBuffers(window);
		glFinish();
	}
	delete this;
}

GLFWApplication::~GLFWApplication() {
}

void GLFWApplication::initialise() {
	return;
}

void GLFWApplication::tick() {
	return;
}

void GLFWApplication::readKeys() {
	return;
}

bool GLFWApplication::testKey(int code) {
	return (keys[code >> 6] >> (code & 63)) & 1;
}

void GLFWApplication::setVSyncEnable(bool enable) {
	glfwSwapInterval(enable);
}

void GLFWApplication::setKey(int code) {
	keys[code >> 6] |= (1LL << (code & 63));
}

void GLFWApplication::resetKey(int code) {
	keys[code >> 6] &= ~(1LL << (code & 63));
}

#include "begincbackdecl.h"

void agl::keyCallback(GLFWwindow* window, int key, int scancode, int action, int mode) {
	if (action == GLFW_PRESS) currentApp->setKey(key);
	else if (action == GLFW_RELEASE) currentApp->resetKey(key);
}

void GLFWApplication::onMouse(double xpos, double ypos) {
	return;
}

void agl::mouseCallback(GLFWwindow* window, double xpos, double ypos) {
	currentApp->onMouse(xpos, ypos);
}

#include "endcbackdecl.h"
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/lib/cpp/EventHandlerBase.h>

#include <folly/portability/GTest.h>

using namespace std;
using namespace folly;
using namespace apache::thrift;

class lulz : public exception {
 public:
  explicit lulz(string message) noexcept : message_(move(message)) {}
  const char* what() const noexcept override { return message_.c_str(); }

 private:
  string message_;
};

namespace {

class EventHandler : public TProcessorEventHandler {
 public:
  string ex_type;
  string ex_what;
  void userException(
      void*,
      const char*,
      const std::string& ex_type,
      const std::string& ex_what) override {
    this->ex_type = ex_type;
    this->ex_what = ex_what;
  }
};

template <class E>
exception_ptr to_eptr(const E& e) {
  try {
    throw e;
  } catch (E&) {
    return current_exception();
  }
}

class TProcessorEventHandlerTest : public testing::Test {};

class TProcessorTester : public TProcessorBase {};
class TClientTester : public TClientBase {};

} // namespace

TEST_F(TProcessorEventHandlerTest, with_full_wrapped_eptr) {
  auto wrap = exception_wrapper(lulz("hello"));
  auto eptr = wrap.to_exception_ptr();
  EXPECT_TRUE(wrap.has_exception_ptr());
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("lulz: hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_surprise) {
  auto wrap = exception_wrapper(lulz("hello"));
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("lulz: hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_declared) {
  auto wrap = exception_wrapper(lulz("hello"));
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, true, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, registerProcessorHandler) {
  auto countProcessor = [](const auto& h) {
    TProcessorTester tpt;
    return std::count(
        tpt.getEventHandlers().begin(), tpt.getEventHandlers().end(), h);
  };
  auto countClient = [](const auto& h) {
    TClientTester tct;
    return std::count(
        tct.getEventHandlers().begin(), tct.getEventHandlers().end(), h);
  };

  auto h = std::make_shared<EventHandler>();
  EXPECT_FALSE(countProcessor(h));
  EXPECT_FALSE(countClient(h));
  TProcessorBase::addProcessorEventHandler(h);
  EXPECT_TRUE(countProcessor(h));
  EXPECT_FALSE(countClient(h));
  TClientBase::addClientEventHandler(h);
  EXPECT_TRUE(countProcessor(h));
  EXPECT_TRUE(countClient(h));
  TProcessorBase::removeProcessorEventHandler(h);
  EXPECT_FALSE(countProcessor(h));
  EXPECT_TRUE(countClient(h));
  TClientBase::removeClientEventHandler(h);
  EXPECT_FALSE(countProcessor(h));
  EXPECT_FALSE(countClient(h));
}

TEST_F(TProcessorEventHandlerTest, registrationActivity) {
  auto count = []() { return TProcessorTester().getEventHandlers().size(); };

  auto h1 = std::make_shared<EventHandler>();
  auto h2 = std::make_shared<EventHandler>();
  auto h3 = std::make_shared<EventHandler>();

  EXPECT_EQ(count(), 0);
  TProcessorBase::addProcessorEventHandler(h1);
  EXPECT_EQ(count(), 1);
  TProcessorBase::removeProcessorEventHandler(h1);
  EXPECT_EQ(count(), 0);
  TProcessorBase::addProcessorEventHandler(h1);
  EXPECT_EQ(count(), 1);
  TProcessorBase::addProcessorEventHandler(h2);
  EXPECT_EQ(count(), 2);
  TProcessorBase::removeProcessorEventHandler(h1);
  EXPECT_EQ(count(), 1);
  TProcessorBase::addProcessorEventHandler(h3);
  EXPECT_EQ(count(), 2);
  TProcessorBase::removeProcessorEventHandler(h3);
  EXPECT_EQ(count(), 1);
  TProcessorBase::removeProcessorEventHandler(h2);
  EXPECT_EQ(count(), 0);
}
<commit_msg>Add factory+handler test to EventHandler<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/lib/cpp/EventHandlerBase.h>

#include <folly/portability/GTest.h>

using namespace std;
using namespace folly;
using namespace apache::thrift;

class lulz : public exception {
 public:
  explicit lulz(string message) noexcept : message_(move(message)) {}
  const char* what() const noexcept override { return message_.c_str(); }

 private:
  string message_;
};

namespace {

class EventHandler : public TProcessorEventHandler {
 public:
  string ex_type;
  string ex_what;
  void userException(
      void*,
      const char*,
      const std::string& ex_type,
      const std::string& ex_what) override {
    this->ex_type = ex_type;
    this->ex_what = ex_what;
  }
};

class EventHandlerFactory : public TProcessorEventHandlerFactory {
 public:
  explicit EventHandlerFactory(std::shared_ptr<EventHandler> handler)
      : handler_(std::move(handler)) {}
  std::shared_ptr<TProcessorEventHandler> getEventHandler() override {
    return handler_;
  }

 private:
  std::shared_ptr<EventHandler> handler_;
};

template <class E>
exception_ptr to_eptr(const E& e) {
  try {
    throw e;
  } catch (E&) {
    return current_exception();
  }
}

class TProcessorEventHandlerTest : public testing::Test {};

class TProcessorTester : public TProcessorBase {};
class TClientTester : public TClientBase {};

} // namespace

TEST_F(TProcessorEventHandlerTest, with_full_wrapped_eptr) {
  auto wrap = exception_wrapper(lulz("hello"));
  auto eptr = wrap.to_exception_ptr();
  EXPECT_TRUE(wrap.has_exception_ptr());
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("lulz: hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_surprise) {
  auto wrap = exception_wrapper(lulz("hello"));
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, false, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("lulz: hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, with_wrap_declared) {
  auto wrap = exception_wrapper(lulz("hello"));
  EXPECT_EQ("lulz", wrap.class_name().toStdString());
  EXPECT_EQ("lulz: hello", wrap.what().toStdString());

  EventHandler eh;
  eh.userExceptionWrapped(nullptr, nullptr, true, wrap);
  EXPECT_EQ("lulz", eh.ex_type);
  EXPECT_EQ("hello", eh.ex_what);
}

TEST_F(TProcessorEventHandlerTest, registerProcessorHandler) {
  auto countProcessor = [](const auto& h) {
    TProcessorTester tpt;
    return std::count(
        tpt.getEventHandlers().begin(), tpt.getEventHandlers().end(), h);
  };
  auto countClient = [](const auto& h) {
    TClientTester tct;
    return std::count(
        tct.getEventHandlers().begin(), tct.getEventHandlers().end(), h);
  };

  auto h = std::make_shared<EventHandler>();
  EXPECT_FALSE(countProcessor(h));
  EXPECT_FALSE(countClient(h));
  TProcessorBase::addProcessorEventHandler(h);
  EXPECT_TRUE(countProcessor(h));
  EXPECT_FALSE(countClient(h));
  TClientBase::addClientEventHandler(h);
  EXPECT_TRUE(countProcessor(h));
  EXPECT_TRUE(countClient(h));
  TProcessorBase::removeProcessorEventHandler(h);
  EXPECT_FALSE(countProcessor(h));
  EXPECT_TRUE(countClient(h));
  TClientBase::removeClientEventHandler(h);
  EXPECT_FALSE(countProcessor(h));
  EXPECT_FALSE(countClient(h));
}

TEST_F(TProcessorEventHandlerTest, registrationActivity) {
  auto count = []() { return TProcessorTester().getEventHandlers().size(); };

  auto h1 = std::make_shared<EventHandler>();
  auto h2 = std::make_shared<EventHandler>();
  auto h3 = std::make_shared<EventHandler>();

  EXPECT_EQ(count(), 0);
  TProcessorBase::addProcessorEventHandler(h1);
  EXPECT_EQ(count(), 1);
  TProcessorBase::removeProcessorEventHandler(h1);
  EXPECT_EQ(count(), 0);
  TProcessorBase::addProcessorEventHandler(h1);
  EXPECT_EQ(count(), 1);
  TProcessorBase::addProcessorEventHandler(h2);
  EXPECT_EQ(count(), 2);
  TProcessorBase::removeProcessorEventHandler(h1);
  EXPECT_EQ(count(), 1);
  TProcessorBase::addProcessorEventHandler(h3);
  EXPECT_EQ(count(), 2);
  TProcessorBase::removeProcessorEventHandler(h3);
  EXPECT_EQ(count(), 1);
  TProcessorBase::removeProcessorEventHandler(h2);
  EXPECT_EQ(count(), 0);
}

TEST_F(TProcessorEventHandlerTest, registerMultipleProcessorHandlerAndFactory) {
  auto h1 = std::make_shared<EventHandler>();
  auto h2 = std::make_shared<EventHandler>();
  auto hf1 = std::make_shared<EventHandler>();
  auto hf2 = std::make_shared<EventHandler>();
  auto f1 = std::make_shared<EventHandlerFactory>(hf1);
  auto f2 = std::make_shared<EventHandlerFactory>(hf2);

  auto size = []() { return TProcessorTester().getEventHandlers().size(); };

  EXPECT_EQ(size(), 0);
  TProcessorBase::addProcessorEventHandler(h1);
  EXPECT_EQ(size(), 1);
  TProcessorBase::addProcessorEventHandler(h2);
  EXPECT_EQ(size(), 2);
  TProcessorBase::addProcessorEventHandlerFactory(f1);
  EXPECT_EQ(size(), 3);
  TProcessorBase::addProcessorEventHandlerFactory(f2);
  EXPECT_EQ(size(), 4);
  TProcessorBase::removeProcessorEventHandler(h1);
  EXPECT_EQ(size(), 3);
  TProcessorBase::removeProcessorEventHandlerFactory(f2);
  EXPECT_EQ(size(), 2);
  TProcessorBase::removeProcessorEventHandlerFactory(f1);
  EXPECT_EQ(size(), 1);
  TProcessorBase::removeProcessorEventHandler(h2);
  EXPECT_EQ(size(), 0);
}
<|endoftext|>