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

#include <algorithm>
#include <list>
#include <map>

#include "chrome/browser/browser_thread.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/login/login_prompt.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/auth.h"

namespace {

class LoginPromptBrowserTest : public InProcessBrowserTest {
 public:
  LoginPromptBrowserTest()
      : bad_password_(L"incorrect"), bad_username_(L"nouser") {
    set_show_window(true);

    auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword");
    auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword");
  }

 protected:
  void SetAuthFor(LoginHandler* handler);

  struct AuthInfo {
    std::wstring username_;
    std::wstring password_;

    AuthInfo() {}

    AuthInfo(const std::wstring username,
             const std::wstring password)
        : username_(username), password_(password) {}
  };

  std::map<std::wstring, AuthInfo> auth_map_;
  std::wstring bad_password_;
  std::wstring bad_username_;
};

void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
  const net::AuthChallengeInfo* challenge = handler->auth_info();

  ASSERT_TRUE(challenge);
  std::map<std::wstring, AuthInfo>::iterator i =
      auth_map_.find(challenge->realm);
  EXPECT_TRUE(auth_map_.end() != i);
  if (i != auth_map_.end()) {
    const AuthInfo& info = i->second;
    handler->SetAuth(info.username_, info.password_);
  }
}

// Maintains a set of LoginHandlers that are currently active and
// keeps a count of the notifications that were observed.
class LoginPromptBrowserTestObserver : public NotificationObserver {
 public:
  LoginPromptBrowserTestObserver()
      : auth_needed_count_(0),
        auth_supplied_count_(0),
        auth_cancelled_count_(0) {}

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  void AddHandler(LoginHandler* handler);

  void RemoveHandler(LoginHandler* handler);

  void Register(const NotificationSource& source);

  std::list<LoginHandler*> handlers_;

  // The exact number of notifications we receive is depedent on the
  // number of requests that were dispatched and is subject to a
  // number of factors that we don't directly control here.  The
  // values below should only be used qualitatively.
  int auth_needed_count_;
  int auth_supplied_count_;
  int auth_cancelled_count_;

 private:
  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver);
};

void LoginPromptBrowserTestObserver::Observe(
    NotificationType type,
    const NotificationSource& source,
    const NotificationDetails& details) {
  if (type == NotificationType::AUTH_NEEDED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    AddHandler(login_details->handler());
    auth_needed_count_++;
  } else if (type == NotificationType::AUTH_SUPPLIED) {
    AuthSuppliedLoginNotificationDetails* login_details =
        Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_supplied_count_++;
  } else if (type == NotificationType::AUTH_CANCELLED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_cancelled_count_++;
  }
}

void LoginPromptBrowserTestObserver::AddHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i == handlers_.end());
  if (i == handlers_.end())
    handlers_.push_back(handler);
}

void LoginPromptBrowserTestObserver::RemoveHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i != handlers_.end());
  if (i != handlers_.end())
    handlers_.erase(i);
}

void LoginPromptBrowserTestObserver::Register(
    const NotificationSource& source) {
  registrar_.Add(this, NotificationType::AUTH_NEEDED, source);
  registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source);
  registrar_.Add(this, NotificationType::AUTH_CANCELLED, source);
}

template <NotificationType::Type T>
class WindowedNavigationObserver
    : public ui_test_utils::WindowedNotificationObserver {
 public:
  explicit WindowedNavigationObserver(NavigationController* controller)
      : ui_test_utils::WindowedNotificationObserver(
          T, Source<NavigationController>(controller)) {}
};

typedef WindowedNavigationObserver<NotificationType::LOAD_STOP>
    WindowedLoadStopObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_NEEDED>
    WindowedAuthNeededObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_CANCELLED>
    WindowedAuthCancelledObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_SUPPLIED>
    WindowedAuthSuppliedObserver;

const char* kPrefetchAuthPage = "files/login/prefetch.html";

const char* kMultiRealmTestPage = "files/login/multi_realm.html";
const int   kMultiRealmTestRealmCount = 2;
const int   kMultiRealmTestResourceCount = 4;

const char* kSingleRealmTestPage = "files/login/single_realm.html";
const int   kSingleRealmTestResourceCount = 6;

// Confirm that <link rel="prefetch"> targetting an auth required
// resource does not provide a login dialog.  These types of requests
// should instead just cancel the auth.

// Unfortunately, this test doesn't assert on anything for its
// correctness.  Instead, it relies on the auth dialog blocking the
// browser, and triggering a timeout to cause failure when the
// prefetch resource requires authorization.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
  ASSERT_TRUE(test_server()->Start());

  GURL test_page = test_server()->GetURL(kPrefetchAuthPage);

  class SetPrefetchForTest {
   public:
    explicit SetPrefetchForTest(bool prefetch)
        : old_prefetch_state_(ResourceDispatcherHost::is_prefetch_enabled()) {
      ResourceDispatcherHost::set_is_prefetch_enabled(prefetch);
    }

    ~SetPrefetchForTest() {
      ResourceDispatcherHost::set_is_prefetch_enabled(old_prefetch_state_);
    }
   private:
    bool old_prefetch_state_;
  } set_prefetch_for_test(true);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);
  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);

  load_stop_waiter.Wait();
  EXPECT_TRUE(observer.handlers_.empty());
  EXPECT_TRUE(test_server()->Stop());
}

// Test handling of resources that require authentication even though
// the page they are included on doesn't.  In this case we should only
// present the minimal number of prompts necessary for successfully
// displaying the page.  First we check whether cancelling works as
// expected.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      handler->CancelAuth();
      auth_cancelled_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_EQ(0, observer.auth_supplied_count_);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Similar to the MultipleRealmCancellation test above, but tests
// whether supplying credentials work as exepcted.
#if defined(OS_WIN)
// See http://crbug.com/70960
#define MAYBE_MultipleRealmConfirmation DISABLED_MultipleRealmConfirmation
#else
#define MAYBE_MultipleRealmConfirmation MultipleRealmConfirmation
#endif
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
                       MAYBE_MultipleRealmConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  int n_handlers = 0;

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_supplied_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Testing for recovery from an incorrect password for the case where
// there are multiple authenticated resources.
// Marked as flaky.  See http://crbug.com/69266 and http://crbug.com/68860
// TODO(asanka): Remove logging when timeout issues are resolved.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, FLAKY_IncorrectConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kSingleRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  LOG(INFO) <<
      "Begin test run "
      "(tracing for potential hang. crbug.com/69266)";
  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    LOG(INFO) << "Waiting for initial AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  EXPECT_FALSE(observer.handlers_.empty());

  if (!observer.handlers_.empty()) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
    LoginHandler* handler = *observer.handlers_.begin();

    ASSERT_TRUE(handler);
    handler->SetAuth(bad_username_, bad_password_);
    LOG(INFO) << "Waiting for initial AUTH_SUPPLIED";
    auth_supplied_waiter.Wait();

    // The request should be retried after the incorrect password is
    // supplied.  This should result in a new AUTH_NEEDED notification
    // for the same realm.
    LOG(INFO) << "Waiting for secondary AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < 1) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      LOG(INFO) << "Waiting for secondary AUTH_SUPPLIED";
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < 1) {
      LOG(INFO) << "Waiting for additional AUTH_NEEDED";
      auth_needed_waiter.Wait();
    }
  }

  // The single realm test has only one realm, and thus only one login
  // prompt.
  EXPECT_EQ(1, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_);
  LOG(INFO) << "Waiting for LOAD_STOP";
  load_stop_waiter.Wait();
  EXPECT_TRUE(test_server()->Stop());
  LOG(INFO) << "Done with test";
}
}  // namespace
<commit_msg>Disable LoginPromptBrowserTest.IncorrectConfirmation<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>
#include <list>
#include <map>

#include "chrome/browser/browser_thread.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/login/login_prompt.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/auth.h"

namespace {

class LoginPromptBrowserTest : public InProcessBrowserTest {
 public:
  LoginPromptBrowserTest()
      : bad_password_(L"incorrect"), bad_username_(L"nouser") {
    set_show_window(true);

    auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword");
    auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword");
  }

 protected:
  void SetAuthFor(LoginHandler* handler);

  struct AuthInfo {
    std::wstring username_;
    std::wstring password_;

    AuthInfo() {}

    AuthInfo(const std::wstring username,
             const std::wstring password)
        : username_(username), password_(password) {}
  };

  std::map<std::wstring, AuthInfo> auth_map_;
  std::wstring bad_password_;
  std::wstring bad_username_;
};

void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
  const net::AuthChallengeInfo* challenge = handler->auth_info();

