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

#include "chrome_frame/test/net/fake_external_tab.h"

#include <exdisp.h>

#include "app/app_paths.h"
#include "app/resource_bundle.h"
#include "app/win_util.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/i18n/icu_util.h"
#include "base/path_service.h"
#include "base/scoped_bstr_win.h"
#include "base/scoped_comptr_win.h"
#include "base/scoped_variant_win.h"

#include "chrome/browser/browser_prefs.h"
#include "chrome/browser/process_singleton.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/browser/renderer_host/render_process_host.h"

#include "chrome_frame/utils.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test/net/dialog_watchdog.h"
#include "chrome_frame/test/net/test_automation_resource_message_filter.h"

namespace {

// A special command line switch to allow developers to manually launch the
// browser and debug CF inside the browser.
const wchar_t kManualBrowserLaunch[] = L"manual-browser";

// Pops up a message box after the test environment has been set up
// and before tearing it down.  Useful for when debugging tests and not
// the test environment that's been set up.
const wchar_t kPromptAfterSetup[] = L"prompt-after-setup";

const int kTestServerPort = 4666;
// The test HTML we use to initialize Chrome Frame.
// Note that there's a little trick in there to avoid an extra URL request
// that the browser will otherwise make for the site's favicon.
// If we don't do this the browser will create a new URL request after
// the CF page has been initialized and that URL request will confuse the
// global URL instance counter in the unit tests and subsequently trip
// some DCHECKs.
const char kChromeFrameHtml[] = ""
    "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />"
    "<link rel=\"shortcut icon\" href=\"file://c:\\favicon.ico\"/>"
    "Chrome Frame should now be loaded";

bool ShouldLaunchBrowser() {
  return !CommandLine::ForCurrentProcess()->HasSwitch(kManualBrowserLaunch);
}

bool PromptAfterSetup() {
  return CommandLine::ForCurrentProcess()->HasSwitch(kPromptAfterSetup);
}

}  // end namespace

FakeExternalTab::FakeExternalTab() {
  PathService::Get(chrome::DIR_USER_DATA, &overridden_user_dir_);
  user_data_dir_ = FilePath::FromWStringHack(GetProfilePath());
  PathService::Override(chrome::DIR_USER_DATA, user_data_dir_);
  process_singleton_.reset(new ProcessSingleton(user_data_dir_));
}

FakeExternalTab::~FakeExternalTab() {
  if (!overridden_user_dir_.empty()) {
    PathService::Override(chrome::DIR_USER_DATA, overridden_user_dir_);
  }
}

std::wstring FakeExternalTab::GetProfileName() {
  return L"iexplore";
}

std::wstring FakeExternalTab::GetProfilePath() {
  std::wstring path;
  GetUserProfileBaseDirectory(&path);
  file_util::AppendToPath(&path, GetProfileName());
  return path;
}

void FakeExternalTab::Initialize() {
  DCHECK(g_browser_process == NULL);

  // The gears plugin causes the PluginRequestInterceptor to kick in and it
  // will cause problems when it tries to intercept URL requests.
  PathService::Override(chrome::FILE_GEARS_PLUGIN, FilePath());

  icu_util::Initialize();

  chrome::RegisterPathProvider();
  app::RegisterPathProvider();

  ResourceBundle::InitSharedInstance(L"en-US");
  ResourceBundle::GetSharedInstance().LoadThemeResources();

  const CommandLine* cmd = CommandLine::ForCurrentProcess();
  browser_process_.reset(new BrowserProcessImpl(*cmd));
  RenderProcessHost::set_run_renderer_in_process(true);
  // BrowserProcessImpl's constructor should set g_browser_process.
  DCHECK(g_browser_process);

  Profile* profile = g_browser_process->profile_manager()->
      GetDefaultProfile(FilePath(user_data()));
  PrefService* prefs = profile->GetPrefs();
  PrefService* local_state = browser_process_->local_state();
  local_state->RegisterStringPref(prefs::kApplicationLocale, L"");
  local_state->RegisterBooleanPref(prefs::kMetricsReportingEnabled, false);

  browser::RegisterAllPrefs(prefs, local_state);

  // Override some settings to avoid hitting some preferences that have not
  // been registered.
  prefs->SetBoolean(prefs::kPasswordManagerEnabled, false);
  prefs->SetBoolean(prefs::kAlternateErrorPagesEnabled, false);
  prefs->SetBoolean(prefs::kSafeBrowsingEnabled, false);

  profile->InitExtensions();
}

void FakeExternalTab::Shutdown() {
  browser_process_.reset();
  g_browser_process = NULL;
  process_singleton_.reset();

  ResourceBundle::CleanupSharedInstance();
}

CFUrlRequestUnittestRunner::CFUrlRequestUnittestRunner(int argc, char** argv)
    : NetTestSuite(argc, argv),
      chrome_frame_html_("/chrome_frame", kChromeFrameHtml) {
  fake_chrome_.Initialize();
  pss_subclass_.reset(new ProcessSingletonSubclass(this));
  EXPECT_TRUE(pss_subclass_->Subclass(fake_chrome_.user_data()));
  StartChromeFrameInHostBrowser();
  // Register the main thread by instantiating it, but don't call any methods.
  main_thread_.reset(new ChromeThread());
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
}

CFUrlRequestUnittestRunner::~CFUrlRequestUnittestRunner() {
  fake_chrome_.Shutdown();
}

DWORD WINAPI NavigateIE(void* param) {
  return 0;
  win_util::ScopedCOMInitializer com;
  BSTR url = reinterpret_cast<BSTR>(param);

  bool found = false;
  int retries = 0;
  const int kMaxRetries = 20;
  while (!found && retries < kMaxRetries) {
    ScopedComPtr<IShellWindows> windows;
    HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL,
        IID_IShellWindows, reinterpret_cast<void**>(windows.Receive()));
    DCHECK(SUCCEEDED(hr)) << "CoCreateInstance";

    if (SUCCEEDED(hr)) {
      hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
      long count = 0;  // NOLINT
      windows->get_Count(&count);
      VARIANT i = { VT_I4 };
      for (i.lVal = 0; i.lVal < count; ++i.lVal) {
        ScopedComPtr<IDispatch> folder;
        windows->Item(i, folder.Receive());
        if (folder != NULL) {
          ScopedComPtr<IWebBrowser2> browser;
          if (SUCCEEDED(browser.QueryFrom(folder))) {
            found = true;
            browser->Stop();
            Sleep(1000);
            VARIANT empty = ScopedVariant::kEmptyVariant;
            hr = browser->Navigate(url, &empty, &empty, &empty, &empty);
            DCHECK(SUCCEEDED(hr)) << "Failed to navigate";
            break;
          }
        }
      }
    }
    if (!found) {
      DLOG(INFO) << "Waiting for browser to initialize...";
      ::Sleep(100);
      retries++;
    }
  }

  DCHECK(retries < kMaxRetries);
  DCHECK(found);

  ::SysFreeString(url);

  return 0;
}

void CFUrlRequestUnittestRunner::StartChromeFrameInHostBrowser() {
  if (!ShouldLaunchBrowser())
    return;

  win_util::ScopedCOMInitializer com;
  chrome_frame_test::CloseAllIEWindows();

  test_http_server_.reset(new test_server::SimpleWebServer(kTestServerPort));
  test_http_server_->AddResponse(&chrome_frame_html_);
  std::wstring url(StringPrintf(L"http://localhost:%i/chrome_frame",
                                kTestServerPort).c_str());

  // Launch IE.  This launches IE correctly on Vista too.
  ScopedHandle ie_process(chrome_frame_test::LaunchIE(url));
  EXPECT_TRUE(ie_process.IsValid());

  // NOTE: If you're running IE8 and CF is not being loaded, you need to
  // disable IE8's prebinding until CF properly handles that situation.
  //
  // HKCU\Software\Microsoft\Internet Explorer\Main
  // Value name: EnablePreBinding (REG_DWORD)
  // Value: 0
}

void CFUrlRequestUnittestRunner::ShutDownHostBrowser() {
  if (ShouldLaunchBrowser()) {
    win_util::ScopedCOMInitializer com;
    chrome_frame_test::CloseAllIEWindows();
  }
}

// Override virtual void Initialize to not call icu initialize
void CFUrlRequestUnittestRunner::Initialize() {
  DCHECK(::GetCurrentThreadId() == test_thread_id_);

  // Start by replicating some of the steps that would otherwise be
  // done by TestSuite::Initialize.  We can't call the base class
  // directly because it will attempt to initialize some things such as
  // ICU that have already been initialized for this process.
  InitializeLogging();
  base::Time::EnableHiResClockForTests();

#if !defined(PURIFY) && defined(OS_WIN)
  logging::SetLogAssertHandler(UnitTestAssertHandler);
#endif  // !defined(PURIFY)

  // Next, do some initialization for NetTestSuite.
  NetTestSuite::InitializeTestThread();
}

void CFUrlRequestUnittestRunner::Shutdown() {
  DCHECK(::GetCurrentThreadId() == test_thread_id_);
  NetTestSuite::Shutdown();
}

void CFUrlRequestUnittestRunner::OnConnectAutomationProviderToChannel(
    const std::string& channel_id) {
  Profile* profile = g_browser_process->profile_manager()->
      GetDefaultProfile(fake_chrome_.user_data());

  AutomationProviderList* list =
      g_browser_process->InitAutomationProviderList();
  DCHECK(list);
  list->AddProvider(TestAutomationProvider::NewAutomationProvider(profile,
      channel_id, this));
}

void CFUrlRequestUnittestRunner::OnInitialTabLoaded() {
  test_http_server_.reset();
  StartTests();
}

void CFUrlRequestUnittestRunner::RunMainUIThread() {
  DCHECK(MessageLoop::current());
  DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
  MessageLoop::current()->Run();
}

void CFUrlRequestUnittestRunner::StartTests() {
  if (PromptAfterSetup())
    MessageBoxA(NULL, "click ok to run", "", MB_OK);

  DCHECK_EQ(test_thread_.IsValid(), false);
  test_thread_.Set(::CreateThread(NULL, 0, RunAllUnittests, this, 0,
                                  &test_thread_id_));
  DCHECK(test_thread_.IsValid());
}

// static
DWORD CFUrlRequestUnittestRunner::RunAllUnittests(void* param) {
  PlatformThread::SetName("CFUrlRequestUnittestRunner");
  CFUrlRequestUnittestRunner* me =
      reinterpret_cast<CFUrlRequestUnittestRunner*>(param);
  me->Run();
  me->fake_chrome_.ui_loop()->PostTask(FROM_HERE,
      NewRunnableFunction(TakeDownBrowser, me));
  return 0;
}

// static
void CFUrlRequestUnittestRunner::TakeDownBrowser(
    CFUrlRequestUnittestRunner* me) {
  if (PromptAfterSetup())
    MessageBoxA(NULL, "click ok to exit", "", MB_OK);

  me->ShutDownHostBrowser();
}

void CFUrlRequestUnittestRunner::InitializeLogging() {
  FilePath exe;
  PathService::Get(base::FILE_EXE, &exe);
  FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
  logging::InitLogging(log_filename.value().c_str(),
                       logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
                       logging::LOCK_LOG_FILE,
                       logging::DELETE_OLD_LOG_FILE);
  // We want process and thread IDs because we may have multiple processes.
  // Note: temporarily enabled timestamps in an effort to catch bug 6361.
  logging::SetLogItems(true, true, true, true);
}