  ASSERT_TRUE(challenge);
  std::map<std::wstring, AuthInfo>::iterator i =
      auth_map_.find(challenge->realm);
  EXPECT_TRUE(auth_map_.end() != i);
  if (i != auth_map_.end()) {
    const AuthInfo& info = i->second;
    handler->SetAuth(info.username_, info.password_);
  }
}

// Maintains a set of LoginHandlers that are currently active and
// keeps a count of the notifications that were observed.
class LoginPromptBrowserTestObserver : public NotificationObserver {
 public:
  LoginPromptBrowserTestObserver()
      : auth_needed_count_(0),
        auth_supplied_count_(0),
        auth_cancelled_count_(0) {}

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  void AddHandler(LoginHandler* handler);

  void RemoveHandler(LoginHandler* handler);

  void Register(const NotificationSource& source);

  std::list<LoginHandler*> handlers_;

  // The exact number of notifications we receive is depedent on the
  // number of requests that were dispatched and is subject to a
  // number of factors that we don't directly control here.  The
  // values below should only be used qualitatively.
  int auth_needed_count_;
  int auth_supplied_count_;
  int auth_cancelled_count_;

 private:
  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver);
};

void LoginPromptBrowserTestObserver::Observe(
    NotificationType type,
    const NotificationSource& source,
    const NotificationDetails& details) {
  if (type == NotificationType::AUTH_NEEDED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    AddHandler(login_details->handler());
    auth_needed_count_++;
  } else if (type == NotificationType::AUTH_SUPPLIED) {
    AuthSuppliedLoginNotificationDetails* login_details =
        Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_supplied_count_++;
  } else if (type == NotificationType::AUTH_CANCELLED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_cancelled_count_++;
  }
}

void LoginPromptBrowserTestObserver::AddHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i == handlers_.end());
  if (i == handlers_.end())
    handlers_.push_back(handler);
}

void LoginPromptBrowserTestObserver::RemoveHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i != handlers_.end());
  if (i != handlers_.end())
    handlers_.erase(i);
}

void LoginPromptBrowserTestObserver::Register(
    const NotificationSource& source) {
  registrar_.Add(this, NotificationType::AUTH_NEEDED, source);
  registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source);
  registrar_.Add(this, NotificationType::AUTH_CANCELLED, source);
}

template <NotificationType::Type T>
class WindowedNavigationObserver
    : public ui_test_utils::WindowedNotificationObserver {
 public:
  explicit WindowedNavigationObserver(NavigationController* controller)
      : ui_test_utils::WindowedNotificationObserver(
          T, Source<NavigationController>(controller)) {}
};

typedef WindowedNavigationObserver<NotificationType::LOAD_STOP>
    WindowedLoadStopObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_NEEDED>
    WindowedAuthNeededObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_CANCELLED>
    WindowedAuthCancelledObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_SUPPLIED>
    WindowedAuthSuppliedObserver;

const char* kPrefetchAuthPage = "files/login/prefetch.html";

const char* kMultiRealmTestPage = "files/login/multi_realm.html";
const int   kMultiRealmTestRealmCount = 2;
const int   kMultiRealmTestResourceCount = 4;

const char* kSingleRealmTestPage = "files/login/single_realm.html";
const int   kSingleRealmTestResourceCount = 6;

// Confirm that <link rel="prefetch"> targetting an auth required
// resource does not provide a login dialog.  These types of requests
// should instead just cancel the auth.

// Unfortunately, this test doesn't assert on anything for its
// correctness.  Instead, it relies on the auth dialog blocking the
// browser, and triggering a timeout to cause failure when the
// prefetch resource requires authorization.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
  ASSERT_TRUE(test_server()->Start());

  GURL test_page = test_server()->GetURL(kPrefetchAuthPage);

  class SetPrefetchForTest {
   public:
    explicit SetPrefetchForTest(bool prefetch)
        : old_prefetch_state_(ResourceDispatcherHost::is_prefetch_enabled()) {
      ResourceDispatcherHost::set_is_prefetch_enabled(prefetch);
    }

    ~SetPrefetchForTest() {
      ResourceDispatcherHost::set_is_prefetch_enabled(old_prefetch_state_);
    }
   private:
    bool old_prefetch_state_;
  } set_prefetch_for_test(true);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);
  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);

  load_stop_waiter.Wait();
  EXPECT_TRUE(observer.handlers_.empty());
  EXPECT_TRUE(test_server()->Stop());
}

// Test handling of resources that require authentication even though
// the page they are included on doesn't.  In this case we should only
// present the minimal number of prompts necessary for successfully
// displaying the page.  First we check whether cancelling works as
// expected.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      handler->CancelAuth();
      auth_cancelled_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_EQ(0, observer.auth_supplied_count_);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Similar to the MultipleRealmCancellation test above, but tests
// whether supplying credentials work as exepcted.
#if defined(OS_WIN)
// See http://crbug.com/70960
#define MAYBE_MultipleRealmConfirmation DISABLED_MultipleRealmConfirmation
#else
#define MAYBE_MultipleRealmConfirmation MultipleRealmConfirmation
#endif
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
                       MAYBE_MultipleRealmConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  int n_handlers = 0;

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_supplied_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Testing for recovery from an incorrect password for the case where
// there are multiple authenticated resources.
// Marked as flaky.  See http://crbug.com/69266 and http://crbug.com/68860
// TODO(asanka): Remove logging when timeout issues are resolved.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, DISABLED_IncorrectConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kSingleRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  LOG(INFO) <<
      "Begin test run "
      "(tracing for potential hang. crbug.com/69266)";
  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    LOG(INFO) << "Waiting for initial AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  EXPECT_FALSE(observer.handlers_.empty());

  if (!observer.handlers_.empty()) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
    LoginHandler* handler = *observer.handlers_.begin();

    ASSERT_TRUE(handler);
    handler->SetAuth(bad_username_, bad_password_);
    LOG(INFO) << "Waiting for initial AUTH_SUPPLIED";
    auth_supplied_waiter.Wait();

    // The request should be retried after the incorrect password is
    // supplied.  This should result in a new AUTH_NEEDED notification
    // for the same realm.
    LOG(INFO) << "Waiting for secondary AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < 1) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      LOG(INFO) << "Waiting for secondary AUTH_SUPPLIED";
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < 1) {
      LOG(INFO) << "Waiting for additional AUTH_NEEDED";
      auth_needed_waiter.Wait();
    }
  }

  // The single realm test has only one realm, and thus only one login
  // prompt.
  EXPECT_EQ(1, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_);
  LOG(INFO) << "Waiting for LOAD_STOP";
  load_stop_waiter.Wait();
  EXPECT_TRUE(test_server()->Stop());
  LOG(INFO) << "Done with test";
}
}  // namespace
<|endoftext|>


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

#include <algorithm>
#include <list>
#include <map>

#include "chrome/browser/browser_thread.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/login/login_prompt.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/auth.h"

namespace {

class LoginPromptBrowserTest : public InProcessBrowserTest {
 public:
  LoginPromptBrowserTest()
      : bad_password_(L"incorrect"), bad_username_(L"nouser") {
    set_show_window(true);

    auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword");
    auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword");
  }

 protected:
  void SetAuthFor(LoginHandler* handler);

  struct AuthInfo {
    std::wstring username_;
    std::wstring password_;

    AuthInfo() {}

    AuthInfo(const std::wstring username,
             const std::wstring password)
        : username_(username), password_(password) {}
  };

  std::map<std::wstring, AuthInfo> auth_map_;
  std::wstring bad_password_;
  std::wstring bad_username_;
};

void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
  const net::AuthChallengeInfo* challenge = handler->auth_info();

  ASSERT_TRUE(challenge);
  std::map<std::wstring, AuthInfo>::iterator i =
      auth_map_.find(challenge->realm);
  EXPECT_TRUE(auth_map_.end() != i);
  if (i != auth_map_.end()) {
    const AuthInfo& info = i->second;
    handler->SetAuth(info.username_, info.password_);
  }
}

// Maintains a set of LoginHandlers that are currently active and
// keeps a count of the notifications that were observed.
class LoginPromptBrowserTestObserver : public NotificationObserver {
 public:
  LoginPromptBrowserTestObserver()
      : auth_needed_count_(0),
        auth_supplied_count_(0),
        auth_cancelled_count_(0) {}

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  void AddHandler(LoginHandler* handler);

  void RemoveHandler(LoginHandler* handler);

  void Register(const NotificationSource& source);

  std::list<LoginHandler*> handlers_;

  // The exact number of notifications we receive is depedent on the
  // number of requests that were dispatched and is subject to a
  // number of factors that we don't directly control here.  The
  // values below should only be used qualitatively.
  int auth_needed_count_;
  int auth_supplied_count_;
  int auth_cancelled_count_;

 private:
  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver);
};

void LoginPromptBrowserTestObserver::Observe(
    NotificationType type,
    const NotificationSource& source,
    const NotificationDetails& details) {
  if (type == NotificationType::AUTH_NEEDED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    AddHandler(login_details->handler());
    auth_needed_count_++;
  } else if (type == NotificationType::AUTH_SUPPLIED) {
    AuthSuppliedLoginNotificationDetails* login_details =
        Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_supplied_count_++;
  } else if (type == NotificationType::AUTH_CANCELLED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_cancelled_count_++;
  }
}

void LoginPromptBrowserTestObserver::AddHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i == handlers_.end());
  if (i == handlers_.end())
    handlers_.push_back(handler);
}

void LoginPromptBrowserTestObserver::RemoveHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i != handlers_.end());
  if (i != handlers_.end())
    handlers_.erase(i);
}

void LoginPromptBrowserTestObserver::Register(
    const NotificationSource& source) {
  registrar_.Add(this, NotificationType::AUTH_NEEDED, source);
  registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source);
  registrar_.Add(this, NotificationType::AUTH_CANCELLED, source);
}

template <NotificationType::Type T>
class WindowedNavigationObserver
    : public ui_test_utils::WindowedNotificationObserver {
 public:
  explicit WindowedNavigationObserver(NavigationController* controller)
      : ui_test_utils::WindowedNotificationObserver(
          T, Source<NavigationController>(controller)) {}
};

typedef WindowedNavigationObserver<NotificationType::LOAD_STOP>
    WindowedLoadStopObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_NEEDED>
    WindowedAuthNeededObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_CANCELLED>
    WindowedAuthCancelledObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_SUPPLIED>
    WindowedAuthSuppliedObserver;

const char* kPrefetchAuthPage = "files/login/prefetch.html";

const char* kMultiRealmTestPage = "files/login/multi_realm.html";
const int   kMultiRealmTestRealmCount = 2;
const int   kMultiRealmTestResourceCount = 4;

const char* kSingleRealmTestPage = "files/login/single_realm.html";
const int   kSingleRealmTestResourceCount = 6;

// Confirm that <link rel="prefetch"> targetting an auth required
// resource does not provide a login dialog.  These types of requests
// should instead just cancel the auth.

// Unfortunately, this test doesn't assert on anything for its
// correctness.  Instead, it relies on the auth dialog blocking the
// browser, and triggering a timeout to cause failure when the
// prefetch resource requires authorization.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
  ASSERT_TRUE(test_server()->Start());

  GURL test_page = test_server()->GetURL(kPrefetchAuthPage);

  class SetPrefetchForTest {
   public:
    explicit SetPrefetchForTest(bool prefetch)
        : old_prefetch_state_(ResourceDispatcherHost::is_prefetch_enabled()) {
      ResourceDispatcherHost::set_is_prefetch_enabled(prefetch);
    }

    ~SetPrefetchForTest() {
      ResourceDispatcherHost::set_is_prefetch_enabled(old_prefetch_state_);
    }
   private:
    bool old_prefetch_state_;
  } set_prefetch_for_test(true);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);
  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);

  load_stop_waiter.Wait();
  EXPECT_TRUE(observer.handlers_.empty());
  EXPECT_TRUE(test_server()->Stop());
}

// Test handling of resources that require authentication even though
// the page they are included on doesn't.  In this case we should only
// present the minimal number of prompts necessary for successfully
// displaying the page.  First we check whether cancelling works as
// expected.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      handler->CancelAuth();
      auth_cancelled_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_EQ(0, observer.auth_supplied_count_);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Similar to the MultipleRealmCancellation test above, but tests
// whether supplying credentials work as exepcted.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  int n_handlers = 0;

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_supplied_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Testing for recovery from an incorrect password for the case where
// there are multiple authenticated resources.
// Marked as flaky.  See http://crbug.com/69266 and http://crbug.com/68860
// TODO(asanka): Remove logging when timeout issues are resolved.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, FLAKY_IncorrectConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kSingleRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  LOG(INFO) <<
      "Begin test run "
      "(tracing for potential hang. crbug.com/69266)";
  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    LOG(INFO) << "Waiting for initial AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  EXPECT_FALSE(observer.handlers_.empty());

  if (!observer.handlers_.empty()) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
    LoginHandler* handler = *observer.handlers_.begin();

    ASSERT_TRUE(handler);
    handler->SetAuth(bad_username_, bad_password_);
    LOG(INFO) << "Waiting for initial AUTH_SUPPLIED";
    auth_supplied_waiter.Wait();

    // The request should be retried after the incorrect password is
    // supplied.  This should result in a new AUTH_NEEDED notification
    // for the same realm.
    LOG(INFO) << "Waiting for secondary AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < 1) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      LOG(INFO) << "Waiting for secondary AUTH_SUPPLIED";
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < 1) {
      LOG(INFO) << "Waiting for additional AUTH_NEEDED";
      auth_needed_waiter.Wait();
    }
  }

  // The single realm test has only one realm, and thus only one login
  // prompt.
  EXPECT_EQ(1, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_);
  LOG(INFO) << "Waiting for LOAD_STOP";
  load_stop_waiter.Wait();
  EXPECT_TRUE(test_server()->Stop());
  LOG(INFO) << "Done with test";
}
}  // namespace
<commit_msg>MultipleRealmConfirmation hangs on vista tests. TEST=none BUG=70960<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>
#include <list>
#include <map>

#include "chrome/browser/browser_thread.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/login/login_prompt.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/auth.h"

namespace {

class LoginPromptBrowserTest : public InProcessBrowserTest {
 public:
  LoginPromptBrowserTest()
      : bad_password_(L"incorrect"), bad_username_(L"nouser") {
    set_show_window(true);

    auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword");
    auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword");
  }

 protected:
  void SetAuthFor(LoginHandler* handler);

  struct AuthInfo {
    std::wstring username_;
    std::wstring password_;

    AuthInfo() {}

    AuthInfo(const std::wstring username,
             const std::wstring password)
        : username_(username), password_(password) {}
  };

  std::map<std::wstring, AuthInfo> auth_map_;
  std::wstring bad_password_;
  std::wstring bad_username_;
};

void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
  const net::AuthChallengeInfo* challenge = handler->auth_info();

  ASSERT_TRUE(challenge);
  std::map<std::wstring, AuthInfo>::iterator i =
      auth_map_.find(challenge->realm);
  EXPECT_TRUE(auth_map_.end() != i);
  if (i != auth_map_.end()) {
    const AuthInfo& info = i->second;
    handler->SetAuth(info.username_, info.password_);
  }
}

// Maintains a set of LoginHandlers that are currently active and
// keeps a count of the notifications that were observed.
class LoginPromptBrowserTestObserver : public NotificationObserver {
 public:
  LoginPromptBrowserTestObserver()
      : auth_needed_count_(0),
        auth_supplied_count_(0),
        auth_cancelled_count_(0) {}

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  void AddHandler(LoginHandler* handler);

  void RemoveHandler(LoginHandler* handler);

  void Register(const NotificationSource& source);

  std::list<LoginHandler*> handlers_;

  // The exact number of notifications we receive is depedent on the
  // number of requests that were dispatched and is subject to a
  // number of factors that we don't directly control here.  The
  // values below should only be used qualitatively.
  int auth_needed_count_;
  int auth_supplied_count_;
  int auth_cancelled_count_;

 private:
  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver);
};

void LoginPromptBrowserTestObserver::Observe(
    NotificationType type,
    const NotificationSource& source,
    const NotificationDetails& details) {
  if (type == NotificationType::AUTH_NEEDED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    AddHandler(login_details->handler());
    auth_needed_count_++;
  } else if (type == NotificationType::AUTH_SUPPLIED) {
    AuthSuppliedLoginNotificationDetails* login_details =
        Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_supplied_count_++;
  } else if (type == NotificationType::AUTH_CANCELLED) {
    LoginNotificationDetails* login_details =
        Details<LoginNotificationDetails>(details).ptr();
    RemoveHandler(login_details->handler());
    auth_cancelled_count_++;
  }
}

void LoginPromptBrowserTestObserver::AddHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i == handlers_.end());
  if (i == handlers_.end())
    handlers_.push_back(handler);
}

void LoginPromptBrowserTestObserver::RemoveHandler(LoginHandler* handler) {
  std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
                                                   handlers_.end(),
                                                   handler);
  EXPECT_TRUE(i != handlers_.end());
  if (i != handlers_.end())
    handlers_.erase(i);
}