void FilterDisabledTests() {
  if (::testing::FLAGS_gtest_filter.length() &&
      ::testing::FLAGS_gtest_filter.Compare("*") != 0) {
    // Don't override user specified filters.
    return;
  }

  const char* disabled_tests[] = {
    // Tests disabled since they're testing the same functionality used
    // by the TestAutomationProvider.
    "URLRequestTest.InterceptNetworkError",
    "URLRequestTest.InterceptRestartRequired",
    "URLRequestTest.InterceptRespectsCancelMain",
    "URLRequestTest.InterceptRespectsCancelRedirect",
    "URLRequestTest.InterceptRespectsCancelFinal",
    "URLRequestTest.InterceptRespectsCancelInRestart",
    "URLRequestTest.InterceptRedirect",
    "URLRequestTest.InterceptServerError",
    "URLRequestTestFTP.*",

    // Tests that are currently not working:

    // Temporarily disabled because they needs user input (login dialog).
    "URLRequestTestHTTP.BasicAuth",
    "URLRequestTestHTTP.BasicAuthWithCookies",

    // HTTPS tests temporarily disabled due to the certificate error dialog.
    // TODO(tommi): The tests currently fail though, so need to fix.
    "HTTPSRequestTest.HTTPSMismatchedTest",
    "HTTPSRequestTest.HTTPSExpiredTest",

    // Tests chrome's network stack's cache (might not apply to CF).
    "URLRequestTestHTTP.VaryHeader",

    // I suspect we can only get this one to work (if at all) on IE8 and
    // later by using the new INTERNET_OPTION_SUPPRESS_BEHAVIOR flags
    // See http://msdn.microsoft.com/en-us/library/aa385328(VS.85).aspx
    "URLRequestTest.DoNotSaveCookies",
  };

  std::string filter("-");  // All following filters will be negative.
  for (int i = 0; i < arraysize(disabled_tests); ++i) {
    if (i > 0)
      filter += ":";
    filter += disabled_tests[i];
  }

  ::testing::FLAGS_gtest_filter = filter;
}

int main(int argc, char** argv) {
  DialogWatchdog watchdog;
  // See url_request_unittest.cc for these credentials.
  SupplyProxyCredentials credentials("user", "secret");
  watchdog.AddObserver(&credentials);
  testing::InitGoogleTest(&argc, argv);
  FilterDisabledTests();
  CFUrlRequestUnittestRunner test_suite(argc, argv);
  test_suite.RunMainUIThread();
  return 0;
}
<commit_msg>Fix build error.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/test/net/fake_external_tab.h"

#include <exdisp.h>

#include "app/app_paths.h"
#include "app/resource_bundle.h"
#include "app/win_util.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/i18n/icu_util.h"
#include "base/path_service.h"
#include "base/scoped_bstr_win.h"
#include "base/scoped_comptr_win.h"
#include "base/scoped_variant_win.h"

#include "chrome/browser/browser_prefs.h"
#include "chrome/browser/process_singleton.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/browser/renderer_host/render_process_host.h"

#include "chrome_frame/utils.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test/net/dialog_watchdog.h"
#include "chrome_frame/test/net/test_automation_resource_message_filter.h"

namespace {

// A special command line switch to allow developers to manually launch the
// browser and debug CF inside the browser.
const wchar_t kManualBrowserLaunch[] = L"manual-browser";

// Pops up a message box after the test environment has been set up
// and before tearing it down.  Useful for when debugging tests and not
// the test environment that's been set up.
const wchar_t kPromptAfterSetup[] = L"prompt-after-setup";

const int kTestServerPort = 4666;
// The test HTML we use to initialize Chrome Frame.
// Note that there's a little trick in there to avoid an extra URL request
// that the browser will otherwise make for the site's favicon.
// If we don't do this the browser will create a new URL request after
// the CF page has been initialized and that URL request will confuse the
// global URL instance counter in the unit tests and subsequently trip
// some DCHECKs.
const char kChromeFrameHtml[] = ""
    "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />"
    "<link rel=\"shortcut icon\" href=\"file://c:\\favicon.ico\"/>"
    "Chrome Frame should now be loaded";

bool ShouldLaunchBrowser() {
  return !CommandLine::ForCurrentProcess()->HasSwitch(kManualBrowserLaunch);
}

bool PromptAfterSetup() {
  return CommandLine::ForCurrentProcess()->HasSwitch(kPromptAfterSetup);
}

}  // end namespace

FakeExternalTab::FakeExternalTab() {
  PathService::Get(chrome::DIR_USER_DATA, &overridden_user_dir_);
  user_data_dir_ = FilePath::FromWStringHack(GetProfilePath());
  PathService::Override(chrome::DIR_USER_DATA, user_data_dir_);
  process_singleton_.reset(new ProcessSingleton(user_data_dir_));
}

FakeExternalTab::~FakeExternalTab() {
  if (!overridden_user_dir_.empty()) {
    PathService::Override(chrome::DIR_USER_DATA, overridden_user_dir_);
  }
}

std::wstring FakeExternalTab::GetProfileName() {
  return L"iexplore";
}

std::wstring FakeExternalTab::GetProfilePath() {
  std::wstring path;
  GetUserProfileBaseDirectory(&path);
  file_util::AppendToPath(&path, GetProfileName());
  return path;
}

void FakeExternalTab::Initialize() {
  DCHECK(g_browser_process == NULL);

  // The gears plugin causes the PluginRequestInterceptor to kick in and it
  // will cause problems when it tries to intercept URL requests.
  PathService::Override(chrome::FILE_GEARS_PLUGIN, FilePath());

  icu_util::Initialize();

  chrome::RegisterPathProvider();
  app::RegisterPathProvider();

  ResourceBundle::InitSharedInstance(L"en-US");
  ResourceBundle::GetSharedInstance().LoadThemeResources();

  const CommandLine* cmd = CommandLine::ForCurrentProcess();
  browser_process_.reset(new BrowserProcessImpl(*cmd));
  RenderProcessHost::set_run_renderer_in_process(true);
  // BrowserProcessImpl's constructor should set g_browser_process.
  DCHECK(g_browser_process);

  Profile* profile = g_browser_process->profile_manager()->
      GetDefaultProfile(FilePath(user_data()));
  PrefService* prefs = profile->GetPrefs();
  PrefService* local_state = browser_process_->local_state();
  local_state->RegisterStringPref(prefs::kApplicationLocale, L"");
  local_state->RegisterBooleanPref(prefs::kMetricsReportingEnabled, false);

  browser::RegisterAllPrefs(prefs, local_state);

  // Override some settings to avoid hitting some preferences that have not
  // been registered.
  prefs->SetBoolean(prefs::kPasswordManagerEnabled, false);
  prefs->SetBoolean(prefs::kAlternateErrorPagesEnabled, false);
  prefs->SetBoolean(prefs::kSafeBrowsingEnabled, false);

  profile->InitExtensions();
}

void FakeExternalTab::Shutdown() {
  browser_process_.reset();
  g_browser_process = NULL;
  process_singleton_.reset();

  ResourceBundle::CleanupSharedInstance();
}

CFUrlRequestUnittestRunner::CFUrlRequestUnittestRunner(int argc, char** argv)
    : NetTestSuite(argc, argv),
      chrome_frame_html_("/chrome_frame", kChromeFrameHtml) {
  fake_chrome_.Initialize();
  pss_subclass_.reset(new ProcessSingletonSubclass(this));
  EXPECT_TRUE(pss_subclass_->Subclass(fake_chrome_.user_data()));
  StartChromeFrameInHostBrowser();
  // Register the main thread by instantiating it, but don't call any methods.
  main_thread_.reset(new ChromeThread(ChromeThread::UI));
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
}

CFUrlRequestUnittestRunner::~CFUrlRequestUnittestRunner() {
  fake_chrome_.Shutdown();
}

DWORD WINAPI NavigateIE(void* param) {
  return 0;
  win_util::ScopedCOMInitializer com;
  BSTR url = reinterpret_cast<BSTR>(param);

  bool found = false;
  int retries = 0;
  const int kMaxRetries = 20;
  while (!found && retries < kMaxRetries) {
    ScopedComPtr<IShellWindows> windows;
    HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL,
        IID_IShellWindows, reinterpret_cast<void**>(windows.Receive()));
    DCHECK(SUCCEEDED(hr)) << "CoCreateInstance";

    if (SUCCEEDED(hr)) {
      hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
      long count = 0;  // NOLINT
      windows->get_Count(&count);
      VARIANT i = { VT_I4 };
      for (i.lVal = 0; i.lVal < count; ++i.lVal) {
        ScopedComPtr<IDispatch> folder;
        windows->Item(i, folder.Receive());
        if (folder != NULL) {
          ScopedComPtr<IWebBrowser2> browser;
          if (SUCCEEDED(browser.QueryFrom(folder))) {
            found = true;
            browser->Stop();
            Sleep(1000);
            VARIANT empty = ScopedVariant::kEmptyVariant;
            hr = browser->Navigate(url, &empty, &empty, &empty, &empty);
            DCHECK(SUCCEEDED(hr)) << "Failed to navigate";
            break;
          }
        }
      }
    }
    if (!found) {
      DLOG(INFO) << "Waiting for browser to initialize...";
      ::Sleep(100);
      retries++;
    }
  }

  DCHECK(retries < kMaxRetries);
  DCHECK(found);

  ::SysFreeString(url);

  return 0;
}

void CFUrlRequestUnittestRunner::StartChromeFrameInHostBrowser() {
  if (!ShouldLaunchBrowser())
    return;

  win_util::ScopedCOMInitializer com;
  chrome_frame_test::CloseAllIEWindows();

  test_http_server_.reset(new test_server::SimpleWebServer(kTestServerPort));
  test_http_server_->AddResponse(&chrome_frame_html_);
  std::wstring url(StringPrintf(L"http://localhost:%i/chrome_frame",
                                kTestServerPort).c_str());

  // Launch IE.  This launches IE correctly on Vista too.
  ScopedHandle ie_process(chrome_frame_test::LaunchIE(url));
  EXPECT_TRUE(ie_process.IsValid());

  // NOTE: If you're running IE8 and CF is not being loaded, you need to
  // disable IE8's prebinding until CF properly handles that situation.
  //
  // HKCU\Software\Microsoft\Internet Explorer\Main
  // Value name: EnablePreBinding (REG_DWORD)
  // Value: 0
}

void CFUrlRequestUnittestRunner::ShutDownHostBrowser() {
  if (ShouldLaunchBrowser()) {
    win_util::ScopedCOMInitializer com;
    chrome_frame_test::CloseAllIEWindows();
  }
}

// Override virtual void Initialize to not call icu initialize
void CFUrlRequestUnittestRunner::Initialize() {
  DCHECK(::GetCurrentThreadId() == test_thread_id_);

  // Start by replicating some of the steps that would otherwise be
  // done by TestSuite::Initialize.  We can't call the base class
  // directly because it will attempt to initialize some things such as
  // ICU that have already been initialized for this process.
  InitializeLogging();
  base::Time::EnableHiResClockForTests();

#if !defined(PURIFY) && defined(OS_WIN)
  logging::SetLogAssertHandler(UnitTestAssertHandler);
#endif  // !defined(PURIFY)

  // Next, do some initialization for NetTestSuite.
  NetTestSuite::InitializeTestThread();
}

void CFUrlRequestUnittestRunner::Shutdown() {
  DCHECK(::GetCurrentThreadId() == test_thread_id_);
  NetTestSuite::Shutdown();
}

void CFUrlRequestUnittestRunner::OnConnectAutomationProviderToChannel(
    const std::string& channel_id) {
  Profile* profile = g_browser_process->profile_manager()->
      GetDefaultProfile(fake_chrome_.user_data());

  AutomationProviderList* list =
      g_browser_process->InitAutomationProviderList();
  DCHECK(list);
  list->AddProvider(TestAutomationProvider::NewAutomationProvider(profile,
      channel_id, this));
}

void CFUrlRequestUnittestRunner::OnInitialTabLoaded() {
  test_http_server_.reset();
  StartTests();
}

void CFUrlRequestUnittestRunner::RunMainUIThread() {
  DCHECK(MessageLoop::current());
  DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
  MessageLoop::current()->Run();
}