void LoginPromptBrowserTestObserver::Register(
    const NotificationSource& source) {
  registrar_.Add(this, NotificationType::AUTH_NEEDED, source);
  registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source);
  registrar_.Add(this, NotificationType::AUTH_CANCELLED, source);
}

template <NotificationType::Type T>
class WindowedNavigationObserver
    : public ui_test_utils::WindowedNotificationObserver {
 public:
  explicit WindowedNavigationObserver(NavigationController* controller)
      : ui_test_utils::WindowedNotificationObserver(
          T, Source<NavigationController>(controller)) {}
};

typedef WindowedNavigationObserver<NotificationType::LOAD_STOP>
    WindowedLoadStopObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_NEEDED>
    WindowedAuthNeededObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_CANCELLED>
    WindowedAuthCancelledObserver;

typedef WindowedNavigationObserver<NotificationType::AUTH_SUPPLIED>
    WindowedAuthSuppliedObserver;

const char* kPrefetchAuthPage = "files/login/prefetch.html";

const char* kMultiRealmTestPage = "files/login/multi_realm.html";
const int   kMultiRealmTestRealmCount = 2;
const int   kMultiRealmTestResourceCount = 4;

const char* kSingleRealmTestPage = "files/login/single_realm.html";
const int   kSingleRealmTestResourceCount = 6;

// Confirm that <link rel="prefetch"> targetting an auth required
// resource does not provide a login dialog.  These types of requests
// should instead just cancel the auth.

// Unfortunately, this test doesn't assert on anything for its
// correctness.  Instead, it relies on the auth dialog blocking the
// browser, and triggering a timeout to cause failure when the
// prefetch resource requires authorization.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
  ASSERT_TRUE(test_server()->Start());

  GURL test_page = test_server()->GetURL(kPrefetchAuthPage);

  class SetPrefetchForTest {
   public:
    explicit SetPrefetchForTest(bool prefetch)
        : old_prefetch_state_(ResourceDispatcherHost::is_prefetch_enabled()) {
      ResourceDispatcherHost::set_is_prefetch_enabled(prefetch);
    }

    ~SetPrefetchForTest() {
      ResourceDispatcherHost::set_is_prefetch_enabled(old_prefetch_state_);
    }
   private:
    bool old_prefetch_state_;
  } set_prefetch_for_test(true);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);
  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);

  load_stop_waiter.Wait();
  EXPECT_TRUE(observer.handlers_.empty());
  EXPECT_TRUE(test_server()->Stop());
}

// Test handling of resources that require authentication even though
// the page they are included on doesn't.  In this case we should only
// present the minimal number of prompts necessary for successfully
// displaying the page.  First we check whether cancelling works as
// expected.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      handler->CancelAuth();
      auth_cancelled_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_EQ(0, observer.auth_supplied_count_);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Similar to the MultipleRealmCancellation test above, but tests
// whether supplying credentials work as exepcted.
#if defined(OS_WIN)
// See http://crbug.com/70960
#define MAYBE_MultipleRealmConfirmation DISABLED_MultipleRealmConfirmation
#else
#define MAYBE_MultipleRealmConfirmation MultipleRealmConfirmation
#endif
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
                       MAYBE_MultipleRealmConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kMultiRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);
  int n_handlers = 0;

  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    auth_needed_waiter.Wait();
  }

  while (n_handlers < kMultiRealmTestRealmCount) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < kMultiRealmTestRealmCount)
      auth_needed_waiter.Wait();
  }

  load_stop_waiter.Wait();

  EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_LT(0, observer.auth_supplied_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_TRUE(test_server()->Stop());
}

// Testing for recovery from an incorrect password for the case where
// there are multiple authenticated resources.
// Marked as flaky.  See http://crbug.com/69266 and http://crbug.com/68860
// TODO(asanka): Remove logging when timeout issues are resolved.
IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, FLAKY_IncorrectConfirmation) {
  ASSERT_TRUE(test_server()->Start());
  GURL test_page = test_server()->GetURL(kSingleRealmTestPage);

  TabContentsWrapper* contents =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(contents);

  NavigationController* controller = &contents->controller();
  LoginPromptBrowserTestObserver observer;

  observer.Register(Source<NavigationController>(controller));

  WindowedLoadStopObserver load_stop_waiter(controller);

  LOG(INFO) <<
      "Begin test run "
      "(tracing for potential hang. crbug.com/69266)";
  {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
    LOG(INFO) << "Waiting for initial AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  EXPECT_FALSE(observer.handlers_.empty());

  if (!observer.handlers_.empty()) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);
    WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
    LoginHandler* handler = *observer.handlers_.begin();

    ASSERT_TRUE(handler);
    handler->SetAuth(bad_username_, bad_password_);
    LOG(INFO) << "Waiting for initial AUTH_SUPPLIED";
    auth_supplied_waiter.Wait();

    // The request should be retried after the incorrect password is
    // supplied.  This should result in a new AUTH_NEEDED notification
    // for the same realm.
    LOG(INFO) << "Waiting for secondary AUTH_NEEDED";
    auth_needed_waiter.Wait();
  }

  int n_handlers = 0;

  while (n_handlers < 1) {
    WindowedAuthNeededObserver auth_needed_waiter(controller);

    while (!observer.handlers_.empty()) {
      WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
      LoginHandler* handler = *observer.handlers_.begin();

      ASSERT_TRUE(handler);
      n_handlers++;
      SetAuthFor(handler);
      LOG(INFO) << "Waiting for secondary AUTH_SUPPLIED";
      auth_supplied_waiter.Wait();
    }

    if (n_handlers < 1) {
      LOG(INFO) << "Waiting for additional AUTH_NEEDED";
      auth_needed_waiter.Wait();
    }
  }

  // The single realm test has only one realm, and thus only one login
  // prompt.
  EXPECT_EQ(1, n_handlers);
  EXPECT_LT(0, observer.auth_needed_count_);
  EXPECT_EQ(0, observer.auth_cancelled_count_);
  EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_);
  LOG(INFO) << "Waiting for LOAD_STOP";
  load_stop_waiter.Wait();
  EXPECT_TRUE(test_server()->Stop());
  LOG(INFO) << "Done with test";
}
}  // namespace
<|endoftext|>


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

#include "chrome/browser/ui/webui/bidi_checker_web_ui_test.h"

#include "base/base_paths.h"
#include "base/i18n/rtl.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/autofill/autofill_common_test.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/personal_data_manager.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_POSIX) && defined(TOOLKIT_USES_GTK)
#include <gtk/gtk.h>
#endif

// These tests are failing on linux views build. crbug.com/96891
#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
#define MAYBE_TestCrashesPageRTL DISABLED_TestCrashesPageRTL
#define MAYBE_TestDownloadsPageRTL DISABLED_TestDownloadsPageRTL
#define MAYBE_TestMainHistoryPageRTL DISABLED_TestMainHistoryPageRTL
#define MAYBE_TestNewTabPageRTL DISABLED_TestNewTabPageRTL
#define MAYBE_TestPluginsPageRTL DISABLED_TestPluginsPageRTL
#define MAYBE_TestSettingsAutofillPageRTL DISABLED_TestSettingsAutofillPageRTL
#define MAYBE_TestSettingsPageRTL DISABLED_TestSettingsPageRTL
#else
#define MAYBE_TestCrashesPageRTL TestCrashesPageRTL
#define MAYBE_TestDownloadsPageRTL TestDownloadsPageRTL
#define MAYBE_TestMainHistoryPageRTL TestMainHistoryPageRTL
#define MAYBE_TestNewTabPageRTL TestNewTabPageRTL
#define MAYBE_TestPluginsPageRTL TestPluginsPageRTL
#define MAYBE_TestSettingsAutofillPageRTL TestSettingsAutofillPageRTL
#define MAYBE_TestSettingsPageRTL TestSettingsPageRTL
#endif

static const FilePath::CharType* kWebUIBidiCheckerLibraryJS =
    FILE_PATH_LITERAL("third_party/bidichecker/bidichecker_packaged.js");

namespace {
FilePath WebUIBidiCheckerLibraryJSPath() {
  FilePath src_root;
  if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_root))
    LOG(ERROR) << "Couldn't find source root";
  return src_root.Append(kWebUIBidiCheckerLibraryJS);
}
}

static const FilePath::CharType* kBidiCheckerTestsJS =
    FILE_PATH_LITERAL("bidichecker_tests.js");

WebUIBidiCheckerBrowserTest::~WebUIBidiCheckerBrowserTest() {}

WebUIBidiCheckerBrowserTest::WebUIBidiCheckerBrowserTest() {}

void WebUIBidiCheckerBrowserTest::SetUpInProcessBrowserTestFixture() {
  WebUIBrowserTest::SetUpInProcessBrowserTestFixture();
  WebUIBrowserTest::AddLibrary(WebUIBidiCheckerLibraryJSPath());
  WebUIBrowserTest::AddLibrary(FilePath(kBidiCheckerTestsJS));
}

void WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(const char pageURL[],
                                                       bool isRTL) {
  ui_test_utils::NavigateToURL(browser(), GURL(pageURL));
  ASSERT_TRUE(RunJavascriptTest("runBidiChecker",
                                Value::CreateStringValue(pageURL),
                                Value::CreateBooleanValue(isRTL)));
}

// WebUIBidiCheckerBrowserTestFakeBidi

WebUIBidiCheckerBrowserTestFakeBidi::~WebUIBidiCheckerBrowserTestFakeBidi() {}

WebUIBidiCheckerBrowserTestFakeBidi::WebUIBidiCheckerBrowserTestFakeBidi() {}

void WebUIBidiCheckerBrowserTestFakeBidi::SetUpOnMainThread() {
  WebUIBidiCheckerBrowserTest::SetUpOnMainThread();
  FilePath pak_path;
  app_locale_ = base::i18n::GetConfiguredLocale();
  ASSERT_TRUE(PathService::Get(base::FILE_MODULE, &pak_path));
  pak_path = pak_path.DirName();
  pak_path = pak_path.AppendASCII("pseudo_locales");
  pak_path = pak_path.AppendASCII("fake-bidi");
  pak_path = pak_path.ReplaceExtension(FILE_PATH_LITERAL("pak"));
  ResourceBundle::GetSharedInstance().OverrideLocalePakForTest(pak_path);
  ResourceBundle::ReloadSharedInstance("he");
#if defined(OS_POSIX) && defined(TOOLKIT_USES_GTK)
  gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
#endif
}

void WebUIBidiCheckerBrowserTestFakeBidi::CleanUpOnMainThread() {
  WebUIBidiCheckerBrowserTest::CleanUpOnMainThread();
#if defined(OS_POSIX) && defined(TOOLKIT_USES_GTK)
  gtk_widget_set_default_direction(GTK_TEXT_DIR_LTR);
#endif
  ResourceBundle::GetSharedInstance().OverrideLocalePakForTest(FilePath());
  ResourceBundle::ReloadSharedInstance(app_locale_);
}

// Tests

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestMainHistoryPageLTR) {
  HistoryService* history_service =
      browser()->profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
  GURL history_url = GURL("http://www.ynet.co.il");
  history_service->AddPage(history_url, history::SOURCE_BROWSED);
  string16 title;
  ASSERT_TRUE(UTF8ToUTF16("\xD7\x91\xD7\x93\xD7\x99\xD7\xA7\xD7\x94\x21",
                          12,
                          &title));
  history_service->SetPageTitle(history_url, title);
  RunBidiCheckerOnPage(chrome::kChromeUIHistoryURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestMainHistoryPageRTL) {
  HistoryService* history_service =
      browser()->profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
  GURL history_url = GURL("http://www.google.com");
  history_service->AddPage(history_url, history::SOURCE_BROWSED);
  string16 title = UTF8ToUTF16("Google");
  history_service->SetPageTitle(history_url, title);
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUIHistoryURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestAboutPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIAboutURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestBugReportPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIBugReportURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestCrashesPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUICrashesURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestCrashesPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUICrashesURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestDownloadsPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIDownloadsURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestDownloadsPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(
      chrome::kChromeUIDownloadsURL, true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestNewTabPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUINewTabURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestNewTabPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUINewTabURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestPluginsPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIPluginsURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestPluginsPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUIPluginsURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestSettingsPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUISettingsURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestSettingsPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(
      chrome::kChromeUISettingsURL, true);
}

#if defined(OS_MACOSX)
// http://crbug.com/94642
#define MAYBE_TestSettingsAutofillPageLTR FLAKY_TestSettingsAutofillPageLTR
#elif defined(OS_WIN)
// http://crbug.com/95425
#define MAYBE_TestSettingsAutofillPageLTR FAILS_TestSettingsAutofillPageLTR
#else
#define MAYBE_TestSettingsAutofillPageLTR TestSettingsAutofillPageLTR
#endif  // defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest,
                       MAYBE_TestSettingsAutofillPageLTR) {
  std::string url(chrome::kChromeUISettingsURL);
  url += std::string(chrome::kAutofillSubPage);

  autofill_test::DisableSystemServices(browser()->profile());
  AutofillProfile profile;
  autofill_test::SetProfileInfo(
      &profile,
      "\xD7\x9E\xD7\xA9\xD7\x94",
      "\xD7\x91",
      "\xD7\x9B\xD7\x94\xD7\x9F",
      "moshe.b.cohen@biditest.com",
      "\xD7\x91\xD7\x93\xD7\x99\xD7\xA7\xD7\x94\x20\xD7\x91\xD7\xA2\xD7\x9E",
      "\xD7\x93\xD7\xA8\xD7\x9A\x20\xD7\x9E\xD7\xA0\xD7\x97\xD7\x9D\x20\xD7\x91\xD7\x92\xD7\x99\xD7\x9F\x20\x32\x33",
      "\xD7\xA7\xD7\x95\xD7\x9E\xD7\x94\x20\x32\x36",
      "\xD7\xAA\xD7\x9C\x20\xD7\x90\xD7\x91\xD7\x99\xD7\x91",
      "",
      "66183",
      "\xD7\x99\xD7\xA9\xD7\xA8\xD7\x90\xD7\x9C",
      "0000");

  PersonalDataManager* personal_data_manager =
    browser()->profile()->GetPersonalDataManager();
  ASSERT_TRUE(personal_data_manager);

  personal_data_manager->AddProfile(profile);

  RunBidiCheckerOnPage(url.c_str(), false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestSettingsAutofillPageRTL) {
  std::string url(chrome::kChromeUISettingsURL);
  url += std::string(chrome::kAutofillSubPage);

  autofill_test::DisableSystemServices(browser()->profile());
  AutofillProfile profile;
  autofill_test::SetProfileInfo(
                                &profile,
                                "Milton",
                                "C.",
                                "Waddams",
                                "red.swingline@initech.com",
                                "Initech",
                                "4120 Freidrich Lane",
                                "Basement",
                                "Austin",
                                "Texas",
                                "78744",
                                "United States",
                                "5125551234");

  PersonalDataManager* personal_data_manager =
      browser()->profile()->GetPersonalDataManager();
  ASSERT_TRUE(personal_data_manager);

  personal_data_manager->AddProfile(profile);

  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(url.c_str(), true);
}
<commit_msg>Disable crashing WebUIBidiCheckerBrowserTestFakeBidi.TestNewTabPageRTL<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/bidi_checker_web_ui_test.h"

#include "base/base_paths.h"
#include "base/i18n/rtl.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/autofill/autofill_common_test.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/personal_data_manager.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_POSIX) && defined(TOOLKIT_USES_GTK)
#include <gtk/gtk.h>
#endif

// These tests are failing on linux views build. crbug.com/96891
#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
#define MAYBE_TestCrashesPageRTL DISABLED_TestCrashesPageRTL
#define MAYBE_TestDownloadsPageRTL DISABLED_TestDownloadsPageRTL
#define MAYBE_TestMainHistoryPageRTL DISABLED_TestMainHistoryPageRTL
#define MAYBE_TestNewTabPageRTL DISABLED_TestNewTabPageRTL
#define MAYBE_TestPluginsPageRTL DISABLED_TestPluginsPageRTL
#define MAYBE_TestSettingsAutofillPageRTL DISABLED_TestSettingsAutofillPageRTL
#define MAYBE_TestSettingsPageRTL DISABLED_TestSettingsPageRTL
#else
#define MAYBE_TestCrashesPageRTL TestCrashesPageRTL
#define MAYBE_TestDownloadsPageRTL TestDownloadsPageRTL
#define MAYBE_TestMainHistoryPageRTL TestMainHistoryPageRTL
#define MAYBE_TestNewTabPageRTL TestNewTabPageRTL
#define MAYBE_TestPluginsPageRTL TestPluginsPageRTL
#define MAYBE_TestSettingsAutofillPageRTL TestSettingsAutofillPageRTL
#define MAYBE_TestSettingsPageRTL TestSettingsPageRTL
#endif

// Disabled, http://crbug.com/97453
#define MAYBE_TestNewTabPageRTL DISABLED_TestNewTabPageRTL

static const FilePath::CharType* kWebUIBidiCheckerLibraryJS =
    FILE_PATH_LITERAL("third_party/bidichecker/bidichecker_packaged.js");

namespace {
FilePath WebUIBidiCheckerLibraryJSPath() {
  FilePath src_root;
  if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_root))
    LOG(ERROR) << "Couldn't find source root";
  return src_root.Append(kWebUIBidiCheckerLibraryJS);
}
}