void CFUrlRequestUnittestRunner::StartTests() {
  if (PromptAfterSetup())
    MessageBoxA(NULL, "click ok to run", "", MB_OK);

  DCHECK_EQ(test_thread_.IsValid(), false);
  test_thread_.Set(::CreateThread(NULL, 0, RunAllUnittests, this, 0,
                                  &test_thread_id_));
  DCHECK(test_thread_.IsValid());
}

// static
DWORD CFUrlRequestUnittestRunner::RunAllUnittests(void* param) {
  PlatformThread::SetName("CFUrlRequestUnittestRunner");
  CFUrlRequestUnittestRunner* me =
      reinterpret_cast<CFUrlRequestUnittestRunner*>(param);
  me->Run();
  me->fake_chrome_.ui_loop()->PostTask(FROM_HERE,
      NewRunnableFunction(TakeDownBrowser, me));
  return 0;
}

// static
void CFUrlRequestUnittestRunner::TakeDownBrowser(
    CFUrlRequestUnittestRunner* me) {
  if (PromptAfterSetup())
    MessageBoxA(NULL, "click ok to exit", "", MB_OK);

  me->ShutDownHostBrowser();
}

void CFUrlRequestUnittestRunner::InitializeLogging() {
  FilePath exe;
  PathService::Get(base::FILE_EXE, &exe);
  FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
  logging::InitLogging(log_filename.value().c_str(),
                       logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
                       logging::LOCK_LOG_FILE,
                       logging::DELETE_OLD_LOG_FILE);
  // We want process and thread IDs because we may have multiple processes.
  // Note: temporarily enabled timestamps in an effort to catch bug 6361.
  logging::SetLogItems(true, true, true, true);
}

void FilterDisabledTests() {
  if (::testing::FLAGS_gtest_filter.length() &&
      ::testing::FLAGS_gtest_filter.Compare("*") != 0) {
    // Don't override user specified filters.
    return;
  }

  const char* disabled_tests[] = {
    // Tests disabled since they're testing the same functionality used
    // by the TestAutomationProvider.
    "URLRequestTest.InterceptNetworkError",
    "URLRequestTest.InterceptRestartRequired",
    "URLRequestTest.InterceptRespectsCancelMain",
    "URLRequestTest.InterceptRespectsCancelRedirect",
    "URLRequestTest.InterceptRespectsCancelFinal",
    "URLRequestTest.InterceptRespectsCancelInRestart",
    "URLRequestTest.InterceptRedirect",
    "URLRequestTest.InterceptServerError",
    "URLRequestTestFTP.*",

    // Tests that are currently not working:

    // Temporarily disabled because they needs user input (login dialog).
    "URLRequestTestHTTP.BasicAuth",
    "URLRequestTestHTTP.BasicAuthWithCookies",

    // HTTPS tests temporarily disabled due to the certificate error dialog.
    // TODO(tommi): The tests currently fail though, so need to fix.
    "HTTPSRequestTest.HTTPSMismatchedTest",
    "HTTPSRequestTest.HTTPSExpiredTest",

    // Tests chrome's network stack's cache (might not apply to CF).
    "URLRequestTestHTTP.VaryHeader",

    // I suspect we can only get this one to work (if at all) on IE8 and
    // later by using the new INTERNET_OPTION_SUPPRESS_BEHAVIOR flags
    // See http://msdn.microsoft.com/en-us/library/aa385328(VS.85).aspx
    "URLRequestTest.DoNotSaveCookies",
  };

  std::string filter("-");  // All following filters will be negative.
  for (int i = 0; i < arraysize(disabled_tests); ++i) {
    if (i > 0)
      filter += ":";
    filter += disabled_tests[i];
  }

  ::testing::FLAGS_gtest_filter = filter;
}

int main(int argc, char** argv) {
  DialogWatchdog watchdog;
  // See url_request_unittest.cc for these credentials.
  SupplyProxyCredentials credentials("user", "secret");
  watchdog.AddObserver(&credentials);
  testing::InitGoogleTest(&argc, argv);
  FilterDisabledTests();
  CFUrlRequestUnittestRunner test_suite(argc, argv);
  test_suite.RunMainUIThread();
  return 0;
}
<|endoftext|>


<commit_before>#include <Pith/Config.hpp>
#include <Pith/Page.hpp>
#include <gtest/gtest.h>

using namespace Pith;

TEST(TestPage, stackAllocate) {
	[[gnu::unused]] Page p;
}

TEST(TestPage, mapOnePage) {
	Span<Page> pages{nullptr, 1};
	auto result = Page::map(pages);
	EXPECT_TRUE(result);
	EXPECT_NE(result(), nullptr);
	pages.value(result());
	EXPECT_EQ(Page::unmap(pages), 0);
}

TEST(TestPage, setPermissions) {
	Span<Page> pages{nullptr, 1};
}

TEST(TestPage, setPermissionsOnUnmappedPage) {
	Span<Page> pages{nullptr, 1};

	// Get a fresh page.
	{
		auto r = Page::map(pages);
		ASSERT_TRUE(r);
		pages.value(r());
	}

	// Explicitly unmap it.
	{
		auto e = Page::unmap(pages);
		ASSERT_EQ(e, 0);
	}

	// Fail to set permissions on unmapped page.
	{
		auto e = Page::setPermissions(pages, Page::Permissions::READ);
		ASSERT_NE(e, 0);
	}
}

#if 0
TEST(PageSpan, mapAndUnmap) {
	PageSpan pages{nullptr, 1};
	auto map = pages.map();
	map.unmap();
}
#endif  // 0<commit_msg>Update the page tests to work with the new API<commit_after>#include <Pith/Config.hpp>
#include <Pith/Page.hpp>
#include <gtest/gtest.h>

using namespace Pith;

TEST(TestPage, pageSize) {
	Process::init();
	EXPECT_NE(Page::size(), std::size_t{0});
	Process::kill();
}

TEST(TestPage, mapOnePage) {
	Process::init();
	auto size = Page::size();
	auto addr = Page::map(size);
	Page::unmap(addr, size);
	Process::kill();
}
<|endoftext|>


<commit_before>/*  -*- c++ -*-
    identitydialog.cpp

    This file is part of KMail, the KDE mail client.
    Copyright (c) 2002 Marc Mutz <mutz@kde.org>

    KMail is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License, version 2, as
    published by the Free Software Foundation.

    KMail is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "identitydialog.h"

// other KMail headers:
#include "signatureconfigurator.h"
#include "kmfoldercombobox.h"
#include "kmfoldermgr.h"
#include "transportmanager.h"
#include "kmkernel.h"

// other kdenetwork headers:
#include <kpgpui.h>

// other KDE headers:
#include <klineedit.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kconfig.h>

// Qt headers:
#include <qtabwidget.h>
#include <qlabel.h>
#include <qwhatsthis.h>

// other headers: (none)

namespace KMail {

  IdentityDialog::IdentityDialog( QWidget * parent, const char * name )
    : KDialogBase( Plain, i18n("Edit Identity"), Ok|Cancel|Help, Ok,
		   parent, name )
  {
    // tmp. vars:
    QWidget * tab;
    QLabel  * label;
    int row;
    QGridLayout * glay;
    QString msg;

    //
    // Tab Widget: General
    //
    row = -1;
    QVBoxLayout * vlay = new QVBoxLayout( plainPage(), 0, spacingHint() );
    QTabWidget *tabWidget = new QTabWidget( plainPage(), "config-identity-tab" );
    vlay->addWidget( tabWidget );

    tab = new QWidget( tabWidget );
    tabWidget->addTab( tab, i18n("&General") );
    glay = new QGridLayout( tab, 4, 2, marginHint(), spacingHint() );
    glay->setRowStretch( 3, 1 );
    glay->setColStretch( 1, 1 );

    // "Name" line edit and label:
    ++row;
    mNameEdit = new KLineEdit( tab );
    glay->addWidget( mNameEdit, row, 1 );
    glay->addWidget( new QLabel( mNameEdit, i18n("&Your name:"), tab ), row, 0 );

    // "Organization" line edit and label:
    ++row;
    mOrganizationEdit = new KLineEdit( tab );
    glay->addWidget( mOrganizationEdit, row, 1 );
    glay->addWidget( new QLabel( mOrganizationEdit,
				 i18n("Organi&zation:"), tab ), row, 0 );

    // "Email Address" line edit and label:
    // (row 3: spacer)
    ++row;
    mEmailEdit = new KLineEdit( tab );
    glay->addWidget( mEmailEdit, row, 1 );
    glay->addWidget( new QLabel( mEmailEdit, i18n("&Email address:"), tab ),
		     row, 0 );

    //
    // Tab Widget: Advanced
    //
    row = -1;
    tab = new QWidget( tabWidget );
    tabWidget->addTab( tab, i18n("&Advanced") );
    glay = new QGridLayout( tab, 7, 2, marginHint(), spacingHint() );
    // the last (empty) row takes all the remaining space
    glay->setRowStretch( 7-1, 1 );
    glay->setColStretch( 1, 1 );

    // "Reply-To Address" line edit and label:
    ++row;
    mReplyToEdit = new KLineEdit( tab );
    glay->addWidget( mReplyToEdit, row, 1 );
    glay->addWidget( new QLabel( mReplyToEdit,
				 i18n("&Reply-To address:"), tab ), row, 0 );

    // "BCC addresses" line edit and label:
    ++row;
    mBccEdit = new KLineEdit( tab );
    glay->addWidget( mBccEdit, row, 1 );
    label = new QLabel( mBccEdit, i18n("&BCC addresses:"), tab );
    glay->addWidget( label, row, 0 );
    msg = i18n("<qt>
BCC (Blind Carbon Copy) addresses
"
	       "
The addresses that you enter here will be added to each "
	       "outgoing mail that is sent with this identity. They will not "
	       "be visible to other recipients.
"
	       "
This is commonly used to send a copy of each sent message to "
	       "another account of yours.
"
	       "
If in doubt, leave this field blank.
</qt>");
    QWhatsThis::add( label, msg );
    QWhatsThis::add( mBccEdit, msg );

    // "OpenPGP Key" requester and label:
    ++row;
    mPgpKeyRequester = new Kpgp::SecretKeyRequester( tab );
    mPgpKeyRequester->dialogButton()->setText( i18n("Chang&e...") );
    mPgpKeyRequester->setDialogCaption( i18n("Your OpenPGP Key") );
    mPgpKeyRequester->setDialogMessage( i18n("Select the OpenPGP key which "
					     "should be used to sign your "
					     "messages and when encrypting to "
					     "yourself.") );
    msg = i18n("<qt>
The OpenPGP key you choose here will be used "
	       "to sign messages and to encrypt messages to "
	       "yourself.
</qt>");

    label = new QLabel( mPgpKeyRequester, i18n("OpenPGP key:"), tab );
    QWhatsThis::add( mPgpKeyRequester, msg );
    QWhatsThis::add( label, msg );

    glay->addWidget( label, row, 0 );
    glay->addWidget( mPgpKeyRequester, row, 1 );

    // "Sent-mail Folder" combo box and label:
    ++row;
    mFccCombo = new KMFolderComboBox( tab );
    mFccCombo->showOutboxFolder( false );
    glay->addWidget( mFccCombo, row, 1 );
    glay->addWidget( new QLabel( mFccCombo, i18n("Sent-mail &folder:"), tab ),
		     row, 0 );

    // "Drafts Folder" combo box and label:
    ++row;
    mDraftsCombo = new KMFolderComboBox( tab );
    mDraftsCombo->showOutboxFolder( false );
    glay->addWidget( mDraftsCombo, row, 1 );
    glay->addWidget( new QLabel( mDraftsCombo, i18n("&Drafts folder:"), tab ),
		     row, 0 );

    // "Special transport" combobox and label:
    ++row;
    mTransportCheck = new QCheckBox( i18n("Special &transport:"), tab );
    glay->addWidget( mTransportCheck, row, 0 );
    mTransportCombo = new QComboBox( true, tab );
    mTransportCombo->setEnabled( false ); // since !mTransportCheck->isChecked()
    mTransportCombo->insertStringList( KMail::TransportManager::transportNames() );
    glay->addWidget( mTransportCombo, row, 1 );
    connect( mTransportCheck, SIGNAL(toggled(bool)),
	     mTransportCombo, SLOT(setEnabled(bool)) );

    // the last row is a spacer

    //
    // Tab Widget: Signature
    //
    mSignatureConfigurator = new SignatureConfigurator( tabWidget );
    mSignatureConfigurator->layout()->setMargin( KDialog::marginHint() );
    tabWidget->addTab( mSignatureConfigurator, i18n("&Signature") );

    KConfigGroup geometry( KMKernel::config(), "Geometry" );
    if ( geometry.hasKey( "Identity Dialog size" ) )
      resize( geometry.readSizeEntry( "Identity Dialog size" ) );
    mNameEdit->setFocus();
  }

  IdentityDialog::~IdentityDialog() {
    KConfigGroup geometry( KMKernel::config(), "Geometry" );
    geometry.writeEntry( "Identity Dialog size", size() );
  }

  bool IdentityDialog::checkFolderExists( const QString & folderID,
					  const QString & msg ) {
    KMFolder * folder = kmkernel->folderMgr()->findIdString( folderID );
    if ( !folder )
      folder = kmkernel->imapFolderMgr()->findIdString( folderID );
    if ( !folder ) {
      KMessageBox::sorry( this, msg );
      return false;
    }
    return true;
  }

  void IdentityDialog::setIdentity( KMIdentity & ident ) {

    setCaption( i18n("Edit Identity \"%1\"").arg( ident.identityName() ) );

    // "General" tab:
    mNameEdit->setText( ident.fullName() );
    mOrganizationEdit->setText( ident.organization() );
    mEmailEdit->setText( ident.emailAddr() );

    // "Advanced" tab:
    mPgpKeyRequester->setKeyIDs( Kpgp::KeyIDList() << ident.pgpIdentity() );
    mReplyToEdit->setText( ident.replyToAddr() );
    mBccEdit->setText( ident.bcc() );
    mTransportCheck->setChecked( !ident.transport().isEmpty() );
    mTransportCombo->setEditText( ident.transport() );
    mTransportCombo->setEnabled( !ident.transport().isEmpty() );

    if ( ident.fcc().isEmpty() ||
	 !checkFolderExists( ident.fcc(),
			     i18n("The custom sent-mail folder for identity "
				  "\"%1\" doesn't exist (anymore). "
				  "Therefore the default sent-mail folder "
				  "will be used.")
			     .arg( ident.identityName() ) ) )
      mFccCombo->setFolder( kmkernel->sentFolder() );
    else
      mFccCombo->setFolder( ident.fcc() );

    if ( ident.drafts().isEmpty() ||
	 !checkFolderExists( ident.drafts(),
			     i18n("The custom drafts folder for identity "
				  "\"%1\" doesn't exist (anymore). "
				  "Therefore the default drafts folder "
				  "will be used.")
			     .arg( ident.identityName() ) ) )
      mDraftsCombo->setFolder( kmkernel->draftsFolder() );
    else
      mDraftsCombo->setFolder( ident.drafts() );

    // "Signature" tab:
    mSignatureConfigurator->setSignature( ident.signature() );
  }

  void IdentityDialog::updateIdentity( KMIdentity & ident ) {
    // "General" tab:
    ident.setFullName( mNameEdit->text() );
    ident.setOrganization( mOrganizationEdit->text() );
    ident.setEmailAddr( mEmailEdit->text() );
    // "Advanced" tab:
    ident.setPgpIdentity( mPgpKeyRequester->keyIDs().first() );
    ident.setReplyToAddr( mReplyToEdit->text() );
    ident.setBcc( mBccEdit->text() );
    ident.setTransport( ( mTransportCheck->isChecked() ) ?
			mTransportCombo->currentText() : QString::null );
    ident.setFcc( mFccCombo->getFolder() ?
		  mFccCombo->getFolder()->idString() : QString::null );
    ident.setDrafts( mDraftsCombo->getFolder() ?
		     mDraftsCombo->getFolder()->idString() : QString::null );
    // "Signature" tab:
    ident.setSignature( mSignatureConfigurator->signature() );
  }

  void IdentityDialog::slotUpdateTransportCombo( const QStringList & sl ) {
    // save old setting:
    QString content = mTransportCombo->currentText();
    // update combo box:
    mTransportCombo->clear();
    mTransportCombo->insertStringList( sl );
    // restore saved setting:
    mTransportCombo->setEditText( content );
  }

}

#include "identitydialog.moc"
<commit_msg>Add some extra QWhatsThis entries<commit_after>/*  -*- c++ -*-
    identitydialog.cpp

    This file is part of KMail, the KDE mail client.
    Copyright (c) 2002 Marc Mutz <mutz@kde.org>

    KMail is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License, version 2, as
    published by the Free Software Foundation.

    KMail is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "identitydialog.h"

// other KMail headers:
#include "signatureconfigurator.h"
#include "kmfoldercombobox.h"
#include "kmfoldermgr.h"
#include "transportmanager.h"
#include "kmkernel.h"

// other kdenetwork headers:
#include <kpgpui.h>

// other KDE headers:
#include <klineedit.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kconfig.h>

// Qt headers:
#include <qtabwidget.h>
#include <qlabel.h>
#include <qwhatsthis.h>

// other headers: (none)

namespace KMail {

  IdentityDialog::IdentityDialog( QWidget * parent, const char * name )
    : KDialogBase( Plain, i18n("Edit Identity"), Ok|Cancel|Help, Ok,
		   parent, name )
  {
    // tmp. vars:
    QWidget * tab;
    QLabel  * label;
    int row;
    QGridLayout * glay;
    QString msg;

    //
    // Tab Widget: General
    //
    row = -1;
    QVBoxLayout * vlay = new QVBoxLayout( plainPage(), 0, spacingHint() );
    QTabWidget *tabWidget = new QTabWidget( plainPage(), "config-identity-tab" );
    vlay->addWidget( tabWidget );

    tab = new QWidget( tabWidget );
    tabWidget->addTab( tab, i18n("&General") );
    glay = new QGridLayout( tab, 4, 2, marginHint(), spacingHint() );
    glay->setRowStretch( 3, 1 );
    glay->setColStretch( 1, 1 );

    // "Name" line edit and label:
    ++row;
    mNameEdit = new KLineEdit( tab );
    glay->addWidget( mNameEdit, row, 1 );
    label = new QLabel( mNameEdit, i18n("&Your name:"), tab );
    glay->addWidget( label, row, 0 );
    msg = i18n("<qt>
Your name
"
	       "
This field should have your name, as you'd like "
	       "it to appear in the email header that is sent out.
"
	       "
If you leave this blank, your real name won't "
	       "appear, only the email address.
</qt>");
    QWhatsThis::add( label, msg );
    QWhatsThis::add( mNameEdit, msg );

    // "Organization" line edit and label:
    ++row;
    mOrganizationEdit = new KLineEdit( tab );
    glay->addWidget( mOrganizationEdit, row, 1 );
    label =  new QLabel( mOrganizationEdit, i18n("Organi&zation:"), tab );
    glay->addWidget( label, row, 0 );
    msg = i18n("<qt>
Organization
"
	       "
This field should have the name of your organization "
	       "if you'd like it to be shown in the email header that "
	       "is sent out.
"
	       "
It is safe (and normal) to leave this blank.
</qt>");
    QWhatsThis::add( label, msg );
    QWhatsThis::add( mOrganizationEdit, msg );

    // "Email Address" line edit and label:
    // (row 3: spacer)
    ++row;
    mEmailEdit = new KLineEdit( tab );
    glay->addWidget( mEmailEdit, row, 1 );
    label = new QLabel( mEmailEdit, i18n("&Email address:"), tab );
    glay->addWidget( label, row, 0 );
    msg = i18n("<qt>
Email address
"
	       "
This field should have your full email address.
"
	       "
If you leave this blank, or get it wrong, people "
	       "will have trouble replying to you.
</qt>");
    QWhatsThis::add( label, msg );
    QWhatsThis::add( mEmailEdit, msg );

    //
    // Tab Widget: Advanced
    //
    row = -1;
    tab = new QWidget( tabWidget );
    tabWidget->addTab( tab, i18n("&Advanced") );
    glay = new QGridLayout( tab, 7, 2, marginHint(), spacingHint() );
    // the last (empty) row takes all the remaining space
    glay->setRowStretch( 7-1, 1 );
    glay->setColStretch( 1, 1 );

    // "Reply-To Address" line edit and label:
    ++row;
    mReplyToEdit = new KLineEdit( tab );
    glay->addWidget( mReplyToEdit, row, 1 );
    label = new QLabel ( mReplyToEdit, i18n("&Reply-To address:"), tab);
    glay->addWidget( label , row, 0 );
    msg = i18n("<qt>
Reply-To addresses
"
	       "
This sets the <tt>Reply-to:</tt> header to contain a "
	       "different email address to the normal <tt>From:</tt> "
	       "address.
"
	       "
This can be useful when you have a group of people "
	       "working together in similar roles. For example, you "
	       "might want any emails sent to have your email in the "
	       "<tt>From:</tt> field, but any responses to go to "
	       "a group address.
"
	       "
If in doubt, leave this field blank.
</qt>");
    QWhatsThis::add( label, msg );
    QWhatsThis::add( mReplyToEdit, msg );

    // "BCC addresses" line edit and label:
    ++row;
    mBccEdit = new KLineEdit( tab );
    glay->addWidget( mBccEdit, row, 1 );
    label = new QLabel( mBccEdit, i18n("&BCC addresses:"), tab );
    glay->addWidget( label, row, 0 );
    msg = i18n("<qt>
BCC (Blind Carbon Copy) addresses
"
	       "
The addresses that you enter here will be added to each "
	       "outgoing mail that is sent with this identity. They will not "
	       "be visible to other recipients.
"
	       "
This is commonly used to send a copy of each sent message to "
	       "another account of yours.
"
	       "
If in doubt, leave this field blank.
</qt>");
    QWhatsThis::add( label, msg );
    QWhatsThis::add( mBccEdit, msg );

    // "OpenPGP Key" requester and label:
    ++row;
    mPgpKeyRequester = new Kpgp::SecretKeyRequester( tab );
    mPgpKeyRequester->dialogButton()->setText( i18n("Chang&e...") );
    mPgpKeyRequester->setDialogCaption( i18n("Your OpenPGP Key") );
    mPgpKeyRequester->setDialogMessage( i18n("Select the OpenPGP key which "
					     "should be used to sign your "
					     "messages and when encrypting to "
					     "yourself.") );
    msg = i18n("<qt>
The OpenPGP key you choose here will be used "
	       "to sign messages and to encrypt messages to "
	       "yourself. You can also use GnuPG keys.
"
	       "You can leave this blank, but KMail won't be able "
	       "to cryptographically sign emails. Normal mail functions won't "
	       "be affected.
"
	       "You can find out more about keys at http://www.gnupg.org</qt>");

    label = new QLabel( mPgpKeyRequester, i18n("OpenPGP key:"), tab );
    QWhatsThis::add( mPgpKeyRequester, msg );
    QWhatsThis::add( label, msg );

    glay->addWidget( label, row, 0 );
    glay->addWidget( mPgpKeyRequester, row, 1 );

    // "Sent-mail Folder" combo box and label:
    ++row;
    mFccCombo = new KMFolderComboBox( tab );
    mFccCombo->showOutboxFolder( false );
    glay->addWidget( mFccCombo, row, 1 );
    glay->addWidget( new QLabel( mFccCombo, i18n("Sent-mail &folder:"), tab ),
		     row, 0 );

    // "Drafts Folder" combo box and label:
    ++row;
    mDraftsCombo = new KMFolderComboBox( tab );
    mDraftsCombo->showOutboxFolder( false );
    glay->addWidget( mDraftsCombo, row, 1 );
    glay->addWidget( new QLabel( mDraftsCombo, i18n("&Drafts folder:"), tab ),
		     row, 0 );

    // "Special transport" combobox and label:
    ++row;
    mTransportCheck = new QCheckBox( i18n("Special &transport:"), tab );
    glay->addWidget( mTransportCheck, row, 0 );
    mTransportCombo = new QComboBox( true, tab );
    mTransportCombo->setEnabled( false ); // since !mTransportCheck->isChecked()
    mTransportCombo->insertStringList( KMail::TransportManager::transportNames() );
    glay->addWidget( mTransportCombo, row, 1 );
    connect( mTransportCheck, SIGNAL(toggled(bool)),
	     mTransportCombo, SLOT(setEnabled(bool)) );

    // the last row is a spacer

    //
    // Tab Widget: Signature
    //
    mSignatureConfigurator = new SignatureConfigurator( tabWidget );
    mSignatureConfigurator->layout()->setMargin( KDialog::marginHint() );
    tabWidget->addTab( mSignatureConfigurator, i18n("&Signature") );

    KConfigGroup geometry( KMKernel::config(), "Geometry" );
    if ( geometry.hasKey( "Identity Dialog size" ) )
      resize( geometry.readSizeEntry( "Identity Dialog size" ) );
    mNameEdit->setFocus();
  }

  IdentityDialog::~IdentityDialog() {
    KConfigGroup geometry( KMKernel::config(), "Geometry" );
    geometry.writeEntry( "Identity Dialog size", size() );
  }

  bool IdentityDialog::checkFolderExists( const QString & folderID,
					  const QString & msg ) {
    KMFolder * folder = kmkernel->folderMgr()->findIdString( folderID );
    if ( !folder )
      folder = kmkernel->imapFolderMgr()->findIdString( folderID );
    if ( !folder ) {
      KMessageBox::sorry( this, msg );
      return false;
    }
    return true;
  }

  void IdentityDialog::setIdentity( KMIdentity & ident ) {

    setCaption( i18n("Edit Identity \"%1\"").arg( ident.identityName() ) );

    // "General" tab:
    mNameEdit->setText( ident.fullName() );
    mOrganizationEdit->setText( ident.organization() );
    mEmailEdit->setText( ident.emailAddr() );

    // "Advanced" tab:
    mPgpKeyRequester->setKeyIDs( Kpgp::KeyIDList() << ident.pgpIdentity() );
    mReplyToEdit->setText( ident.replyToAddr() );
    mBccEdit->setText( ident.bcc() );
    mTransportCheck->setChecked( !ident.transport().isEmpty() );
    mTransportCombo->setEditText( ident.transport() );
    mTransportCombo->setEnabled( !ident.transport().isEmpty() );

    if ( ident.fcc().isEmpty() ||
	 !checkFolderExists( ident.fcc(),
			     i18n("The custom sent-mail folder for identity "
				  "\"%1\" doesn't exist (anymore). "
				  "Therefore the default sent-mail folder "
				  "will be used.")
			     .arg( ident.identityName() ) ) )
      mFccCombo->setFolder( kmkernel->sentFolder() );
    else
      mFccCombo->setFolder( ident.fcc() );

    if ( ident.drafts().isEmpty() ||
	 !checkFolderExists( ident.drafts(),
			     i18n("The custom drafts folder for identity "
				  "\"%1\" doesn't exist (anymore). "
				  "Therefore the default drafts folder "
				  "will be used.")
			     .arg( ident.identityName() ) ) )
      mDraftsCombo->setFolder( kmkernel->draftsFolder() );
    else
      mDraftsCombo->setFolder( ident.drafts() );

    // "Signature" tab:
    mSignatureConfigurator->setSignature( ident.signature() );
  }

  void IdentityDialog::updateIdentity( KMIdentity & ident ) {
    // "General" tab:
    ident.setFullName( mNameEdit->text() );
    ident.setOrganization( mOrganizationEdit->text() );
    ident.setEmailAddr( mEmailEdit->text() );
    // "Advanced" tab:
    ident.setPgpIdentity( mPgpKeyRequester->keyIDs().first() );
    ident.setReplyToAddr( mReplyToEdit->text() );
    ident.setBcc( mBccEdit->text() );
    ident.setTransport( ( mTransportCheck->isChecked() ) ?
			mTransportCombo->currentText() : QString::null );
    ident.setFcc( mFccCombo->getFolder() ?
		  mFccCombo->getFolder()->idString() : QString::null );
    ident.setDrafts( mDraftsCombo->getFolder() ?
		     mDraftsCombo->getFolder()->idString() : QString::null );
    // "Signature" tab:
    ident.setSignature( mSignatureConfigurator->signature() );
  }

  void IdentityDialog::slotUpdateTransportCombo( const QStringList & sl ) {
    // save old setting:
    QString content = mTransportCombo->currentText();
    // update combo box:
    mTransportCombo->clear();
    mTransportCombo->insertStringList( sl );
    // restore saved setting:
    mTransportCombo->setEditText( content );
  }

}

#include "identitydialog.moc"
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: native_bootstrap.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: kz $ $Date: 2007-09-06 14:27:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cli_ure.hxx"

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include "uno/environment.hxx"
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "native_share.h"

#include "rtl/bootstrap.hxx"
#include "cppuhelper/bootstrap.hxx"

#include <delayimp.h>
#include <stdio.h>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

#define OFFICE_LOCATION_REGISTRY_KEY "Software\\OpenOffice.org\\UNO\\InstallPath"

namespace
{

char* getLibraryPath()
{
    static char* sPath = NULL;

    //do not use oslMutex here. That would cause to load sal and we would
    //run in a loop with delayLoadHook
    if (sPath == NULL)
    {
        //First we try the environment variable UNO_PATH. It overrides all other settings.
        //Get the UNO_PATH environment variable, do not use CRT, use Kernel library
        char * sEnvUnoPath = NULL;
        DWORD  cChars = GetEnvironmentVariableA("UNO_PATH", sEnvUnoPath, 0);
        if (cChars > 0)
        {
            sEnvUnoPath = new char[cChars];
            cChars = GetEnvironmentVariableA("UNO_PATH", sEnvUnoPath, cChars);
        }
        //store the UNO_PATH in the static variable that will be returned from now on.
        if (cChars > 0)
        {
            sPath = new char[cChars + 1];
            sPath[0] = 0;
            lstrcatA(sPath, sEnvUnoPath);
        }
        delete[] sEnvUnoPath;

        //try registry
        if (sPath == NULL)
        {
            bool failed = false;
            HKEY    hKey = 0;
            if (RegOpenKeyExA(HKEY_CURRENT_USER,OFFICE_LOCATION_REGISTRY_KEY,
                              0, KEY_READ, &hKey) != ERROR_SUCCESS)
            {
                if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, OFFICE_LOCATION_REGISTRY_KEY,
                                  0, KEY_READ, &hKey) != ERROR_SUCCESS)
                {
                    OSL_ASSERT(0);
#if OSL_DEBUG_LEVEL >= 2
                    fprintf(stderr, "cli_cppuhelper: Office not properly installed. "
                            "Could not open registry keys.");
#endif
                    failed = true;
                }
            }
            if (failed)
                return NULL;

            DWORD   dwType = 0;
            DWORD   dwLen = 0;
            char *arData = NULL;
            //get the length for the path to office
            if (RegQueryValueExA(hKey, NULL, NULL, &dwType, NULL,
                                 &dwLen) == ERROR_SUCCESS)
            {
                arData = new  char[dwLen];
                if (RegQueryValueExA(hKey, NULL, NULL, &dwType, (LPBYTE) arData,
                                     & dwLen) == ERROR_SUCCESS)
                {
                    sPath = new char[dwLen];
                    lstrcpyA(sPath, arData);
#if OSL_DEBUG_LEVEL >=2
                    fprintf(stdout,"[cli_cppuhelper]: Using path %s to load office libraries.", sPath);
#endif
                }
                delete [] arData;
            }
            RegCloseKey(hKey);
        }
        if (sPath)
        {
            //We extend the path to contain the program directory of the office,
            //so that components can use osl_loadModule with arguments, such as
            //"reg3.dll". That is, the arguments are only the library names.

            //Get the PATH environment variable, do not use CRT, use Kernel library
            char * sEnvPath = NULL;
            DWORD  cChars = GetEnvironmentVariableA("PATH", sEnvPath, 0);
            if (cChars > 0)
            {
                sEnvPath = new char[cChars];
                cChars = GetEnvironmentVariableA("PATH", sEnvPath, cChars);
            }
            if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
            {
                delete[] sEnvPath;
                return NULL;
            }

            //prepare the new PATH, including the path to the program folder
            char * sNewPath = NULL;
            int lenPath = lstrlenA(sEnvPath);
            if (lenPath > 0)
                sNewPath = new char[lenPath + lstrlenA(sPath) + 2];
            else
                sNewPath = new char[lenPath + 1];
            sNewPath[0] = 0;

            lstrcatA(sNewPath, sPath);
            if (lenPath)
            {
                lstrcatA(sNewPath, ";");
                lstrcatA(sNewPath, sEnvPath);
            }

            BOOL bSet = SetEnvironmentVariableA("PATH", sNewPath);

            delete[] sEnvPath;
            delete[] sNewPath;

            if (bSet == FALSE)
                return NULL;
        }
    }

    return  sPath;
}

//Hook for delayed loading of libraries which this library is linked with.
extern "C"  FARPROC WINAPI delayLoadHook(
    unsigned        dliNotify,
    PDelayLoadInfo  pdli
    )
{
    if (dliNotify == dliFailLoadLib)
    {
        char* sPath = getLibraryPath();
        if (sPath)
        {
            int lenPath = lstrlenA(sPath);
            //create string to contain the full path to cppuhelper
            int lenLib = lstrlenA(pdli->szDll);
            char*  sFullPath = new char[lenLib + lenPath + 2];
            sFullPath[0] = 0;
            sFullPath = lstrcatA(sFullPath, sPath);
            sFullPath = lstrcatA(sFullPath, "\\");
            sFullPath = lstrcatA(sFullPath, pdli->szDll);

            HMODULE handle = LoadLibraryExA(sFullPath, NULL,
                                            LOAD_WITH_ALTERED_SEARCH_PATH);
            delete[] sFullPath;
            return (FARPROC) handle;
        }
    }
    return 0;
}
}

ExternC
PfnDliHook   __pfnDliFailureHook2 = delayLoadHook;

namespace uno
{
namespace util
{

/** Bootstrapping native UNO.

    Bootstrapping requires the existence of many libraries which are contained
    in an office installation. To find and load these libraries the Windows
    registry keys HKEY_CURRENT_USER\Software\OpenOffice.org\UNO\InstallPath
    and HKEY_LOCAL_MACHINE\Software\OpenOffice.org\UNO\InstallPath are examined.
    These contain the paths to the program folder of the office which was
    installed most recently. Please note that the office's setup either
    writes the key in HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE dependent on
    whether the user chooses a user installation or an installation for all
    users.
*/
public __sealed __gc class Bootstrap
{
    inline Bootstrap() {}

public:

    /** Bootstraps the initial component context from a native UNO installation.

        @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
    */
    static ::unoidl::com::sun::star::uno::XComponentContext *
        defaultBootstrap_InitialComponentContext();

    /** Bootstraps the initial component context from a native UNO installation.

        @param ini_file
               a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must
               reside next to the cppuhelper library)
        @param bootstrap_parameters
               bootstrap parameters (maybe null)

        @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
    */
    static ::unoidl::com::sun::star::uno::XComponentContext *
        defaultBootstrap_InitialComponentContext(
            ::System::String * ini_file,
            ::System::Collections::IDictionaryEnumerator *
              bootstrap_parameters );

    /** Bootstraps the initial component context from a native UNO installation.

    @see cppuhelper/bootstrap.hxx:bootstrap()
     */
    static ::unoidl::com::sun::star::uno::XComponentContext *
    bootstrap();
};