static const FilePath::CharType* kBidiCheckerTestsJS =
    FILE_PATH_LITERAL("bidichecker_tests.js");

WebUIBidiCheckerBrowserTest::~WebUIBidiCheckerBrowserTest() {}

WebUIBidiCheckerBrowserTest::WebUIBidiCheckerBrowserTest() {}

void WebUIBidiCheckerBrowserTest::SetUpInProcessBrowserTestFixture() {
  WebUIBrowserTest::SetUpInProcessBrowserTestFixture();
  WebUIBrowserTest::AddLibrary(WebUIBidiCheckerLibraryJSPath());
  WebUIBrowserTest::AddLibrary(FilePath(kBidiCheckerTestsJS));
}

void WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(const char pageURL[],
                                                       bool isRTL) {
  ui_test_utils::NavigateToURL(browser(), GURL(pageURL));
  ASSERT_TRUE(RunJavascriptTest("runBidiChecker",
                                Value::CreateStringValue(pageURL),
                                Value::CreateBooleanValue(isRTL)));
}

// WebUIBidiCheckerBrowserTestFakeBidi

WebUIBidiCheckerBrowserTestFakeBidi::~WebUIBidiCheckerBrowserTestFakeBidi() {}

WebUIBidiCheckerBrowserTestFakeBidi::WebUIBidiCheckerBrowserTestFakeBidi() {}

void WebUIBidiCheckerBrowserTestFakeBidi::SetUpOnMainThread() {
  WebUIBidiCheckerBrowserTest::SetUpOnMainThread();
  FilePath pak_path;
  app_locale_ = base::i18n::GetConfiguredLocale();
  ASSERT_TRUE(PathService::Get(base::FILE_MODULE, &pak_path));
  pak_path = pak_path.DirName();
  pak_path = pak_path.AppendASCII("pseudo_locales");
  pak_path = pak_path.AppendASCII("fake-bidi");
  pak_path = pak_path.ReplaceExtension(FILE_PATH_LITERAL("pak"));
  ResourceBundle::GetSharedInstance().OverrideLocalePakForTest(pak_path);
  ResourceBundle::ReloadSharedInstance("he");
#if defined(OS_POSIX) && defined(TOOLKIT_USES_GTK)
  gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
#endif
}

void WebUIBidiCheckerBrowserTestFakeBidi::CleanUpOnMainThread() {
  WebUIBidiCheckerBrowserTest::CleanUpOnMainThread();
#if defined(OS_POSIX) && defined(TOOLKIT_USES_GTK)
  gtk_widget_set_default_direction(GTK_TEXT_DIR_LTR);
#endif
  ResourceBundle::GetSharedInstance().OverrideLocalePakForTest(FilePath());
  ResourceBundle::ReloadSharedInstance(app_locale_);
}

// Tests

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestMainHistoryPageLTR) {
  HistoryService* history_service =
      browser()->profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
  GURL history_url = GURL("http://www.ynet.co.il");
  history_service->AddPage(history_url, history::SOURCE_BROWSED);
  string16 title;
  ASSERT_TRUE(UTF8ToUTF16("\xD7\x91\xD7\x93\xD7\x99\xD7\xA7\xD7\x94\x21",
                          12,
                          &title));
  history_service->SetPageTitle(history_url, title);
  RunBidiCheckerOnPage(chrome::kChromeUIHistoryURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestMainHistoryPageRTL) {
  HistoryService* history_service =
      browser()->profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
  GURL history_url = GURL("http://www.google.com");
  history_service->AddPage(history_url, history::SOURCE_BROWSED);
  string16 title = UTF8ToUTF16("Google");
  history_service->SetPageTitle(history_url, title);
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUIHistoryURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestAboutPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIAboutURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestBugReportPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIBugReportURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestCrashesPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUICrashesURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestCrashesPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUICrashesURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestDownloadsPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIDownloadsURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestDownloadsPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(
      chrome::kChromeUIDownloadsURL, true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestNewTabPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUINewTabURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestNewTabPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUINewTabURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestPluginsPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUIPluginsURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestPluginsPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(chrome::kChromeUIPluginsURL,
                                                    true);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest, TestSettingsPageLTR) {
  RunBidiCheckerOnPage(chrome::kChromeUISettingsURL, false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestSettingsPageRTL) {
  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(
      chrome::kChromeUISettingsURL, true);
}

#if defined(OS_MACOSX)
// http://crbug.com/94642
#define MAYBE_TestSettingsAutofillPageLTR FLAKY_TestSettingsAutofillPageLTR
#elif defined(OS_WIN)
// http://crbug.com/95425
#define MAYBE_TestSettingsAutofillPageLTR FAILS_TestSettingsAutofillPageLTR
#else
#define MAYBE_TestSettingsAutofillPageLTR TestSettingsAutofillPageLTR
#endif  // defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTest,
                       MAYBE_TestSettingsAutofillPageLTR) {
  std::string url(chrome::kChromeUISettingsURL);
  url += std::string(chrome::kAutofillSubPage);

  autofill_test::DisableSystemServices(browser()->profile());
  AutofillProfile profile;
  autofill_test::SetProfileInfo(
      &profile,
      "\xD7\x9E\xD7\xA9\xD7\x94",
      "\xD7\x91",
      "\xD7\x9B\xD7\x94\xD7\x9F",
      "moshe.b.cohen@biditest.com",
      "\xD7\x91\xD7\x93\xD7\x99\xD7\xA7\xD7\x94\x20\xD7\x91\xD7\xA2\xD7\x9E",
      "\xD7\x93\xD7\xA8\xD7\x9A\x20\xD7\x9E\xD7\xA0\xD7\x97\xD7\x9D\x20\xD7\x91\xD7\x92\xD7\x99\xD7\x9F\x20\x32\x33",
      "\xD7\xA7\xD7\x95\xD7\x9E\xD7\x94\x20\x32\x36",
      "\xD7\xAA\xD7\x9C\x20\xD7\x90\xD7\x91\xD7\x99\xD7\x91",
      "",
      "66183",
      "\xD7\x99\xD7\xA9\xD7\xA8\xD7\x90\xD7\x9C",
      "0000");

  PersonalDataManager* personal_data_manager =
    browser()->profile()->GetPersonalDataManager();
  ASSERT_TRUE(personal_data_manager);

  personal_data_manager->AddProfile(profile);

  RunBidiCheckerOnPage(url.c_str(), false);
}

IN_PROC_BROWSER_TEST_F(WebUIBidiCheckerBrowserTestFakeBidi,
                       MAYBE_TestSettingsAutofillPageRTL) {
  std::string url(chrome::kChromeUISettingsURL);
  url += std::string(chrome::kAutofillSubPage);

  autofill_test::DisableSystemServices(browser()->profile());
  AutofillProfile profile;
  autofill_test::SetProfileInfo(
                                &profile,
                                "Milton",
                                "C.",
                                "Waddams",
                                "red.swingline@initech.com",
                                "Initech",
                                "4120 Freidrich Lane",
                                "Basement",
                                "Austin",
                                "Texas",
                                "78744",
                                "United States",
                                "5125551234");

  PersonalDataManager* personal_data_manager =
      browser()->profile()->GetPersonalDataManager();
  ASSERT_TRUE(personal_data_manager);

  personal_data_manager->AddProfile(profile);

  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(url.c_str(), true);
}
<|endoftext|>


<commit_before>#include "LayeredWnd.h"

#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
#include <VersionHelpers.h>

#include "..\Error.h"

LayeredWnd::LayeredWnd(LPCWSTR className, LPCWSTR title, HINSTANCE hInstance,
    Gdiplus::Bitmap *bitmap, DWORD exStyles) :
_className(className),
_hInstance(hInstance),
_title(title),
_transparency(255),
_visible(false) {

    if (_hInstance == NULL) {
        _hInstance = (HINSTANCE) GetModuleHandle(NULL);
    }

    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = 0;
    wcex.lpfnWndProc = &LayeredWnd::StaticWndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = _hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = _className;
    wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wcex)) {
        throw SYSERR_REGISTERCLASS;
    }

    DWORD styles = WS_EX_LAYERED | exStyles;

    _hWnd = CreateWindowEx(
        styles,
        _className, _title,
        WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
        _size.cx, _size.cy,
        NULL, NULL, _hInstance, this);

    if (_hWnd == NULL) {
        throw SYSERR_CREATEWINDOW;
    }

    Bitmap(bitmap);
}