//______________________________________________________________________________
::unoidl::com::sun::star::uno::XComponentContext *
Bootstrap::defaultBootstrap_InitialComponentContext(
    ::System::String * ini_file,
    ::System::Collections::IDictionaryEnumerator * bootstrap_parameters )
{
    if (0 != bootstrap_parameters)
    {
        bootstrap_parameters->Reset();
        while (bootstrap_parameters->MoveNext())
        {
            OUString key(
                String_to_ustring( __try_cast< ::System::String * >(
                                       bootstrap_parameters->get_Key() ) ) );
            OUString value(
                String_to_ustring( __try_cast< ::System::String * >(
                                       bootstrap_parameters->get_Value() ) ) );

            ::rtl::Bootstrap::set( key, value );
        }
    }

    // bootstrap native uno
    Reference< XComponentContext > xContext;
    if (0 == ini_file)
    {
        xContext = ::cppu::defaultBootstrap_InitialComponentContext();
    }
    else
    {
        xContext = ::cppu::defaultBootstrap_InitialComponentContext(
            String_to_ustring( __try_cast< ::System::String * >( ini_file ) ) );
    }

    return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
        to_cli( xContext ) );
}

//______________________________________________________________________________
::unoidl::com::sun::star::uno::XComponentContext *
Bootstrap::defaultBootstrap_InitialComponentContext()
{
    return defaultBootstrap_InitialComponentContext( 0, 0 );
}

::unoidl::com::sun::star::uno::XComponentContext * Bootstrap::bootstrap()
{
    Reference<XComponentContext> xContext = ::cppu::bootstrap();
    return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
        to_cli( xContext ) );

}

}
}
<commit_msg>INTEGRATION: CWS sb71 (1.9.24); FILE MERGED 2007/10/02 09:07:59 sb 1.9.24.3: RESYNC: (1.10-1.11); FILE MERGED 2007/05/30 14:11:22 sb 1.9.24.2: RESYNC: (1.9-1.10); FILE MERGED 2007/04/23 09:36:46 sb 1.9.24.1: #i75466# Missing includes.'<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: native_bootstrap.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: vg $ $Date: 2007-10-15 12:26:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cli_ure.hxx"

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include "uno/environment.hxx"
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "native_share.h"

#include "rtl/bootstrap.hxx"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "cppuhelper/bootstrap.hxx"

#include <delayimp.h>
#include <stdio.h>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

#define OFFICE_LOCATION_REGISTRY_KEY "Software\\OpenOffice.org\\UNO\\InstallPath"

namespace
{

char* getLibraryPath()
{
    static char* sPath = NULL;

    //do not use oslMutex here. That would cause to load sal and we would
    //run in a loop with delayLoadHook
    if (sPath == NULL)
    {
        //First we try the environment variable UNO_PATH. It overrides all other settings.
        //Get the UNO_PATH environment variable, do not use CRT, use Kernel library
        char * sEnvUnoPath = NULL;
        DWORD  cChars = GetEnvironmentVariableA("UNO_PATH", sEnvUnoPath, 0);
        if (cChars > 0)
        {
            sEnvUnoPath = new char[cChars];
            cChars = GetEnvironmentVariableA("UNO_PATH", sEnvUnoPath, cChars);
        }
        //store the UNO_PATH in the static variable that will be returned from now on.
        if (cChars > 0)
        {
            sPath = new char[cChars + 1];
            sPath[0] = 0;
            lstrcatA(sPath, sEnvUnoPath);
        }
        delete[] sEnvUnoPath;

        //try registry
        if (sPath == NULL)
        {
            bool failed = false;
            HKEY    hKey = 0;
            if (RegOpenKeyExA(HKEY_CURRENT_USER,OFFICE_LOCATION_REGISTRY_KEY,
                              0, KEY_READ, &hKey) != ERROR_SUCCESS)
            {
                if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, OFFICE_LOCATION_REGISTRY_KEY,
                                  0, KEY_READ, &hKey) != ERROR_SUCCESS)
                {
                    OSL_ASSERT(0);
#if OSL_DEBUG_LEVEL >= 2
                    fprintf(stderr, "cli_cppuhelper: Office not properly installed. "
                            "Could not open registry keys.");
#endif
                    failed = true;
                }
            }
            if (failed)
                return NULL;

            DWORD   dwType = 0;
            DWORD   dwLen = 0;
            char *arData = NULL;
            //get the length for the path to office
            if (RegQueryValueExA(hKey, NULL, NULL, &dwType, NULL,
                                 &dwLen) == ERROR_SUCCESS)
            {
                arData = new  char[dwLen];
                if (RegQueryValueExA(hKey, NULL, NULL, &dwType, (LPBYTE) arData,
                                     & dwLen) == ERROR_SUCCESS)
                {
                    sPath = new char[dwLen];
                    lstrcpyA(sPath, arData);
#if OSL_DEBUG_LEVEL >=2
                    fprintf(stdout,"[cli_cppuhelper]: Using path %s to load office libraries.", sPath);
#endif
                }
                delete [] arData;
            }
            RegCloseKey(hKey);
        }
        if (sPath)
        {
            //We extend the path to contain the program directory of the office,
            //so that components can use osl_loadModule with arguments, such as
            //"reg3.dll". That is, the arguments are only the library names.

            //Get the PATH environment variable, do not use CRT, use Kernel library
            char * sEnvPath = NULL;
            DWORD  cChars = GetEnvironmentVariableA("PATH", sEnvPath, 0);
            if (cChars > 0)
            {
                sEnvPath = new char[cChars];
                cChars = GetEnvironmentVariableA("PATH", sEnvPath, cChars);
            }
            if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
            {
                delete[] sEnvPath;
                return NULL;
            }

            //prepare the new PATH, including the path to the program folder
            char * sNewPath = NULL;
            int lenPath = lstrlenA(sEnvPath);
            if (lenPath > 0)
                sNewPath = new char[lenPath + lstrlenA(sPath) + 2];
            else
                sNewPath = new char[lenPath + 1];
            sNewPath[0] = 0;

            lstrcatA(sNewPath, sPath);
            if (lenPath)
            {
                lstrcatA(sNewPath, ";");
                lstrcatA(sNewPath, sEnvPath);
            }

            BOOL bSet = SetEnvironmentVariableA("PATH", sNewPath);

            delete[] sEnvPath;
            delete[] sNewPath;

            if (bSet == FALSE)
                return NULL;
        }
    }

    return  sPath;
}

//Hook for delayed loading of libraries which this library is linked with.
extern "C"  FARPROC WINAPI delayLoadHook(
    unsigned        dliNotify,
    PDelayLoadInfo  pdli
    )
{
    if (dliNotify == dliFailLoadLib)
    {
        char* sPath = getLibraryPath();
        if (sPath)
        {
            int lenPath = lstrlenA(sPath);
            //create string to contain the full path to cppuhelper
            int lenLib = lstrlenA(pdli->szDll);
            char*  sFullPath = new char[lenLib + lenPath + 2];
            sFullPath[0] = 0;
            sFullPath = lstrcatA(sFullPath, sPath);
            sFullPath = lstrcatA(sFullPath, "\\");
            sFullPath = lstrcatA(sFullPath, pdli->szDll);

            HMODULE handle = LoadLibraryExA(sFullPath, NULL,
                                            LOAD_WITH_ALTERED_SEARCH_PATH);
            delete[] sFullPath;
            return (FARPROC) handle;
        }
    }
    return 0;
}
}

ExternC
PfnDliHook   __pfnDliFailureHook2 = delayLoadHook;

namespace uno
{
namespace util
{

/** Bootstrapping native UNO.

    Bootstrapping requires the existence of many libraries which are contained
    in an office installation. To find and load these libraries the Windows
    registry keys HKEY_CURRENT_USER\Software\OpenOffice.org\UNO\InstallPath
    and HKEY_LOCAL_MACHINE\Software\OpenOffice.org\UNO\InstallPath are examined.
    These contain the paths to the program folder of the office which was
    installed most recently. Please note that the office's setup either
    writes the key in HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE dependent on
    whether the user chooses a user installation or an installation for all
    users.
*/
public __sealed __gc class Bootstrap
{
    inline Bootstrap() {}

public:

    /** Bootstraps the initial component context from a native UNO installation.

        @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
    */
    static ::unoidl::com::sun::star::uno::XComponentContext *
        defaultBootstrap_InitialComponentContext();

    /** Bootstraps the initial component context from a native UNO installation.

        @param ini_file
               a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must
               reside next to the cppuhelper library)
        @param bootstrap_parameters
               bootstrap parameters (maybe null)

        @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
    */
    static ::unoidl::com::sun::star::uno::XComponentContext *
        defaultBootstrap_InitialComponentContext(
            ::System::String * ini_file,
            ::System::Collections::IDictionaryEnumerator *
              bootstrap_parameters );

    /** Bootstraps the initial component context from a native UNO installation.

    @see cppuhelper/bootstrap.hxx:bootstrap()
     */
    static ::unoidl::com::sun::star::uno::XComponentContext *
    bootstrap();
};

//______________________________________________________________________________
::unoidl::com::sun::star::uno::XComponentContext *
Bootstrap::defaultBootstrap_InitialComponentContext(
    ::System::String * ini_file,
    ::System::Collections::IDictionaryEnumerator * bootstrap_parameters )
{
    if (0 != bootstrap_parameters)
    {
        bootstrap_parameters->Reset();
        while (bootstrap_parameters->MoveNext())
        {
            OUString key(
                String_to_ustring( __try_cast< ::System::String * >(
                                       bootstrap_parameters->get_Key() ) ) );
            OUString value(
                String_to_ustring( __try_cast< ::System::String * >(
                                       bootstrap_parameters->get_Value() ) ) );

            ::rtl::Bootstrap::set( key, value );
        }
    }

    // bootstrap native uno
    Reference< XComponentContext > xContext;
    if (0 == ini_file)
    {
        xContext = ::cppu::defaultBootstrap_InitialComponentContext();
    }
    else
    {
        xContext = ::cppu::defaultBootstrap_InitialComponentContext(
            String_to_ustring( __try_cast< ::System::String * >( ini_file ) ) );
    }

    return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
        to_cli( xContext ) );
}

//______________________________________________________________________________
::unoidl::com::sun::star::uno::XComponentContext *
Bootstrap::defaultBootstrap_InitialComponentContext()
{
    return defaultBootstrap_InitialComponentContext( 0, 0 );
}

::unoidl::com::sun::star::uno::XComponentContext * Bootstrap::bootstrap()
{
    Reference<XComponentContext> xContext = ::cppu::bootstrap();
    return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
        to_cli( xContext ) );

}

}
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "mangling.hpp"
#include "Type.hpp"
#include "Platform.hpp"
#include "GlobalContext.hpp"

using namespace eddic;

/* Standard Types */

std::shared_ptr<const Type> eddic::BOOL = std::make_shared<StandardType>(BaseType::BOOL, false);
std::shared_ptr<const Type> eddic::INT = std::make_shared<StandardType>(BaseType::INT, false);
std::shared_ptr<const Type> eddic::CHAR = std::make_shared<StandardType>(BaseType::CHAR, false);
std::shared_ptr<const Type> eddic::FLOAT = std::make_shared<StandardType>(BaseType::FLOAT, false);
std::shared_ptr<const Type> eddic::STRING = std::make_shared<StandardType>(BaseType::STRING, false);
std::shared_ptr<const Type> eddic::VOID = std::make_shared<StandardType>(BaseType::VOID, false);