LayeredWnd::~LayeredWnd() {
    DestroyWindow(_hWnd);
    UnregisterClass(_className, _hInstance);
}

void LayeredWnd::UpdateWindow(RECT *dirtyRect) {
    BLENDFUNCTION bFunc;
    bFunc.AlphaFormat = AC_SRC_ALPHA;
    bFunc.BlendFlags = 0;
    bFunc.BlendOp = AC_SRC_OVER;
    bFunc.SourceConstantAlpha = _transparency;

    HDC screenDc = GetDC(GetDesktopWindow());
    HDC sourceDc = CreateCompatibleDC(screenDc);

    HBITMAP hBmp;
    _bitmap->GetHBITMAP(Gdiplus::Color(0, 0, 0, 0), &hBmp);
    HGDIOBJ hReplaced = SelectObject(sourceDc, hBmp);

    POINT pt = { 0, 0 };
    SIZE size = { _bitmap->GetWidth(), _bitmap->GetHeight() };

    UPDATELAYEREDWINDOWINFO lwInfo;
    lwInfo.cbSize = sizeof(UPDATELAYEREDWINDOWINFO);
    lwInfo.crKey = 0;
    lwInfo.dwFlags = ULW_ALPHA;
    lwInfo.hdcDst = screenDc;
    lwInfo.hdcSrc = sourceDc;
    lwInfo.pblend = &bFunc;
    lwInfo.pptDst = &_location;
    lwInfo.pptSrc = &pt;
    lwInfo.prcDirty = dirtyRect;
    lwInfo.psize = &size;

    UpdateLayeredWindowIndirect(_hWnd, &lwInfo);

    SelectObject(sourceDc, hReplaced);
    DeleteDC(sourceDc);
    DeleteObject(hBmp);
    ReleaseDC(GetDesktopWindow(), screenDc);
}

void LayeredWnd::UpdateTransparency() {
    BLENDFUNCTION bFunc;
    bFunc.AlphaFormat = AC_SRC_ALPHA;
    bFunc.BlendFlags = 0;
    bFunc.BlendOp = AC_SRC_OVER;
    bFunc.SourceConstantAlpha = _transparency;

    UPDATELAYEREDWINDOWINFO lwInfo;
    lwInfo.cbSize = sizeof(UPDATELAYEREDWINDOWINFO);
    lwInfo.crKey = 0;
    lwInfo.dwFlags = ULW_ALPHA;
    lwInfo.hdcDst = NULL;
    lwInfo.hdcSrc = NULL;
    lwInfo.pblend = &bFunc;
    lwInfo.pptDst = NULL;
    lwInfo.pptSrc = NULL;
    lwInfo.prcDirty = NULL;
    lwInfo.psize = NULL;

    UpdateLayeredWindowIndirect(_hWnd, &lwInfo);
}

bool LayeredWnd::EnableGlass(Gdiplus::Bitmap *mask) {
    if (mask == NULL) {
        return false;
    }

    /* Disable for Windows 8+ */
    if (IsWindows8OrGreater()) {
        return false;
    }

    /* Disable for Windows XP */
    if (IsWindowsXPOrGreater() == true && IsWindowsVistaOrGreater() == false) {
        return false;
    }

    _glassMask = mask;

    using namespace Gdiplus;
    ARGB searchArgb = 0xFF000000;

    unsigned int height = _glassMask->GetHeight();
    unsigned int width = _glassMask->GetWidth();

    Region glassRegion;
    glassRegion.MakeEmpty();
    bool match = false;

    /* One row of pixels is scanned at a time, so the height is 1. */
    Rect rec(0, 0, 0, 1);

    for (unsigned int y = 0; y < height; ++y) {
        for (unsigned int x = 0; x < width; ++x) {
            Color pixelColor;
            _glassMask->GetPixel(x, y, &pixelColor);
            ARGB pixelArgb = pixelColor.GetValue();

            if (searchArgb == pixelArgb && (x + 1 != width)) {
                if (match) {
                    continue;
                }

                match = true;
                rec.X = x;
                rec.Y = y;
            } else if (match) {
                /* Reached the end of a matching line */
                match = false;
                rec.Width = x - rec.X;
                glassRegion.Union(rec);
            }
        }
    }

    DWM_BLURBEHIND blurBehind = { 0 };
    blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
    blurBehind.fEnable = TRUE;

    Graphics g(_glassMask);
    blurBehind.hRgnBlur = glassRegion.GetHRGN(&g);

    HRESULT hr = DwmEnableBlurBehindWindow(_hWnd, &blurBehind);
    return SUCCEEDED(hr);
}

bool LayeredWnd::DisableGlass() {
    DWM_BLURBEHIND blurBehind = { 0 };
    blurBehind.dwFlags = DWM_BB_ENABLE;
    blurBehind.fEnable = FALSE;
    HRESULT hr = DwmEnableBlurBehindWindow(_hWnd, &blurBehind);
    return SUCCEEDED(hr);
}

void LayeredWnd::UpdateWindowPosition() {
    MoveWindow(_hWnd, _location.x, _location.y, _size.cx, _size.cy, FALSE);
}

void LayeredWnd::Show() {
    if (_visible == true) {
        return;
    }

    UpdateWindow();
    ShowWindow(_hWnd, SW_SHOW);
    _visible = true;
}

void LayeredWnd::Hide() {
    if (_visible == false) {
        return;
    }

    ShowWindow(_hWnd, SW_HIDE);
    _visible = false;
}

Gdiplus::Bitmap *LayeredWnd::Bitmap() {
    return _bitmap;
}

void LayeredWnd::Bitmap(Gdiplus::Bitmap *bitmap) {
    if (bitmap == NULL) {
        return;
    }

    _bitmap = bitmap;
    _size.cx = bitmap->GetWidth();
    _size.cy = bitmap->GetHeight();
    UpdateWindow();
}

byte LayeredWnd::Transparency() {
    return _transparency;
}

void LayeredWnd::Transparency(byte transparency) {
    _transparency = transparency;
    UpdateTransparency();
}

int LayeredWnd::X() {
    return _location.x;
}

void LayeredWnd::X(int x) {
    _location.x = x;
}

int LayeredWnd::Y() {
    return _location.y;
}

void LayeredWnd::Y(int y) {
    _location.y = y;
}

int LayeredWnd::Width() {
    return _size.cx;
}

int LayeredWnd::Height() {
    return _size.cy;
}

POINT LayeredWnd::Position() {
    return _location;
}

void LayeredWnd::Position(int x, int y) {
    _location.x = x;
    _location.y = y;
    UpdateWindowPosition();
}

LRESULT CALLBACK
LayeredWnd::StaticWndProc(
        HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    LayeredWnd* wnd;

    if (message == WM_CREATE) {
        wnd = (LayeredWnd *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) wnd);
    } else {
        wnd = (LayeredWnd *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
        if (!wnd) {
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }

    return wnd->WndProc(message, wParam, lParam);
}

LRESULT LayeredWnd::WndProc(UINT message, WPARAM wParam, LPARAM lParam) {
    if (_glassMask && message == WM_DWMCOMPOSITIONCHANGED) {
        BOOL compositionEnabled = FALSE;
        DwmIsCompositionEnabled(&compositionEnabled);

        if (compositionEnabled) {
            EnableGlass(_glassMask);
        } else {
            DisableGlass();
        }
    }

    return DefWindowProc(_hWnd, message, wParam, lParam);
}<commit_msg>Check HRESULT<commit_after>#include "LayeredWnd.h"

#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
#include <VersionHelpers.h>

#include "..\Error.h"

LayeredWnd::LayeredWnd(LPCWSTR className, LPCWSTR title, HINSTANCE hInstance,
    Gdiplus::Bitmap *bitmap, DWORD exStyles) :
_className(className),
_hInstance(hInstance),
_title(title),
_transparency(255),
_visible(false) {

    if (_hInstance == NULL) {
        _hInstance = (HINSTANCE) GetModuleHandle(NULL);
    }

    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = 0;
    wcex.lpfnWndProc = &LayeredWnd::StaticWndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = _hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = _className;
    wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wcex)) {
        throw SYSERR_REGISTERCLASS;
    }

    DWORD styles = WS_EX_LAYERED | exStyles;

    _hWnd = CreateWindowEx(
        styles,
        _className, _title,
        WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
        _size.cx, _size.cy,
        NULL, NULL, _hInstance, this);

    if (_hWnd == NULL) {
        throw SYSERR_CREATEWINDOW;
    }

    Bitmap(bitmap);
}