/* Const versions */

const std::shared_ptr<const Type> CBOOL = std::make_shared<StandardType>(BaseType::BOOL, true);
const std::shared_ptr<const Type> CINT = std::make_shared<StandardType>(BaseType::INT, true);
const std::shared_ptr<const Type> CCHAR = std::make_shared<StandardType>(BaseType::CHAR, true);
const std::shared_ptr<const Type> CFLOAT = std::make_shared<StandardType>(BaseType::FLOAT, true);
const std::shared_ptr<const Type> CSTRING = std::make_shared<StandardType>(BaseType::STRING, true);
const std::shared_ptr<const Type> CVOID = std::make_shared<StandardType>(BaseType::VOID, true);

/* Implementation of Type */

Type::Type() {}

bool Type::is_array() const {
    return false;
}

bool Type::is_dynamic_array() const {
    return is_array() && !has_elements();
}

bool Type::is_structure() const {
    return is_custom_type() || is_template_type();
}

bool Type::is_pointer() const {
    return false;
}

bool Type::is_custom_type() const {
    return false;
}

bool Type::is_standard_type() const {
    return false;
}

bool Type::is_const() const {
    return false;
}

bool Type::is_template_type() const {
    return false;
}

unsigned int Type::size(Platform) const {
    eddic_unreachable("Not specialized type");
}

unsigned int Type::elements() const {
    eddic_unreachable("Not an array type");
}

bool Type::has_elements() const {
    eddic_unreachable("Not an array type");
}

std::string Type::type() const {
    eddic_unreachable("Not a custom type");
}

std::shared_ptr<const Type> Type::data_type() const {
    eddic_unreachable("No data type");
}

std::vector<std::shared_ptr<const Type>> Type::template_types() const {
    eddic_unreachable("No template types");
}

BaseType Type::base() const {
    eddic_unreachable("Not a standard type");
}

std::string Type::mangle() const {
    return ::mangle(shared_from_this());
}

bool eddic::operator==(std::shared_ptr<const Type> lhs, std::shared_ptr<const Type> rhs){
    if(lhs->is_array()){
        return rhs->is_array() && lhs->data_type() == rhs->data_type() ;//&& lhs->elements() == rhs->elements();
    }

    if(lhs->is_pointer()){
        return rhs->is_pointer() && lhs->data_type() == rhs->data_type();
    }

    if(lhs->is_custom_type()){
        return rhs->is_custom_type() && lhs->type() == rhs->type();
    }

    if(lhs->is_standard_type()){
        return rhs->is_standard_type() && lhs->base() == rhs->base();
    }

    if(lhs->is_template_type()){
        if(rhs->is_template_type() && lhs->type() == rhs->type()){
            return lhs->template_types() == rhs->template_types();
        }
    }

    return false;
}

bool eddic::operator!=(std::shared_ptr<const Type> lhs, std::shared_ptr<const Type> rhs){
    return !(lhs == rhs);
}

/* Implementation of StandardType  */

StandardType::StandardType(BaseType type, bool const_) : base_type(type), const_(const_) {}

BaseType StandardType::base() const {
    return base_type;
}

bool StandardType::is_standard_type() const {
    return true;
}

bool StandardType::is_const() const {
    return const_;
}

unsigned int StandardType::size(Platform platform) const {
    auto descriptor = getPlatformDescriptor(platform);
    return descriptor->size_of(base());
}

/* Implementation of CustomType */

CustomType::CustomType(std::shared_ptr<GlobalContext> context, const std::string& type) :
    context(context), m_type(type) {}

std::string CustomType::type() const {
    return m_type;
}

bool CustomType::is_custom_type() const {
    return true;
}

unsigned int CustomType::size(Platform) const {
    return context->total_size_of_struct(context->get_struct(shared_from_this()));
}

/* Implementation of ArrayType  */

ArrayType::ArrayType(std::shared_ptr<const Type> sub_type) : sub_type(sub_type) {}
ArrayType::ArrayType(std::shared_ptr<const Type> sub_type, int size) : sub_type(sub_type), m_elements(size) {}

unsigned int ArrayType::elements() const {
    assert(has_elements());

    return *m_elements;
}

bool ArrayType::has_elements() const {
    return m_elements;
}

std::shared_ptr<const Type> ArrayType::data_type() const {
    return sub_type;
}

bool ArrayType::is_array() const {
    return true;
}

unsigned int ArrayType::size(Platform platform) const {
    if(has_elements()){
        return data_type()->size(platform) * elements() + INT->size(platform);
    } else {
        return INT->size(platform);
    }
}

/* Implementation of PointerType  */

PointerType::PointerType(std::shared_ptr<const Type> sub_type) : sub_type(sub_type) {}

std::shared_ptr<const Type> PointerType::data_type() const {
    return sub_type;
}

bool PointerType::is_pointer() const {
    return true;
}

unsigned int PointerType::size(Platform platform) const {
    return INT->size(platform);
}

/* Implementation of TemplateType  */

TemplateType::TemplateType(std::shared_ptr<GlobalContext> context, std::string main_type, std::vector<std::shared_ptr<const Type>> sub_types) :
    context(context), main_type(main_type), sub_types(sub_types) {}

std::string TemplateType::type() const {
    return main_type;
}

std::vector<std::shared_ptr<const Type>> TemplateType::template_types() const {
    return sub_types;
}

bool TemplateType::is_template_type() const {
    return true;
}

unsigned int TemplateType::size(Platform) const {
    return context->total_size_of_struct(context->get_struct(shared_from_this()));
}

/* Implementation of factories  */

std::shared_ptr<const Type> eddic::new_type(std::shared_ptr<GlobalContext> context, const std::string& type, bool const_){
    //Parse standard and custom types
    if(is_standard_type(type)){
        if(const_){
            if (type == "int") {
                return CINT;
            } else if (type == "char") {
                return CCHAR;
            } else if (type == "bool") {
                return CBOOL;
            } else if (type == "float"){
                return CFLOAT;
            } else if (type == "str"){
                return CSTRING;
            } else {
                return CVOID;
            }
        } else {
            if (type == "int") {
                return INT;
            } else if (type == "char") {
                return CHAR;
            } else if (type == "bool") {
                return BOOL;
            } else if (type == "float"){
                return FLOAT;
            } else if (type == "str"){
                return STRING;
            } else {
                return VOID;
            }
        }
    } else {
        assert(!const_);
        return std::make_shared<CustomType>(context, type);
    }
}

std::shared_ptr<const Type> eddic::new_array_type(std::shared_ptr<const Type> data_type){
    return std::make_shared<ArrayType>(data_type);
}

std::shared_ptr<const Type> eddic::new_array_type(std::shared_ptr<const Type> data_type, int size){
    return std::make_shared<ArrayType>(data_type, size);
}

std::shared_ptr<const Type> eddic::new_pointer_type(std::shared_ptr<const Type> data_type){
    return std::make_shared<PointerType>(data_type);
}

std::shared_ptr<const Type> eddic::new_template_type(std::shared_ptr<GlobalContext> context, std::string data_type, std::vector<std::shared_ptr<const Type>> template_types){
    return std::make_shared<TemplateType>(context, data_type, template_types);
}

bool eddic::is_standard_type(const std::string& type){
    return type == "int" || type == "char" || type == "void" || type == "str" || type == "bool" || type == "float";
}
<commit_msg>Fix explicit conversion<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "mangling.hpp"
#include "Type.hpp"
#include "Platform.hpp"
#include "GlobalContext.hpp"

using namespace eddic;

/* Standard Types */

std::shared_ptr<const Type> eddic::BOOL = std::make_shared<StandardType>(BaseType::BOOL, false);
std::shared_ptr<const Type> eddic::INT = std::make_shared<StandardType>(BaseType::INT, false);
std::shared_ptr<const Type> eddic::CHAR = std::make_shared<StandardType>(BaseType::CHAR, false);
std::shared_ptr<const Type> eddic::FLOAT = std::make_shared<StandardType>(BaseType::FLOAT, false);
std::shared_ptr<const Type> eddic::STRING = std::make_shared<StandardType>(BaseType::STRING, false);
std::shared_ptr<const Type> eddic::VOID = std::make_shared<StandardType>(BaseType::VOID, false);

/* Const versions */

const std::shared_ptr<const Type> CBOOL = std::make_shared<StandardType>(BaseType::BOOL, true);
const std::shared_ptr<const Type> CINT = std::make_shared<StandardType>(BaseType::INT, true);
const std::shared_ptr<const Type> CCHAR = std::make_shared<StandardType>(BaseType::CHAR, true);
const std::shared_ptr<const Type> CFLOAT = std::make_shared<StandardType>(BaseType::FLOAT, true);
const std::shared_ptr<const Type> CSTRING = std::make_shared<StandardType>(BaseType::STRING, true);
const std::shared_ptr<const Type> CVOID = std::make_shared<StandardType>(BaseType::VOID, true);

/* Implementation of Type */

Type::Type() {}

bool Type::is_array() const {
    return false;
}

bool Type::is_dynamic_array() const {
    return is_array() && !has_elements();
}

bool Type::is_structure() const {
    return is_custom_type() || is_template_type();
}

bool Type::is_pointer() const {
    return false;
}

bool Type::is_custom_type() const {
    return false;
}

bool Type::is_standard_type() const {
    return false;
}

bool Type::is_const() const {
    return false;
}

bool Type::is_template_type() const {
    return false;
}

unsigned int Type::size(Platform) const {
    eddic_unreachable("Not specialized type");
}

unsigned int Type::elements() const {
    eddic_unreachable("Not an array type");
}

bool Type::has_elements() const {
    eddic_unreachable("Not an array type");
}

std::string Type::type() const {
    eddic_unreachable("Not a custom type");
}

std::shared_ptr<const Type> Type::data_type() const {
    eddic_unreachable("No data type");
}

std::vector<std::shared_ptr<const Type>> Type::template_types() const {
    eddic_unreachable("No template types");
}

BaseType Type::base() const {
    eddic_unreachable("Not a standard type");
}

std::string Type::mangle() const {
    return ::mangle(shared_from_this());
}

bool eddic::operator==(std::shared_ptr<const Type> lhs, std::shared_ptr<const Type> rhs){
    if(lhs->is_array()){
        return rhs->is_array() && lhs->data_type() == rhs->data_type() ;//&& lhs->elements() == rhs->elements();
    }

    if(lhs->is_pointer()){
        return rhs->is_pointer() && lhs->data_type() == rhs->data_type();
    }

    if(lhs->is_custom_type()){
        return rhs->is_custom_type() && lhs->type() == rhs->type();
    }

    if(lhs->is_standard_type()){
        return rhs->is_standard_type() && lhs->base() == rhs->base();
    }

    if(lhs->is_template_type()){
        if(rhs->is_template_type() && lhs->type() == rhs->type()){
            return lhs->template_types() == rhs->template_types();
        }
    }

    return false;
}

bool eddic::operator!=(std::shared_ptr<const Type> lhs, std::shared_ptr<const Type> rhs){
    return !(lhs == rhs);
}

/* Implementation of StandardType  */

StandardType::StandardType(BaseType type, bool const_) : base_type(type), const_(const_) {}

BaseType StandardType::base() const {
    return base_type;
}

bool StandardType::is_standard_type() const {
    return true;
}

bool StandardType::is_const() const {
    return const_;
}

unsigned int StandardType::size(Platform platform) const {
    auto descriptor = getPlatformDescriptor(platform);
    return descriptor->size_of(base());
}

/* Implementation of CustomType */

CustomType::CustomType(std::shared_ptr<GlobalContext> context, const std::string& type) :
    context(context), m_type(type) {}

std::string CustomType::type() const {
    return m_type;
}

bool CustomType::is_custom_type() const {
    return true;
}