LayeredWnd::~LayeredWnd() {
    DestroyWindow(_hWnd);
    UnregisterClass(_className, _hInstance);
}

void LayeredWnd::UpdateWindow(RECT *dirtyRect) {
    BLENDFUNCTION bFunc;
    bFunc.AlphaFormat = AC_SRC_ALPHA;
    bFunc.BlendFlags = 0;
    bFunc.BlendOp = AC_SRC_OVER;
    bFunc.SourceConstantAlpha = _transparency;

    HDC screenDc = GetDC(GetDesktopWindow());
    HDC sourceDc = CreateCompatibleDC(screenDc);

    HBITMAP hBmp;
    _bitmap->GetHBITMAP(Gdiplus::Color(0, 0, 0, 0), &hBmp);
    HGDIOBJ hReplaced = SelectObject(sourceDc, hBmp);

    POINT pt = { 0, 0 };
    SIZE size = { _bitmap->GetWidth(), _bitmap->GetHeight() };

    UPDATELAYEREDWINDOWINFO lwInfo;
    lwInfo.cbSize = sizeof(UPDATELAYEREDWINDOWINFO);
    lwInfo.crKey = 0;
    lwInfo.dwFlags = ULW_ALPHA;
    lwInfo.hdcDst = screenDc;
    lwInfo.hdcSrc = sourceDc;
    lwInfo.pblend = &bFunc;
    lwInfo.pptDst = &_location;
    lwInfo.pptSrc = &pt;
    lwInfo.prcDirty = dirtyRect;
    lwInfo.psize = &size;

    UpdateLayeredWindowIndirect(_hWnd, &lwInfo);

    SelectObject(sourceDc, hReplaced);
    DeleteDC(sourceDc);
    DeleteObject(hBmp);
    ReleaseDC(GetDesktopWindow(), screenDc);
}

void LayeredWnd::UpdateTransparency() {
    BLENDFUNCTION bFunc;
    bFunc.AlphaFormat = AC_SRC_ALPHA;
    bFunc.BlendFlags = 0;
    bFunc.BlendOp = AC_SRC_OVER;
    bFunc.SourceConstantAlpha = _transparency;

    UPDATELAYEREDWINDOWINFO lwInfo;
    lwInfo.cbSize = sizeof(UPDATELAYEREDWINDOWINFO);
    lwInfo.crKey = 0;
    lwInfo.dwFlags = ULW_ALPHA;
    lwInfo.hdcDst = NULL;
    lwInfo.hdcSrc = NULL;
    lwInfo.pblend = &bFunc;
    lwInfo.pptDst = NULL;
    lwInfo.pptSrc = NULL;
    lwInfo.prcDirty = NULL;
    lwInfo.psize = NULL;

    UpdateLayeredWindowIndirect(_hWnd, &lwInfo);
}

bool LayeredWnd::EnableGlass(Gdiplus::Bitmap *mask) {
    if (mask == NULL) {
        return false;
    }

    /* Disable for Windows 8+ */
    if (IsWindows8OrGreater()) {
        return false;
    }

    /* Disable for Windows XP */
    if (IsWindowsXPOrGreater() == true && IsWindowsVistaOrGreater() == false) {
        return false;
    }

    _glassMask = mask;

    using namespace Gdiplus;
    ARGB searchArgb = 0xFF000000;

    unsigned int height = _glassMask->GetHeight();
    unsigned int width = _glassMask->GetWidth();

    Region glassRegion;
    glassRegion.MakeEmpty();
    bool match = false;

    /* One row of pixels is scanned at a time, so the height is 1. */
    Rect rec(0, 0, 0, 1);

    for (unsigned int y = 0; y < height; ++y) {
        for (unsigned int x = 0; x < width; ++x) {
            Color pixelColor;
            _glassMask->GetPixel(x, y, &pixelColor);
            ARGB pixelArgb = pixelColor.GetValue();

            if (searchArgb == pixelArgb && (x + 1 != width)) {
                if (match) {
                    continue;
                }

                match = true;
                rec.X = x;
                rec.Y = y;
            } else if (match) {
                /* Reached the end of a matching line */
                match = false;
                rec.Width = x - rec.X;
                glassRegion.Union(rec);
            }
        }
    }

    DWM_BLURBEHIND blurBehind = { 0 };
    blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
    blurBehind.fEnable = TRUE;

    Graphics g(_glassMask);
    blurBehind.hRgnBlur = glassRegion.GetHRGN(&g);

    HRESULT hr = DwmEnableBlurBehindWindow(_hWnd, &blurBehind);
    return SUCCEEDED(hr);
}

bool LayeredWnd::DisableGlass() {
    DWM_BLURBEHIND blurBehind = { 0 };
    blurBehind.dwFlags = DWM_BB_ENABLE;
    blurBehind.fEnable = FALSE;
    HRESULT hr = DwmEnableBlurBehindWindow(_hWnd, &blurBehind);
    return SUCCEEDED(hr);
}

void LayeredWnd::UpdateWindowPosition() {
    MoveWindow(_hWnd, _location.x, _location.y, _size.cx, _size.cy, FALSE);
}

void LayeredWnd::Show() {
    if (_visible == true) {
        return;
    }

    UpdateWindow();
    ShowWindow(_hWnd, SW_SHOW);
    _visible = true;
}

void LayeredWnd::Hide() {
    if (_visible == false) {
        return;
    }

    ShowWindow(_hWnd, SW_HIDE);
    _visible = false;
}

Gdiplus::Bitmap *LayeredWnd::Bitmap() {
    return _bitmap;
}

void LayeredWnd::Bitmap(Gdiplus::Bitmap *bitmap) {
    if (bitmap == NULL) {
        return;
    }

    _bitmap = bitmap;
    _size.cx = bitmap->GetWidth();
    _size.cy = bitmap->GetHeight();
    UpdateWindow();
}

byte LayeredWnd::Transparency() {
    return _transparency;
}

void LayeredWnd::Transparency(byte transparency) {
    _transparency = transparency;
    UpdateTransparency();
}

int LayeredWnd::X() {
    return _location.x;
}

void LayeredWnd::X(int x) {
    _location.x = x;
}

int LayeredWnd::Y() {
    return _location.y;
}

void LayeredWnd::Y(int y) {
    _location.y = y;
}

int LayeredWnd::Width() {
    return _size.cx;
}

int LayeredWnd::Height() {
    return _size.cy;
}

POINT LayeredWnd::Position() {
    return _location;
}

void LayeredWnd::Position(int x, int y) {
    _location.x = x;
    _location.y = y;
    UpdateWindowPosition();
}

LRESULT CALLBACK
LayeredWnd::StaticWndProc(
        HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    LayeredWnd* wnd;

    if (message == WM_CREATE) {
        wnd = (LayeredWnd *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) wnd);
    } else {
        wnd = (LayeredWnd *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
        if (!wnd) {
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }

    return wnd->WndProc(message, wParam, lParam);
}

LRESULT LayeredWnd::WndProc(UINT message, WPARAM wParam, LPARAM lParam) {
    if (_glassMask && message == WM_DWMCOMPOSITIONCHANGED) {
        BOOL compositionEnabled = FALSE;
        HRESULT hr = DwmIsCompositionEnabled(&compositionEnabled);

        if (SUCCEEDED(hr)) {
            if (compositionEnabled) {
                EnableGlass(_glassMask);
            } else {
                DisableGlass();
            }
        }
    }

    return DefWindowProc(_hWnd, message, wParam, lParam);
}<|endoftext|>


<commit_before>/*

    TSIframework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Carles F. Julià <carles.fernandez@upf.edu>

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef SINGLETON_H
#define SINGLETON_H
//Inspired by http://cc.byexamples.com/20080609/stl-singleton-template/

template<typename T>
class Singleton
{
    public:
        static T& Instance()
        {
            static T me;
            return me;
        }
        static T* get()
        {
            return &Instance();
        }
};

#endif //SINGLETON_H
<commit_msg>Extending Singleton Template to admit Base Classes<commit_after>/*

    TSIframework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Carles F. Julià <carles.fernandez@upf.edu>

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef SINGLETON_H
#define SINGLETON_H
//Inspired by http://cc.byexamples.com/20080609/stl-singleton-template/
class VoidClass{};
template<typename T, class Base=VoidClass>
class Singleton : public Base
{
    public:
        static T& Instance()
        {
            static T me;
            return me;
        }
        static T* get()
        {
            return &Instance();
        }
};

#endif //SINGLETON_H
<|endoftext|>