unsigned int CustomType::size(Platform) const {
    return context->total_size_of_struct(context->get_struct(shared_from_this()));
}

/* Implementation of ArrayType  */

ArrayType::ArrayType(std::shared_ptr<const Type> sub_type) : sub_type(sub_type) {}
ArrayType::ArrayType(std::shared_ptr<const Type> sub_type, int size) : sub_type(sub_type), m_elements(size) {}

unsigned int ArrayType::elements() const {
    assert(has_elements());

    return *m_elements;
}

bool ArrayType::has_elements() const {
    return static_cast<bool>(m_elements);
}

std::shared_ptr<const Type> ArrayType::data_type() const {
    return sub_type;
}

bool ArrayType::is_array() const {
    return true;
}

unsigned int ArrayType::size(Platform platform) const {
    if(has_elements()){
        return data_type()->size(platform) * elements() + INT->size(platform);
    } else {
        return INT->size(platform);
    }
}

/* Implementation of PointerType  */

PointerType::PointerType(std::shared_ptr<const Type> sub_type) : sub_type(sub_type) {}

std::shared_ptr<const Type> PointerType::data_type() const {
    return sub_type;
}

bool PointerType::is_pointer() const {
    return true;
}

unsigned int PointerType::size(Platform platform) const {
    return INT->size(platform);
}

/* Implementation of TemplateType  */

TemplateType::TemplateType(std::shared_ptr<GlobalContext> context, std::string main_type, std::vector<std::shared_ptr<const Type>> sub_types) :
    context(context), main_type(main_type), sub_types(sub_types) {}

std::string TemplateType::type() const {
    return main_type;
}

std::vector<std::shared_ptr<const Type>> TemplateType::template_types() const {
    return sub_types;
}

bool TemplateType::is_template_type() const {
    return true;
}

unsigned int TemplateType::size(Platform) const {
    return context->total_size_of_struct(context->get_struct(shared_from_this()));
}

/* Implementation of factories  */

std::shared_ptr<const Type> eddic::new_type(std::shared_ptr<GlobalContext> context, const std::string& type, bool const_){
    //Parse standard and custom types
    if(is_standard_type(type)){
        if(const_){
            if (type == "int") {
                return CINT;
            } else if (type == "char") {
                return CCHAR;
            } else if (type == "bool") {
                return CBOOL;
            } else if (type == "float"){
                return CFLOAT;
            } else if (type == "str"){
                return CSTRING;
            } else {
                return CVOID;
            }
        } else {
            if (type == "int") {
                return INT;
            } else if (type == "char") {
                return CHAR;
            } else if (type == "bool") {
                return BOOL;
            } else if (type == "float"){
                return FLOAT;
            } else if (type == "str"){
                return STRING;
            } else {
                return VOID;
            }
        }
    } else {
        assert(!const_);
        return std::make_shared<CustomType>(context, type);
    }
}

std::shared_ptr<const Type> eddic::new_array_type(std::shared_ptr<const Type> data_type){
    return std::make_shared<ArrayType>(data_type);
}

std::shared_ptr<const Type> eddic::new_array_type(std::shared_ptr<const Type> data_type, int size){
    return std::make_shared<ArrayType>(data_type, size);
}

std::shared_ptr<const Type> eddic::new_pointer_type(std::shared_ptr<const Type> data_type){
    return std::make_shared<PointerType>(data_type);
}

std::shared_ptr<const Type> eddic::new_template_type(std::shared_ptr<GlobalContext> context, std::string data_type, std::vector<std::shared_ptr<const Type>> template_types){
    return std::make_shared<TemplateType>(context, data_type, template_types);
}

bool eddic::is_standard_type(const std::string& type){
    return type == "int" || type == "char" || type == "void" || type == "str" || type == "bool" || type == "float";
}
<|endoftext|>


<commit_before>#include "types.h"
#include "mmu.h"
#include "kernel.hh"
#include "spinlock.hh"
#include "condvar.hh"
#include "proc.hh"
#include "fs.h"
#include "file.hh"
#include "cpu.hh"
#include "uk/unistd.h"
#include "uk/fcntl.h"

#define PIPESIZE (16*4096)

struct pipe {
  virtual ~pipe() { };
  virtual int write(const char *addr, int n) = 0;
  virtual int read(char *addr, int n) = 0;
  virtual int close(int writable) = 0;
  NEW_DELETE_OPS(pipe);
};

struct ordered : pipe {
  struct spinlock lock;
  struct spinlock lock_close;
  struct condvar  empty;
  struct condvar  full;
  int readopen;   // read fd is still open
  int writeopen;  // write fd is still open
  std::atomic<size_t> nread;  // number of bytes read
  std::atomic<size_t> nwrite; // number of bytes written
  bool nonblock;
  char data[PIPESIZE];

  ordered(int flags)
    : readopen(1), writeopen(1), nread(0), nwrite(0),
      nonblock(flags & O_NONBLOCK)
  {
    lock = spinlock("pipe", LOCKSTAT_PIPE);
    lock_close = spinlock("pipe:close", LOCKSTAT_PIPE);
    empty = condvar("pipe:empty");
    full = condvar("pipe:full");
  };
  ~ordered() override {
  };
  NEW_DELETE_OPS(ordered);

  virtual int write(const char *addr, int n) override {
    if (nonblock) {
      for (;;) {
        size_t nr = nread;
        size_t nw = nwrite;
        if (nr == nread) {
          // use nread sort-of like a seqlock
          if (nw == nr + PIPESIZE)
            return -1;
          break;
        }
      }
    }

    scoped_acquire l(&lock);
    for(int i = 0; i < n; i++){
      while(nwrite == nread + PIPESIZE){
        if (nonblock || myproc()->killed)
          return -1;
        scoped_acquire lclose(&lock_close);
        if (readopen == 0)
          return -1;
        full.sleep(&lock, &lock_close);
      }
      data[nwrite++ % PIPESIZE] = addr[i];
    }
    if (n > 0)
      empty.wake_all();
    return n;
  }

  virtual int read(char *addr, int n) override {
    if (nonblock) {
      for (;;) {
        size_t nr = nread;
        size_t nw = nwrite;
        if (nr == nread) {
          // use nread sort-of like a seqlock
          if (nw == nr)
            return -1;
          break;
        }
      }
    }

    scoped_acquire l(&lock);
    while(nread == nwrite) {
      if (nonblock || myproc()->killed)
        return -1;
      scoped_acquire lclose(&lock_close);
      if (writeopen == 0)
        return 0;
      empty.sleep(&lock, &lock_close);
    }
    int i;
    for(i = 0; i < n; i++) {
      if(nread == nwrite)
        break;
      addr[i] = data[nread++ % PIPESIZE];
    }
    if (i > 0)
      full.wake_all();
    return i;
  }

  virtual int close(int writable) override {
    scoped_acquire l(&lock_close);
    if(writable){
      writeopen = 0;
    } else {
      readopen = 0;
    }
    empty.wake_all();
    if(readopen == 0 && writeopen == 0){
      return 1;
    }
    return 0;
  }
};

int
pipealloc(sref<file> *f0, sref<file> *f1, int flags)
{
  struct pipe *p = nullptr;
  auto cleanup = scoped_cleanup([&](){delete p;});
  try {
    p = new ordered(flags);
    *f0 = make_sref<file_pipe_reader>(p);
    *f1 = make_sref<file_pipe_writer>(p);
  } catch (std::bad_alloc &e) {
    return -1;
  }
  cleanup.dismiss();
  return 0;
}

void
pipeclose(struct pipe *p, int writable)
{
  if (p->close(writable))
    delete p;
}

int
pipewrite(struct pipe *p, const char *addr, int n)
{
  return p->write(addr, n);
}

int
piperead(struct pipe *p, char *addr, int n)
{
  return p->read(addr, n);
}
<commit_msg>pipe: Verify readopen before locking<commit_after>#include "types.h"
#include "mmu.h"
#include "kernel.hh"
#include "spinlock.hh"
#include "condvar.hh"
#include "proc.hh"
#include "fs.h"
#include "file.hh"
#include "cpu.hh"
#include "uk/unistd.h"
#include "uk/fcntl.h"

#define PIPESIZE (16*4096)

struct pipe {
  virtual ~pipe() { };
  virtual int write(const char *addr, int n) = 0;
  virtual int read(char *addr, int n) = 0;
  virtual int close(int writable) = 0;
  NEW_DELETE_OPS(pipe);
};

struct ordered : pipe {
  struct spinlock lock;
  struct spinlock lock_close;
  struct condvar  empty;
  struct condvar  full;
  std::atomic<bool> readopen;   // read fd is still open
  int writeopen;  // write fd is still open
  std::atomic<size_t> nread;  // number of bytes read
  std::atomic<size_t> nwrite; // number of bytes written
  bool nonblock;
  char data[PIPESIZE];

  ordered(int flags)
    : readopen(true), writeopen(1), nread(0), nwrite(0),
      nonblock(flags & O_NONBLOCK)
  {
    lock = spinlock("pipe", LOCKSTAT_PIPE);
    lock_close = spinlock("pipe:close", LOCKSTAT_PIPE);
    empty = condvar("pipe:empty");
    full = condvar("pipe:full");
  };
  ~ordered() override {
  };
  NEW_DELETE_OPS(ordered);

  virtual int write(const char *addr, int n) override {
    if (nonblock) {
      for (;;) {
        size_t nr = nread;
        size_t nw = nwrite;
        if (nr == nread) {
          // use nread sort-of like a seqlock
          if (nw == nr + PIPESIZE)
            return -1;
          break;
        }
      }
    }

    if (!readopen)
      return -1;

    scoped_acquire l(&lock);
    for(int i = 0; i < n; i++){
      while(nwrite == nread + PIPESIZE){
        if (nonblock || myproc()->killed)
          return -1;
        scoped_acquire lclose(&lock_close);
        if (!readopen)
          return -1;
        full.sleep(&lock, &lock_close);
      }
      data[nwrite++ % PIPESIZE] = addr[i];
    }
    if (n > 0)
      empty.wake_all();
    return n;
  }

  virtual int read(char *addr, int n) override {
    if (nonblock) {
      for (;;) {
        size_t nr = nread;
        size_t nw = nwrite;
        if (nr == nread) {
          // use nread sort-of like a seqlock
          if (nw == nr)
            return -1;
          break;
        }
      }
    }

    scoped_acquire l(&lock);
    while(nread == nwrite) {
      if (nonblock || myproc()->killed)
        return -1;
      scoped_acquire lclose(&lock_close);
      if (writeopen == 0)
        return 0;
      empty.sleep(&lock, &lock_close);
    }
    int i;
    for(i = 0; i < n; i++) {
      if(nread == nwrite)
        break;
      addr[i] = data[nread++ % PIPESIZE];
    }
    if (i > 0)
      full.wake_all();
    return i;
  }

  virtual int close(int writable) override {
    scoped_acquire l(&lock_close);
    if(writable){
      writeopen = 0;
    } else {
      readopen = 0;
    }
    empty.wake_all();
    if(readopen == 0 && writeopen == 0){
      return 1;
    }
    return 0;
  }
};

int
pipealloc(sref<file> *f0, sref<file> *f1, int flags)
{
  struct pipe *p = nullptr;
  auto cleanup = scoped_cleanup([&](){delete p;});
  try {
    p = new ordered(flags);
    *f0 = make_sref<file_pipe_reader>(p);
    *f1 = make_sref<file_pipe_writer>(p);
  } catch (std::bad_alloc &e) {
    return -1;
  }
  cleanup.dismiss();
  return 0;
}

void
pipeclose(struct pipe *p, int writable)
{
  if (p->close(writable))
    delete p;
}

int
pipewrite(struct pipe *p, const char *addr, int n)
{
  return p->write(addr, n);
}

int
piperead(struct pipe *p, char *addr, int n)
{
  return p->read(addr, n);
}
<|endoftext|>