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

#include <vector>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/stringprintf.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_install_dialog.h"
#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_webstore_private_api.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/gpu/gpu_blacklist.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "net/base/mock_host_resolver.h"
#include "ui/gfx/gl/gl_switches.h"

using namespace extension_function_test_utils;

namespace {

class WebstoreInstallListener : public WebstoreInstaller::Delegate {
 public:
  WebstoreInstallListener()
      : received_failure_(false), received_success_(false), waiting_(false) {}

  void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
  void OnExtensionInstallFailure(const std::string& id,
                                 const std::string& error) OVERRIDE;
  void Wait();

  bool received_failure() const { return received_failure_; }
  bool received_success() const { return received_success_; }
  const std::string& id() const { return id_; }
  const std::string& error() const { return error_; }

 private:
  bool received_failure_;
  bool received_success_;
  bool waiting_;
  std::string id_;
  std::string error_;
};

void WebstoreInstallListener::OnExtensionInstallSuccess(const std::string& id) {
  received_success_ = true;
  id_ = id;

  if (waiting_) {
    waiting_ = false;
    MessageLoopForUI::current()->Quit();
  }
}

void WebstoreInstallListener::OnExtensionInstallFailure(
    const std::string& id, const std::string& error) {
  received_failure_ = true;
  id_ = id;
  error_ = error;

  if (waiting_) {
    waiting_ = false;
    MessageLoopForUI::current()->Quit();
  }
}

void WebstoreInstallListener::Wait() {
  if (received_success_ || received_failure_)
    return;

  waiting_ = true;
  ui_test_utils::RunMessageLoop();
}

}  // namespace

// A base class for tests below.
class ExtensionWebstorePrivateApiTest : public ExtensionApiTest {
 public:
  void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(
        switches::kAppsGalleryURL, "http://www.example.com");
    command_line->AppendSwitchASCII(
        switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
  }

  void SetUpInProcessBrowserTestFixture() OVERRIDE {
    // Start up the test server and get us ready for calling the install
    // API functions.
    host_resolver()->AddRule("www.example.com", "127.0.0.1");
    ASSERT_TRUE(test_server()->Start());
    ExtensionInstallUI::DisableFailureUIForTests();
  }

 protected:
  // Returns a test server URL, but with host 'www.example.com' so it matches
  // the web store app's extent that we set up via command line flags.
  GURL GetTestServerURL(const std::string& path) {
    GURL url = test_server()->GetURL(
        std::string("files/extensions/api_test/webstore_private/") + path);

    // Replace the host with 'www.example.com' so it matches the web store
    // app's extent.
    GURL::Replacements replace_host;
    std::string host_str("www.example.com");
    replace_host.SetHostStr(host_str);

    return url.ReplaceComponents(replace_host);
  }

  // Navigates to |page| and runs the Extension API test there. Any downloads
  // of extensions will return the contents of |crx_file|.
  bool RunInstallTest(const std::string& page, const std::string& crx_file) {
    GURL crx_url = GetTestServerURL(crx_file);
    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kAppsGalleryUpdateURL, crx_url.spec());

    GURL page_url = GetTestServerURL(page);
    return RunPageTest(page_url.spec());
  }

  ExtensionService* service() {
    return browser()->profile()->GetExtensionService();
  }
};

class ExtensionWebstorePrivateBundleTest
    : public ExtensionWebstorePrivateApiTest {
 public:
  void SetUpInProcessBrowserTestFixture() OVERRIDE {
    ExtensionWebstorePrivateApiTest::SetUpInProcessBrowserTestFixture();

    // The test server needs to have already started, so setup the switch here
    // rather than in SetUpCommandLine.
    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kAppsGalleryDownloadURL,
        GetTestServerURL("bundle/%s.crx").spec());

    PackCRX("begfmnajjkbjdgmffnjaojchoncnmngg");
    PackCRX("bmfoocgfinpmkmlbjhcbofejhkhlbchk");
    PackCRX("mpneghmdnmaolkljkipbhaienajcflfe");
  }

  void TearDownInProcessBrowserTestFixture() OVERRIDE {
    ExtensionWebstorePrivateApiTest::TearDownInProcessBrowserTestFixture();
    for (size_t i = 0; i < test_crx_.size(); ++i)
      ASSERT_TRUE(file_util::Delete(test_crx_[i], false));
  }

 private:
  void PackCRX(const std::string& id) {
    FilePath data_path = test_data_dir_.AppendASCII("webstore_private/bundle");
    FilePath dir_path = data_path.AppendASCII(id);
    FilePath pem_path = data_path.AppendASCII(id + ".pem");
    FilePath crx_path = data_path.AppendASCII(id + ".crx");
    FilePath destination = PackExtensionWithOptions(
        dir_path, crx_path, pem_path, FilePath());

    ASSERT_FALSE(destination.empty());
    ASSERT_EQ(destination, crx_path);

    test_crx_.push_back(destination);
  }

  std::vector<FilePath> test_crx_;
};

class ExtensionWebstoreGetWebGLStatusTest : public InProcessBrowserTest {
 public:
  void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    // In linux, we need to launch GPU process to decide if WebGL is allowed.
    // Run it on top of osmesa to avoid bot driver issues.
#if defined(OS_LINUX)
    CHECK(test_launcher_utils::OverrideGLImplementation(
        command_line, gfx::kGLImplementationOSMesaName)) <<
        "kUseGL must not be set multiple times!";
#endif
  }

 protected:
  void RunTest(bool webgl_allowed) {
    static const char kEmptyArgs[] = "[]";
    static const char kWebGLStatusAllowed[] = "webgl_allowed";
    static const char kWebGLStatusBlocked[] = "webgl_blocked";
    scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
            new GetWebGLStatusFunction(), kEmptyArgs, browser()));
    EXPECT_EQ(base::Value::TYPE_STRING, result->GetType());
    StringValue* value = static_cast<StringValue*>(result.get());
    std::string webgl_status = "";
    EXPECT_TRUE(value && value->GetAsString(&webgl_status));
    EXPECT_STREQ(webgl_allowed ? kWebGLStatusAllowed : kWebGLStatusBlocked,
                 webgl_status.c_str());
  }
};

// Test cases where the user accepts the install confirmation dialog.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallAccepted) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath temp_path = temp_dir.path();
  WebstoreInstaller::SetDownloadDirectoryForTests(&temp_path);

  ASSERT_TRUE(RunInstallTest("accepted.html", "extension.crx"));
}

// Test having the default download directory missing.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, MissingDownloadDir) {
  // Set a non-existent directory as the download path.
  ScopedTempDir temp_dir;
  EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath missing_directory = temp_dir.Take();
  EXPECT_TRUE(file_util::Delete(missing_directory, true));
  WebstoreInstaller::SetDownloadDirectoryForTests(&missing_directory);

  // Now run the install test, which should succeed.
  ASSERT_TRUE(RunInstallTest("accepted.html", "extension.crx"));

  // Cleanup.
  if (file_util::DirectoryExists(missing_directory))
    EXPECT_TRUE(file_util::Delete(missing_directory, true));
}

// Tests passing a localized name.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallLocalized) {
  ASSERT_TRUE(RunInstallTest("localized.html", "localized_extension.crx"));
}

// Now test the case where the user cancels the confirmation dialog.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallCancelled) {
  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
      switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
  ASSERT_TRUE(RunInstallTest("cancelled.html", "extension.crx"));
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest1) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath temp_path = temp_dir.path();
  WebstoreInstaller::SetDownloadDirectoryForTests(&temp_path);

  WebstoreInstallListener listener;
  WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
  ASSERT_TRUE(RunInstallTest("incorrect_manifest1.html", "extension.crx"));
  listener.Wait();
  ASSERT_TRUE(listener.received_failure());
  ASSERT_EQ("Manifest file is invalid.", listener.error());
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest2) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath temp_path = temp_dir.path();
  WebstoreInstaller::SetDownloadDirectoryForTests(&temp_path);

  WebstoreInstallListener listener;
  WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
  ASSERT_TRUE(RunInstallTest("incorrect_manifest2.html", "extension.crx"));
  listener.Wait();
  EXPECT_TRUE(listener.received_failure());
  ASSERT_EQ("Manifest file is invalid.", listener.error());
}

// Tests that we can request an app installed bubble (instead of the default
// UI when an app is installed).
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       AppInstallBubble) {
  WebstoreInstallListener listener;
  WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
  ASSERT_TRUE(RunInstallTest("app_install_bubble.html", "app.crx"));
  listener.Wait();
  ASSERT_TRUE(listener.received_success());
  ASSERT_EQ("iladmdjkfniedhfhcfoefgojhgaiaccc", listener.id());
}

// Tests using the iconUrl parameter to the install function.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IconUrl) {
  ASSERT_TRUE(RunInstallTest("icon_url.html", "extension.crx"));
}

// Tests using silentlyInstall to install extensions.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateBundleTest, SilentlyInstall) {
  WebstorePrivateApi::SetTrustTestIDsForTesting(true);
  ASSERT_TRUE(RunPageTest(GetTestServerURL("silently_install.html").spec()));
}

// Tests getWebGLStatus function when WebGL is allowed.
IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Allowed) {
  bool webgl_allowed = true;
  RunTest(webgl_allowed);
}

// Tests getWebGLStatus function when WebGL is blacklisted.
IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Blocked) {
  static const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"webgl\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  scoped_ptr<Version> os_version(Version::GetVersionFromString("1.0"));
  GpuBlacklist* blacklist = new GpuBlacklist("1.0");

  ASSERT_TRUE(blacklist->LoadGpuBlacklist(
      json_blacklist, GpuBlacklist::kAllOs));
  GpuDataManager::GetInstance()->SetGpuBlacklist(blacklist);
  GpuFeatureFlags flags = GpuDataManager::GetInstance()->GetGpuFeatureFlags();
  EXPECT_EQ(
      flags.flags(), static_cast<uint32>(GpuFeatureFlags::kGpuFeatureWebgl));

  bool webgl_allowed = false;
  RunTest(webgl_allowed);
}
<commit_msg>Mark  - ExtensionWebstorePrivateApiTest.AppInstallBubble,  - ExtensionWebstorePrivateApiTest.InstallLocalized,  - ExtensionWebstorePrivateApiTest.SilentlyInstall as flaky.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/stringprintf.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_install_dialog.h"
#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_webstore_private_api.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/gpu/gpu_blacklist.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "net/base/mock_host_resolver.h"
#include "ui/gfx/gl/gl_switches.h"

using namespace extension_function_test_utils;

namespace {

class WebstoreInstallListener : public WebstoreInstaller::Delegate {
 public:
  WebstoreInstallListener()
      : received_failure_(false), received_success_(false), waiting_(false) {}

  void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
  void OnExtensionInstallFailure(const std::string& id,
                                 const std::string& error) OVERRIDE;
  void Wait();

  bool received_failure() const { return received_failure_; }
  bool received_success() const { return received_success_; }
  const std::string& id() const { return id_; }
  const std::string& error() const { return error_; }

 private:
  bool received_failure_;
  bool received_success_;
  bool waiting_;
  std::string id_;
  std::string error_;
};

void WebstoreInstallListener::OnExtensionInstallSuccess(const std::string& id) {
  received_success_ = true;
  id_ = id;

  if (waiting_) {
    waiting_ = false;
    MessageLoopForUI::current()->Quit();
  }
}

void WebstoreInstallListener::OnExtensionInstallFailure(
    const std::string& id, const std::string& error) {
  received_failure_ = true;
  id_ = id;
  error_ = error;

  if (waiting_) {
    waiting_ = false;
    MessageLoopForUI::current()->Quit();
  }
}

void WebstoreInstallListener::Wait() {
  if (received_success_ || received_failure_)
    return;

  waiting_ = true;
  ui_test_utils::RunMessageLoop();
}

}  // namespace

// A base class for tests below.
class ExtensionWebstorePrivateApiTest : public ExtensionApiTest {
 public:
  void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(
        switches::kAppsGalleryURL, "http://www.example.com");
    command_line->AppendSwitchASCII(
        switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
  }

  void SetUpInProcessBrowserTestFixture() OVERRIDE {
    // Start up the test server and get us ready for calling the install
    // API functions.
    host_resolver()->AddRule("www.example.com", "127.0.0.1");
    ASSERT_TRUE(test_server()->Start());
    ExtensionInstallUI::DisableFailureUIForTests();
  }

 protected:
  // Returns a test server URL, but with host 'www.example.com' so it matches
  // the web store app's extent that we set up via command line flags.
  GURL GetTestServerURL(const std::string& path) {
    GURL url = test_server()->GetURL(
        std::string("files/extensions/api_test/webstore_private/") + path);

    // Replace the host with 'www.example.com' so it matches the web store
    // app's extent.
    GURL::Replacements replace_host;
    std::string host_str("www.example.com");
    replace_host.SetHostStr(host_str);

    return url.ReplaceComponents(replace_host);
  }

  // Navigates to |page| and runs the Extension API test there. Any downloads
  // of extensions will return the contents of |crx_file|.
  bool RunInstallTest(const std::string& page, const std::string& crx_file) {
    GURL crx_url = GetTestServerURL(crx_file);
    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kAppsGalleryUpdateURL, crx_url.spec());

    GURL page_url = GetTestServerURL(page);
    return RunPageTest(page_url.spec());
  }

  ExtensionService* service() {
    return browser()->profile()->GetExtensionService();
  }
};

class ExtensionWebstorePrivateBundleTest
    : public ExtensionWebstorePrivateApiTest {
 public:
  void SetUpInProcessBrowserTestFixture() OVERRIDE {
    ExtensionWebstorePrivateApiTest::SetUpInProcessBrowserTestFixture();

    // The test server needs to have already started, so setup the switch here
    // rather than in SetUpCommandLine.
    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kAppsGalleryDownloadURL,
        GetTestServerURL("bundle/%s.crx").spec());

    PackCRX("begfmnajjkbjdgmffnjaojchoncnmngg");
    PackCRX("bmfoocgfinpmkmlbjhcbofejhkhlbchk");
    PackCRX("mpneghmdnmaolkljkipbhaienajcflfe");
  }

  void TearDownInProcessBrowserTestFixture() OVERRIDE {
    ExtensionWebstorePrivateApiTest::TearDownInProcessBrowserTestFixture();
    for (size_t i = 0; i < test_crx_.size(); ++i)
      ASSERT_TRUE(file_util::Delete(test_crx_[i], false));
  }

 private:
  void PackCRX(const std::string& id) {
    FilePath data_path = test_data_dir_.AppendASCII("webstore_private/bundle");
    FilePath dir_path = data_path.AppendASCII(id);
    FilePath pem_path = data_path.AppendASCII(id + ".pem");
    FilePath crx_path = data_path.AppendASCII(id + ".crx");
    FilePath destination = PackExtensionWithOptions(
        dir_path, crx_path, pem_path, FilePath());

    ASSERT_FALSE(destination.empty());
    ASSERT_EQ(destination, crx_path);

    test_crx_.push_back(destination);
  }

  std::vector<FilePath> test_crx_;
};

class ExtensionWebstoreGetWebGLStatusTest : public InProcessBrowserTest {
 public:
  void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    // In linux, we need to launch GPU process to decide if WebGL is allowed.
    // Run it on top of osmesa to avoid bot driver issues.
#if defined(OS_LINUX)
    CHECK(test_launcher_utils::OverrideGLImplementation(
        command_line, gfx::kGLImplementationOSMesaName)) <<
        "kUseGL must not be set multiple times!";
#endif
  }

 protected:
  void RunTest(bool webgl_allowed) {
    static const char kEmptyArgs[] = "[]";
    static const char kWebGLStatusAllowed[] = "webgl_allowed";
    static const char kWebGLStatusBlocked[] = "webgl_blocked";
    scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
            new GetWebGLStatusFunction(), kEmptyArgs, browser()));
    EXPECT_EQ(base::Value::TYPE_STRING, result->GetType());
    StringValue* value = static_cast<StringValue*>(result.get());
    std::string webgl_status = "";
    EXPECT_TRUE(value && value->GetAsString(&webgl_status));
    EXPECT_STREQ(webgl_allowed ? kWebGLStatusAllowed : kWebGLStatusBlocked,
                 webgl_status.c_str());
  }
};

// Test cases where the user accepts the install confirmation dialog.
//
// flaky: http://crbug.com/111308
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, FLAKY_InstallAccepted) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath temp_path = temp_dir.path();
  WebstoreInstaller::SetDownloadDirectoryForTests(&temp_path);

  ASSERT_TRUE(RunInstallTest("accepted.html", "extension.crx"));
}

// Test having the default download directory missing.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, MissingDownloadDir) {
  // Set a non-existent directory as the download path.
  ScopedTempDir temp_dir;
  EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath missing_directory = temp_dir.Take();
  EXPECT_TRUE(file_util::Delete(missing_directory, true));
  WebstoreInstaller::SetDownloadDirectoryForTests(&missing_directory);

  // Now run the install test, which should succeed.
  ASSERT_TRUE(RunInstallTest("accepted.html", "extension.crx"));

  // Cleanup.
  if (file_util::DirectoryExists(missing_directory))
    EXPECT_TRUE(file_util::Delete(missing_directory, true));
}

// Tests passing a localized name.
//
// flaky: http://crbug.com/111308
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       FLAKY_InstallLocalized) {
  ASSERT_TRUE(RunInstallTest("localized.html", "localized_extension.crx"));
}

// Now test the case where the user cancels the confirmation dialog.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallCancelled) {
  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
      switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
  ASSERT_TRUE(RunInstallTest("cancelled.html", "extension.crx"));
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest1) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath temp_path = temp_dir.path();
  WebstoreInstaller::SetDownloadDirectoryForTests(&temp_path);

  WebstoreInstallListener listener;
  WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
  ASSERT_TRUE(RunInstallTest("incorrect_manifest1.html", "extension.crx"));
  listener.Wait();
  ASSERT_TRUE(listener.received_failure());
  ASSERT_EQ("Manifest file is invalid.", listener.error());
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest2) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath temp_path = temp_dir.path();
  WebstoreInstaller::SetDownloadDirectoryForTests(&temp_path);

  WebstoreInstallListener listener;
  WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
  ASSERT_TRUE(RunInstallTest("incorrect_manifest2.html", "extension.crx"));
  listener.Wait();
  EXPECT_TRUE(listener.received_failure());
  ASSERT_EQ("Manifest file is invalid.", listener.error());
}

// Tests that we can request an app installed bubble (instead of the default
// UI when an app is installed).
//
// flaky: http://crbug.com/111308
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       FLAKY_AppInstallBubble) {
  WebstoreInstallListener listener;
  WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
  ASSERT_TRUE(RunInstallTest("app_install_bubble.html", "app.crx"));
  listener.Wait();
  ASSERT_TRUE(listener.received_success());
  ASSERT_EQ("iladmdjkfniedhfhcfoefgojhgaiaccc", listener.id());
}

// Tests using the iconUrl parameter to the install function.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IconUrl) {
  ASSERT_TRUE(RunInstallTest("icon_url.html", "extension.crx"));
}

// Tests using silentlyInstall to install extensions.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateBundleTest, SilentlyInstall) {
  WebstorePrivateApi::SetTrustTestIDsForTesting(true);
  ASSERT_TRUE(RunPageTest(GetTestServerURL("silently_install.html").spec()));
}

// Tests getWebGLStatus function when WebGL is allowed.
IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Allowed) {
  bool webgl_allowed = true;
  RunTest(webgl_allowed);
}

// Tests getWebGLStatus function when WebGL is blacklisted.
IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Blocked) {
  static const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"webgl\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  scoped_ptr<Version> os_version(Version::GetVersionFromString("1.0"));
  GpuBlacklist* blacklist = new GpuBlacklist("1.0");

  ASSERT_TRUE(blacklist->LoadGpuBlacklist(
      json_blacklist, GpuBlacklist::kAllOs));
  GpuDataManager::GetInstance()->SetGpuBlacklist(blacklist);
  GpuFeatureFlags flags = GpuDataManager::GetInstance()->GetGpuFeatureFlags();
  EXPECT_EQ(
      flags.flags(), static_cast<uint32>(GpuFeatureFlags::kGpuFeatureWebgl));

  bool webgl_allowed = false;
  RunTest(webgl_allowed);
}
<|endoftext|>


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

#include "chrome/browser/sync/notifier/communicator/ssl_socket_adapter.h"

#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/profile.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_config_service.h"
#include "net/base/sys_addrinfo.h"
#include "net/socket/client_socket_factory.h"
#include "net/url_request/url_request_context.h"

namespace notifier {

namespace {

// Convert values from <errno.h> to values from "net/base/net_errors.h"
int MapPosixError(int err) {
  // There are numerous posix error codes, but these are the ones we thus far
  // find interesting.
  switch (err) {
    case EAGAIN:
#if EWOULDBLOCK != EAGAIN
    case EWOULDBLOCK:
#endif
      return net::ERR_IO_PENDING;
    case ENETDOWN:
      return net::ERR_INTERNET_DISCONNECTED;
    case ETIMEDOUT:
      return net::ERR_TIMED_OUT;
    case ECONNRESET:
    case ENETRESET:  // Related to keep-alive
      return net::ERR_CONNECTION_RESET;
    case ECONNABORTED:
      return net::ERR_CONNECTION_ABORTED;
    case ECONNREFUSED:
      return net::ERR_CONNECTION_REFUSED;
    case EHOSTUNREACH:
    case ENETUNREACH:
      return net::ERR_ADDRESS_UNREACHABLE;
    case EADDRNOTAVAIL:
      return net::ERR_ADDRESS_INVALID;
    case 0:
      return net::OK;
    default:
      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
      return net::ERR_FAILED;
  }
}

}  // namespace

SSLSocketAdapter* SSLSocketAdapter::Create(AsyncSocket* socket) {
  return new SSLSocketAdapter(socket);
}

SSLSocketAdapter::SSLSocketAdapter(AsyncSocket* socket)
    : SSLAdapter(socket),
      ignore_bad_cert_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(
        connected_callback_(this, &SSLSocketAdapter::OnConnected)),
      ALLOW_THIS_IN_INITIALIZER_LIST(
        io_callback_(this, &SSLSocketAdapter::OnIO)),
      ssl_connected_(false),
      state_(STATE_NONE) {
  transport_socket_ = new TransportSocket(socket, this);
}

int SSLSocketAdapter::StartSSL(const char* hostname, bool restartable) {
  DCHECK(!restartable);
  hostname_ = hostname;

  if (socket_->GetState() != Socket::CS_CONNECTED) {
    state_ = STATE_SSL_WAIT;
    return 0;
  } else {
    return BeginSSL();
  }
}

int SSLSocketAdapter::BeginSSL() {
  if (!MessageLoop::current()) {
    // Certificate verification is done via the Chrome message loop.
    // Without this check, if we don't have a chrome message loop the
    // SSL connection just hangs silently.
    LOG(DFATAL) << "Chrome message loop (needed by SSL certificate "
                << "verification) does not exist";
    return net::ERR_UNEXPECTED;
  }

  // SSLConfigService is not thread-safe, and the default values for SSLConfig
  // are correct for us, so we don't use the config service to initialize this
  // object.
  net::SSLConfig ssl_config;
  transport_socket_->set_addr(talk_base::SocketAddress(hostname_.c_str()));
  ssl_socket_.reset(
      net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
          transport_socket_, hostname_.c_str(), ssl_config));

  int result = ssl_socket_->Connect(&connected_callback_, NULL);

  if (result == net::ERR_IO_PENDING || result == net::OK) {
    return 0;
  } else {
    LOG(ERROR) << "Could not start SSL: " << net::ErrorToString(result);
    return result;
  }
}

int SSLSocketAdapter::Send(const void* buf, size_t len) {
  if (!ssl_connected_) {
    return AsyncSocketAdapter::Send(buf, len);
  } else {
    scoped_refptr<net::IOBuffer> transport_buf = new net::IOBuffer(len);
    memcpy(transport_buf->data(), buf, len);

    int result = ssl_socket_->Write(transport_buf, len, NULL);
    if (result == net::ERR_IO_PENDING) {
      SetError(EWOULDBLOCK);
    }
    transport_buf = NULL;
    return result;
  }
}

int SSLSocketAdapter::Recv(void* buf, size_t len) {
  if (!ssl_connected_) {
    return AsyncSocketAdapter::Recv(buf, len);
  }

  switch (state_) {
    case STATE_NONE: {
      transport_buf_ = new net::IOBuffer(len);
      int result = ssl_socket_->Read(transport_buf_, len, &io_callback_);
      if (result >= 0) {
        memcpy(buf, transport_buf_->data(), len);
      }

      if (result == net::ERR_IO_PENDING) {
        state_ = STATE_READ;
        SetError(EWOULDBLOCK);
      } else {
        if (result < 0) {
          SetError(result);
          LOG(INFO) << "Socket error " << result;
        }
        transport_buf_ = NULL;
      }
      return result;
    }
    case STATE_READ_COMPLETE:
      memcpy(buf, transport_buf_->data(), len);
      transport_buf_ = NULL;
      state_ = STATE_NONE;
      return data_transferred_;

    case STATE_READ:
    case STATE_WRITE:
    case STATE_WRITE_COMPLETE:
    case STATE_SSL_WAIT:
      SetError(EWOULDBLOCK);
      return -1;

    default:
      NOTREACHED();
      break;
  }
  return -1;
}

void SSLSocketAdapter::OnConnected(int result) {
  if (result == net::OK) {
    ssl_connected_ = true;
    OnConnectEvent(this);
  }
}

void SSLSocketAdapter::OnIO(int result) {
  switch (state_) {
    case STATE_READ:
      state_ = STATE_READ_COMPLETE;
      data_transferred_ = result;
      AsyncSocketAdapter::OnReadEvent(this);
      break;
    case STATE_WRITE:
      state_ = STATE_WRITE_COMPLETE;
      data_transferred_ = result;
      AsyncSocketAdapter::OnWriteEvent(this);
      break;
    case STATE_NONE:
    case STATE_READ_COMPLETE:
    case STATE_WRITE_COMPLETE:
    case STATE_SSL_WAIT:
    default:
      NOTREACHED();
      break;
  }
}

void SSLSocketAdapter::OnReadEvent(talk_base::AsyncSocket* socket) {
  if (!transport_socket_->OnReadEvent(socket))
    AsyncSocketAdapter::OnReadEvent(socket);
}

void SSLSocketAdapter::OnWriteEvent(talk_base::AsyncSocket* socket) {
  if (!transport_socket_->OnWriteEvent(socket))
    AsyncSocketAdapter::OnWriteEvent(socket);
}

void SSLSocketAdapter::OnConnectEvent(talk_base::AsyncSocket* socket) {
  if (state_ != STATE_SSL_WAIT) {
    AsyncSocketAdapter::OnConnectEvent(socket);
  } else {
    state_ = STATE_NONE;
    int result = BeginSSL();
    if (0 != result) {
      // TODO(zork): Handle this case gracefully.
      LOG(WARNING) << "BeginSSL() failed with " << result;
    }
  }
}

TransportSocket::TransportSocket(talk_base::AsyncSocket* socket,
                                 SSLSocketAdapter *ssl_adapter)
    : connect_callback_(NULL),
      read_callback_(NULL),
      write_callback_(NULL),
      read_buffer_len_(0),
      write_buffer_len_(0),
      socket_(socket) {
    socket_->SignalConnectEvent.connect(this, &TransportSocket::OnConnectEvent);
}

int TransportSocket::Connect(net::CompletionCallback* callback,
                             const net::BoundNetLog& /* net_log */) {
  connect_callback_ = callback;
  return socket_->Connect(addr_);
}

void TransportSocket::Disconnect() {
  socket_->Close();
}

bool TransportSocket::IsConnected() const {
  return (socket_->GetState() == talk_base::Socket::CS_CONNECTED);
}

bool TransportSocket::IsConnectedAndIdle() const {
  // Not implemented.
  NOTREACHED();
  return false;
}

int TransportSocket::GetPeerAddress(net::AddressList* address) const {
  talk_base::SocketAddress socket_address = socket_->GetRemoteAddress();

  // libjingle supports only IPv4 addresses.
  sockaddr_in ipv4addr;
  socket_address.ToSockAddr(&ipv4addr);

  struct addrinfo ai;
  memset(&ai, 0, sizeof(ai));
  ai.ai_family = ipv4addr.sin_family;
  ai.ai_socktype = SOCK_STREAM;
  ai.ai_protocol = IPPROTO_TCP;
  ai.ai_addr = reinterpret_cast<struct sockaddr*>(&ipv4addr);
  ai.ai_addrlen = sizeof(ipv4addr);

  address->Copy(&ai, false);
  return net::OK;
}

int TransportSocket::Read(net::IOBuffer* buf, int buf_len,
                          net::CompletionCallback* callback) {
  DCHECK(buf);
  DCHECK(!read_callback_);
  DCHECK(!read_buffer_.get());
  int result = socket_->Recv(buf->data(), buf_len);
  if (result < 0) {
    result = MapPosixError(socket_->GetError());
    if (result == net::ERR_IO_PENDING) {
      read_callback_ = callback;
      read_buffer_ = buf;
      read_buffer_len_ = buf_len;
    }
  }
  return result;
}

int TransportSocket::Write(net::IOBuffer* buf, int buf_len,
                           net::CompletionCallback* callback) {
  DCHECK(buf);
  DCHECK(!write_callback_);
  DCHECK(!write_buffer_.get());
  int result = socket_->Send(buf->data(), buf_len);
  if (result < 0) {
    result = MapPosixError(socket_->GetError());
    if (result == net::ERR_IO_PENDING) {
      write_callback_ = callback;
      write_buffer_ = buf;
      write_buffer_len_ = buf_len;
    }
  }
  return result;
}

bool TransportSocket::SetReceiveBufferSize(int32 size) {
  // Not implemented.
  return false;
}

bool TransportSocket::SetSendBufferSize(int32 size) {
  // Not implemented.
  return false;
}

void TransportSocket::OnConnectEvent(talk_base::AsyncSocket * socket) {
  if (connect_callback_) {
    net::CompletionCallback *callback = connect_callback_;
    connect_callback_ = NULL;
    callback->RunWithParams(Tuple1<int>(MapPosixError(socket_->GetError())));
  }
}

bool TransportSocket::OnReadEvent(talk_base::AsyncSocket* socket) {
  if (read_callback_) {
    DCHECK(read_buffer_.get());
    net::CompletionCallback* callback = read_callback_;
    scoped_refptr<net::IOBuffer> buffer = read_buffer_;
    int buffer_len = read_buffer_len_;

    read_callback_ = NULL;
    read_buffer_ = NULL;
    read_buffer_len_ = 0;

    int result = socket_->Recv(buffer->data(), buffer_len);
    if (result < 0) {
      result = MapPosixError(socket_->GetError());
      if (result == net::ERR_IO_PENDING) {
        read_callback_ = callback;
        read_buffer_ = buffer;
        read_buffer_len_ = buffer_len;
        return true;
      }
    }
    callback->RunWithParams(Tuple1<int>(result));
    return true;
  } else {
    return false;
  }
}

bool TransportSocket::OnWriteEvent(talk_base::AsyncSocket* socket) {
  if (write_callback_) {
    DCHECK(write_buffer_.get());
    net::CompletionCallback* callback = write_callback_;
    scoped_refptr<net::IOBuffer> buffer = write_buffer_;
    int buffer_len = write_buffer_len_;

    write_callback_ = NULL;
    write_buffer_ = NULL;
    write_buffer_len_ = 0;

    int result = socket_->Send(buffer->data(), buffer_len);
    if (result < 0) {
      result = MapPosixError(socket_->GetError());
      if (result == net::ERR_IO_PENDING) {
        write_callback_ = callback;
        write_buffer_ = buffer;
        write_buffer_len_ = buffer_len;
        return true;
      }
    }
    callback->RunWithParams(Tuple1<int>(result));
    return true;
  } else {
    return false;
  }
}

}  // namespace notifier
<commit_msg>Add logging statements to ssl_socket_adapter.cc to watch for unexpected conditions.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/notifier/communicator/ssl_socket_adapter.h"

#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/profile.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_config_service.h"
#include "net/base/sys_addrinfo.h"
#include "net/socket/client_socket_factory.h"
#include "net/url_request/url_request_context.h"

namespace notifier {

namespace {

// Convert values from <errno.h> to values from "net/base/net_errors.h"
int MapPosixError(int err) {
  // There are numerous posix error codes, but these are the ones we thus far
  // find interesting.
  switch (err) {
    case EAGAIN:
#if EWOULDBLOCK != EAGAIN
    case EWOULDBLOCK:
#endif
      return net::ERR_IO_PENDING;
    case ENETDOWN:
      return net::ERR_INTERNET_DISCONNECTED;
    case ETIMEDOUT:
      return net::ERR_TIMED_OUT;
    case ECONNRESET:
    case ENETRESET:  // Related to keep-alive
      return net::ERR_CONNECTION_RESET;
    case ECONNABORTED:
      return net::ERR_CONNECTION_ABORTED;
    case ECONNREFUSED:
      return net::ERR_CONNECTION_REFUSED;
    case EHOSTUNREACH:
    case ENETUNREACH:
      return net::ERR_ADDRESS_UNREACHABLE;
    case EADDRNOTAVAIL:
      return net::ERR_ADDRESS_INVALID;
    case 0:
      return net::OK;
    default:
      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
      return net::ERR_FAILED;
  }
}

}  // namespace

SSLSocketAdapter* SSLSocketAdapter::Create(AsyncSocket* socket) {
  return new SSLSocketAdapter(socket);
}

SSLSocketAdapter::SSLSocketAdapter(AsyncSocket* socket)
    : SSLAdapter(socket),
      ignore_bad_cert_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(
        connected_callback_(this, &SSLSocketAdapter::OnConnected)),
      ALLOW_THIS_IN_INITIALIZER_LIST(
        io_callback_(this, &SSLSocketAdapter::OnIO)),
      ssl_connected_(false),
      state_(STATE_NONE) {
  transport_socket_ = new TransportSocket(socket, this);
}

int SSLSocketAdapter::StartSSL(const char* hostname, bool restartable) {
  DCHECK(!restartable);
  hostname_ = hostname;

  if (socket_->GetState() != Socket::CS_CONNECTED) {
    state_ = STATE_SSL_WAIT;
    return 0;
  } else {
    return BeginSSL();
  }
}

int SSLSocketAdapter::BeginSSL() {
  if (!MessageLoop::current()) {
    // Certificate verification is done via the Chrome message loop.
    // Without this check, if we don't have a chrome message loop the
    // SSL connection just hangs silently.
    LOG(DFATAL) << "Chrome message loop (needed by SSL certificate "
                << "verification) does not exist";
    return net::ERR_UNEXPECTED;
  }

  // SSLConfigService is not thread-safe, and the default values for SSLConfig
  // are correct for us, so we don't use the config service to initialize this
  // object.
  net::SSLConfig ssl_config;
  transport_socket_->set_addr(talk_base::SocketAddress(hostname_.c_str()));
  ssl_socket_.reset(
      net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
          transport_socket_, hostname_.c_str(), ssl_config));

  int result = ssl_socket_->Connect(&connected_callback_, NULL);

  if (result == net::ERR_IO_PENDING || result == net::OK) {
    return 0;
  } else {
    LOG(ERROR) << "Could not start SSL: " << net::ErrorToString(result);
    return result;
  }
}

int SSLSocketAdapter::Send(const void* buf, size_t len) {
  if (!ssl_connected_) {
    return AsyncSocketAdapter::Send(buf, len);
  } else {
    scoped_refptr<net::IOBuffer> transport_buf = new net::IOBuffer(len);
    memcpy(transport_buf->data(), buf, len);

    int result = ssl_socket_->Write(transport_buf, len, NULL);
    if (result == net::ERR_IO_PENDING) {
      SetError(EWOULDBLOCK);
    }
    transport_buf = NULL;
    return result;
  }
}

int SSLSocketAdapter::Recv(void* buf, size_t len) {
  if (!ssl_connected_) {
    return AsyncSocketAdapter::Recv(buf, len);
  }

  switch (state_) {
    case STATE_NONE: {
      transport_buf_ = new net::IOBuffer(len);
      int result = ssl_socket_->Read(transport_buf_, len, &io_callback_);
      if (result >= 0) {
        memcpy(buf, transport_buf_->data(), len);
      }

      if (result == net::ERR_IO_PENDING) {
        state_ = STATE_READ;
        SetError(EWOULDBLOCK);
      } else {
        if (result < 0) {
          SetError(result);
          LOG(INFO) << "Socket error " << result;
        }
        transport_buf_ = NULL;
      }
      return result;
    }
    case STATE_READ_COMPLETE:
      memcpy(buf, transport_buf_->data(), len);
      transport_buf_ = NULL;
      state_ = STATE_NONE;
      return data_transferred_;

    case STATE_READ:
    case STATE_WRITE:
    case STATE_WRITE_COMPLETE:
    case STATE_SSL_WAIT:
      SetError(EWOULDBLOCK);
      return -1;

    default:
      NOTREACHED();
      break;
  }
  return -1;
}

void SSLSocketAdapter::OnConnected(int result) {
  if (result == net::OK) {
    ssl_connected_ = true;
    OnConnectEvent(this);
  } else {
    LOG(WARNING) << "OnConnected failed with error " << result;
  }
}

void SSLSocketAdapter::OnIO(int result) {
  switch (state_) {
    case STATE_READ:
      state_ = STATE_READ_COMPLETE;
      data_transferred_ = result;
      AsyncSocketAdapter::OnReadEvent(this);
      break;
    case STATE_WRITE:
      state_ = STATE_WRITE_COMPLETE;
      data_transferred_ = result;
      AsyncSocketAdapter::OnWriteEvent(this);
      break;
    case STATE_NONE:
    case STATE_READ_COMPLETE:
    case STATE_WRITE_COMPLETE:
    case STATE_SSL_WAIT:
    default:
      NOTREACHED();
      break;
  }
}

void SSLSocketAdapter::OnReadEvent(talk_base::AsyncSocket* socket) {
  if (!transport_socket_->OnReadEvent(socket))
    AsyncSocketAdapter::OnReadEvent(socket);
}

void SSLSocketAdapter::OnWriteEvent(talk_base::AsyncSocket* socket) {
  if (!transport_socket_->OnWriteEvent(socket))
    AsyncSocketAdapter::OnWriteEvent(socket);
}

void SSLSocketAdapter::OnConnectEvent(talk_base::AsyncSocket* socket) {
  if (state_ != STATE_SSL_WAIT) {
    AsyncSocketAdapter::OnConnectEvent(socket);
  } else {
    state_ = STATE_NONE;
    int result = BeginSSL();
    if (0 != result) {
      // TODO(zork): Handle this case gracefully.
      LOG(WARNING) << "BeginSSL() failed with " << result;
    }
  }
}

TransportSocket::TransportSocket(talk_base::AsyncSocket* socket,
                                 SSLSocketAdapter *ssl_adapter)
    : connect_callback_(NULL),
      read_callback_(NULL),
      write_callback_(NULL),
      read_buffer_len_(0),
      write_buffer_len_(0),
      socket_(socket) {
    socket_->SignalConnectEvent.connect(this, &TransportSocket::OnConnectEvent);
}

int TransportSocket::Connect(net::CompletionCallback* callback,
                             const net::BoundNetLog& /* net_log */) {
  connect_callback_ = callback;
  return socket_->Connect(addr_);
}

void TransportSocket::Disconnect() {
  socket_->Close();
}

bool TransportSocket::IsConnected() const {
  return (socket_->GetState() == talk_base::Socket::CS_CONNECTED);
}

bool TransportSocket::IsConnectedAndIdle() const {
  // Not implemented.
  NOTREACHED();
  return false;
}

int TransportSocket::GetPeerAddress(net::AddressList* address) const {
  talk_base::SocketAddress socket_address = socket_->GetRemoteAddress();

  // libjingle supports only IPv4 addresses.
  sockaddr_in ipv4addr;
  socket_address.ToSockAddr(&ipv4addr);

  struct addrinfo ai;
  memset(&ai, 0, sizeof(ai));
  ai.ai_family = ipv4addr.sin_family;
  ai.ai_socktype = SOCK_STREAM;
  ai.ai_protocol = IPPROTO_TCP;
  ai.ai_addr = reinterpret_cast<struct sockaddr*>(&ipv4addr);
  ai.ai_addrlen = sizeof(ipv4addr);

  address->Copy(&ai, false);
  return net::OK;
}

int TransportSocket::Read(net::IOBuffer* buf, int buf_len,
                          net::CompletionCallback* callback) {
  DCHECK(buf);
  DCHECK(!read_callback_);
  DCHECK(!read_buffer_.get());
  int result = socket_->Recv(buf->data(), buf_len);
  if (result < 0) {
    result = MapPosixError(socket_->GetError());
    if (result == net::ERR_IO_PENDING) {
      read_callback_ = callback;
      read_buffer_ = buf;
      read_buffer_len_ = buf_len;
    }
  }
  return result;
}

int TransportSocket::Write(net::IOBuffer* buf, int buf_len,
                           net::CompletionCallback* callback) {
  DCHECK(buf);
  DCHECK(!write_callback_);
  DCHECK(!write_buffer_.get());
  int result = socket_->Send(buf->data(), buf_len);
  if (result < 0) {
    result = MapPosixError(socket_->GetError());
    if (result == net::ERR_IO_PENDING) {
      write_callback_ = callback;
      write_buffer_ = buf;
      write_buffer_len_ = buf_len;
    }
  }
  return result;
}

bool TransportSocket::SetReceiveBufferSize(int32 size) {
  // Not implemented.
  return false;
}

bool TransportSocket::SetSendBufferSize(int32 size) {
  // Not implemented.
  return false;
}

void TransportSocket::OnConnectEvent(talk_base::AsyncSocket * socket) {
  if (connect_callback_) {
    net::CompletionCallback *callback = connect_callback_;
    connect_callback_ = NULL;
    callback->RunWithParams(Tuple1<int>(MapPosixError(socket_->GetError())));
  } else {
    LOG(WARNING) << "OnConnectEvent called with no callback.";
  }
}

bool TransportSocket::OnReadEvent(talk_base::AsyncSocket* socket) {
  if (read_callback_) {
    DCHECK(read_buffer_.get());
    net::CompletionCallback* callback = read_callback_;
    scoped_refptr<net::IOBuffer> buffer = read_buffer_;
    int buffer_len = read_buffer_len_;

    read_callback_ = NULL;
    read_buffer_ = NULL;
    read_buffer_len_ = 0;

    int result = socket_->Recv(buffer->data(), buffer_len);
    if (result < 0) {
      result = MapPosixError(socket_->GetError());
      if (result == net::ERR_IO_PENDING) {
        read_callback_ = callback;
        read_buffer_ = buffer;
        read_buffer_len_ = buffer_len;
        return true;
      }
    }
    callback->RunWithParams(Tuple1<int>(result));
    return true;
  } else {
    LOG(WARNING) << "OnReadEvent called with no callback.";
    return false;
  }
}

bool TransportSocket::OnWriteEvent(talk_base::AsyncSocket* socket) {
  if (write_callback_) {
    DCHECK(write_buffer_.get());
    net::CompletionCallback* callback = write_callback_;
    scoped_refptr<net::IOBuffer> buffer = write_buffer_;
    int buffer_len = write_buffer_len_;

    write_callback_ = NULL;
    write_buffer_ = NULL;
    write_buffer_len_ = 0;

    int result = socket_->Send(buffer->data(), buffer_len);
    if (result < 0) {
      result = MapPosixError(socket_->GetError());
      if (result == net::ERR_IO_PENDING) {
        write_callback_ = callback;
        write_buffer_ = buffer;
        write_buffer_len_ = buffer_len;
        return true;
      }
    }
    callback->RunWithParams(Tuple1<int>(result));
    return true;
  } else {
    LOG(WARNING) << "OnWriteEvent called with no callback.";
    return false;
  }
}

}  // namespace notifier
<|endoftext|>


<commit_before>#include <iostream>
#include <boost/foreach.hpp>
#include <libport/package-info.hh>

namespace libport
{
  PackageInfo::PackageInfo ()
    : map_()
  {
  }

  PackageInfo::data_type
  PackageInfo::name_version_revision() const
  {
    return (get ("name")
	    + " version " + get ("version")
	    + " rev. "    + get ("revision"));
  }

  PackageInfo::data_type
  PackageInfo::signature() const
  {
    return (
      get ("name")
      + " version " + get ("version")
      + " rev. "    + get ("revision")
      + " (C) "     + get ("copyright-years")
      + " "         + get ("copyright-holder")
      );
  }

  PackageInfo::data_type&
  PackageInfo::operator[](const key_type& k)
  {
    return map_[k];
  }

  const PackageInfo::data_type&
  PackageInfo::get(const key_type& k) const
  {
    return map_.find(k)->second;
  }

  std::ostream&
  PackageInfo::dump(std::ostream& o) const
  {
    bool not_first = false;
    BOOST_FOREACH(value_type p, map_)
      o << (not_first++ ? ", " : "") << p.first << " = " << p.second;
    return o;
  }

  std::ostream&
  operator<<(std::ostream& o, const PackageInfo& p)
  {
    return o << p.signature();
  }

}
<commit_msg>Stylistic changes.<commit_after>#include <iostream>
#include <libport/foreach.hh>
#include <libport/package-info.hh>

namespace libport
{
  PackageInfo::PackageInfo ()
    : map_()
  {
  }

  PackageInfo::data_type
  PackageInfo::name_version_revision() const
  {
    return (get ("name")
	    + " version " + get ("version")
	    + " rev. "    + get ("revision"));
  }

  PackageInfo::data_type
  PackageInfo::signature() const
  {
    return (
      get ("name")
      + " version " + get ("version")
      + " rev. "    + get ("revision")
      + " (C) "     + get ("copyright-years")
      + " "         + get ("copyright-holder")
      );
  }

  PackageInfo::data_type&
  PackageInfo::operator[](const key_type& k)
  {
    return map_[k];
  }

  const PackageInfo::data_type&
  PackageInfo::get(const key_type& k) const
  {
    return map_.find(k)->second;
  }

  std::ostream&
  PackageInfo::dump(std::ostream& o) const
  {
    bool tail = false;
    foreach(value_type p, map_)
      o << (tail++ ? ", " : "") << p.first << " = " << p.second;
    return o;
  }

  std::ostream&
  operator<<(std::ostream& o, const PackageInfo& p)
  {
    return o << p.signature();
  }

}
<|endoftext|>


<commit_before>#include "dreal/contractor/contractor.h"

#include <algorithm>
#include <utility>

#include "dreal/contractor/contractor_cell.h"
#include "dreal/contractor/contractor_fixpoint.h"
#include "dreal/contractor/contractor_forall.h"
#include "dreal/contractor/contractor_ibex_fwdbwd.h"
#include "dreal/contractor/contractor_ibex_polytope.h"
#include "dreal/contractor/contractor_id.h"
#include "dreal/contractor/contractor_integer.h"
#include "dreal/contractor/contractor_join.h"
#include "dreal/contractor/contractor_seq.h"
#include "dreal/contractor/contractor_worklist_fixpoint.h"

using std::any_of;
using std::make_shared;
using std::move;
using std::ostream;
using std::shared_ptr;
using std::vector;

namespace dreal {

namespace {

// Flattens contractors and filters out ID contractors.
vector<Contractor> Flatten(const vector<Contractor>& contractors) {
  vector<Contractor> vec;
  vec.reserve(contractors.size());
  for (const Contractor& contractor : contractors) {
    const Contractor::Kind kind{contractor.kind()};
    if (kind == Contractor::Kind::ID) {
      // Skip if contractor == ID.
      continue;
    } else if (kind == Contractor::Kind::SEQ) {
      // Flatten it out if contractor == SEQ.
      const vector<Contractor>& contractors_inside{
          to_seq(contractor)->contractors()};
      vec.insert(vec.end(), contractors_inside.begin(),
                 contractors_inside.end());
    } else {
      vec.push_back(contractor);
    }
  }
  return vec;
}

}  // namespace

Contractor::Contractor() : ptr_{make_shared<ContractorId>()} {}

Contractor::Contractor(const shared_ptr<ContractorCell>& ptr) : ptr_(ptr) {}

const ibex::BitSet& Contractor::input() const { return ptr_->input(); }

void Contractor::Prune(ContractorStatus* cs) const { ptr_->Prune(cs); }

Contractor::Kind Contractor::kind() const { return ptr_->kind(); }

Contractor make_contractor_id() { return Contractor{}; }

Contractor make_contractor_integer(const Box& box) {
  if (any_of(box.variables().begin(), box.variables().end(),
             [](const Variable& v) {
               const Variable::Type type{v.get_type()};
               return type == Variable::Type::INTEGER ||
                      type == Variable::Type::BINARY;
             })) {
    return Contractor{make_shared<ContractorInteger>(box)};
  } else {
    return make_contractor_id();
  }
}

Contractor make_contractor_seq(const vector<Contractor>& contractors) {
  return Contractor{make_shared<ContractorSeq>(Flatten(contractors))};
}

Contractor make_contractor_ibex_fwdbwd(Formula f, const Box& box) {
  return Contractor{make_shared<ContractorIbexFwdbwd>(move(f), box)};
}

Contractor make_contractor_ibex_polytope(vector<Formula> formulas,
                                         const Box& box) {
  return Contractor{make_shared<ContractorIbexPolytope>(move(formulas), box)};
}

Contractor make_contractor_fixpoint(TerminationCondition term_cond,
                                    const vector<Contractor>& contractors) {
  return Contractor{
      make_shared<ContractorFixpoint>(move(term_cond), Flatten(contractors))};
}

Contractor make_contractor_worklist_fixpoint(
    TerminationCondition term_cond, const vector<Contractor>& contractors) {
  return Contractor{make_shared<ContractorWorklistFixpoint>(
      move(term_cond), Flatten(contractors))};
}

Contractor make_contractor_join(vector<Contractor> vec) {
  return Contractor{make_shared<ContractorJoin>(move(vec))};
}

ostream& operator<<(ostream& os, const Contractor& ctc) {
  if (ctc.ptr_) {
    os << *(ctc.ptr_);
  }
  return os;
}

bool is_id(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::ID;
}
bool is_integer(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::INTEGER;
}
bool is_seq(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::SEQ;
}
bool is_ibex_fwdbwd(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::IBEX_FWDBWD;
}
bool is_ibex_polytope(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::IBEX_POLYTOPE;
}
bool is_fixpoint(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::FIXPOINT;
}
bool is_worklist_fixpoint(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::WORKLIST_FIXPOINT;
}
bool is_forall(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::FORALL;
}
bool is_join(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::JOIN;
}

}  // namespace dreal
<commit_msg>feat(contractor): Add ContractorStat which shows stat info at INFO level<commit_after>#include "dreal/contractor/contractor.h"

#include <algorithm>
#include <utility>

#include "dreal/contractor/contractor_cell.h"
#include "dreal/contractor/contractor_fixpoint.h"
#include "dreal/contractor/contractor_forall.h"
#include "dreal/contractor/contractor_ibex_fwdbwd.h"
#include "dreal/contractor/contractor_ibex_polytope.h"
#include "dreal/contractor/contractor_id.h"
#include "dreal/contractor/contractor_integer.h"
#include "dreal/contractor/contractor_join.h"
#include "dreal/contractor/contractor_seq.h"
#include "dreal/contractor/contractor_worklist_fixpoint.h"

using std::any_of;
using std::make_shared;
using std::move;
using std::ostream;
using std::shared_ptr;
using std::vector;

namespace dreal {

namespace {

// Flattens contractors and filters out ID contractors.
vector<Contractor> Flatten(const vector<Contractor>& contractors) {
  vector<Contractor> vec;
  vec.reserve(contractors.size());
  for (const Contractor& contractor : contractors) {
    const Contractor::Kind kind{contractor.kind()};
    if (kind == Contractor::Kind::ID) {
      // Skip if contractor == ID.
      continue;
    } else if (kind == Contractor::Kind::SEQ) {
      // Flatten it out if contractor == SEQ.
      const vector<Contractor>& contractors_inside{
          to_seq(contractor)->contractors()};
      vec.insert(vec.end(), contractors_inside.begin(),
                 contractors_inside.end());
    } else {
      vec.push_back(contractor);
    }
  }
  return vec;
}

// A class to show statistics information at destruction. We have a
// static instance in Contractor::Prune() to keep track of the number
// of pruning operations.
class ContractorStat {
 public:
  ContractorStat() = default;
  ~ContractorStat() {
    DREAL_LOG_INFO("Total # of Pruning @ Contractor level = {}", num_prune_);
  }
  int num_prune_{0};
};

}  // namespace

Contractor::Contractor() : ptr_{make_shared<ContractorId>()} {}

Contractor::Contractor(const shared_ptr<ContractorCell>& ptr) : ptr_(ptr) {}

const ibex::BitSet& Contractor::input() const { return ptr_->input(); }

void Contractor::Prune(ContractorStatus* cs) const {
  static ContractorStat stat;
  stat.num_prune_++;
  ptr_->Prune(cs);
}

Contractor::Kind Contractor::kind() const { return ptr_->kind(); }

Contractor make_contractor_id() { return Contractor{}; }

Contractor make_contractor_integer(const Box& box) {
  if (any_of(box.variables().begin(), box.variables().end(),
             [](const Variable& v) {
               const Variable::Type type{v.get_type()};
               return type == Variable::Type::INTEGER ||
                      type == Variable::Type::BINARY;
             })) {
    return Contractor{make_shared<ContractorInteger>(box)};
  } else {
    return make_contractor_id();
  }
}

Contractor make_contractor_seq(const vector<Contractor>& contractors) {
  return Contractor{make_shared<ContractorSeq>(Flatten(contractors))};
}

Contractor make_contractor_ibex_fwdbwd(Formula f, const Box& box) {
  return Contractor{make_shared<ContractorIbexFwdbwd>(move(f), box)};
}

Contractor make_contractor_ibex_polytope(vector<Formula> formulas,
                                         const Box& box) {
  return Contractor{make_shared<ContractorIbexPolytope>(move(formulas), box)};
}

Contractor make_contractor_fixpoint(TerminationCondition term_cond,
                                    const vector<Contractor>& contractors) {
  return Contractor{
      make_shared<ContractorFixpoint>(move(term_cond), Flatten(contractors))};
}

Contractor make_contractor_worklist_fixpoint(
    TerminationCondition term_cond, const vector<Contractor>& contractors) {
  return Contractor{make_shared<ContractorWorklistFixpoint>(
      move(term_cond), Flatten(contractors))};
}

Contractor make_contractor_join(vector<Contractor> vec) {
  return Contractor{make_shared<ContractorJoin>(move(vec))};
}

ostream& operator<<(ostream& os, const Contractor& ctc) {
  if (ctc.ptr_) {
    os << *(ctc.ptr_);
  }
  return os;
}

bool is_id(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::ID;
}
bool is_integer(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::INTEGER;
}
bool is_seq(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::SEQ;
}
bool is_ibex_fwdbwd(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::IBEX_FWDBWD;
}
bool is_ibex_polytope(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::IBEX_POLYTOPE;
}
bool is_fixpoint(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::FIXPOINT;
}
bool is_worklist_fixpoint(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::WORKLIST_FIXPOINT;
}
bool is_forall(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::FORALL;
}
bool is_join(const Contractor& contractor) {
  return contractor.kind() == Contractor::Kind::JOIN;
}

}  // namespace dreal
<|endoftext|>


<commit_before>#include "directories.h"
#include "logging.h"

Directories::Controller::Controller(Directories::Config& cfg) :
  config_(cfg) {
  m_ScrolledWindow.add(m_TreeView);
  m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
}

void Directories::Controller::
open_folder(const boost::filesystem::path& dir_path) {
  INFO("Open folder");
  m_refTreeModel = Gtk::TreeStore::create(view());
  m_TreeView.set_model(m_refTreeModel);
  m_TreeView.remove_all_columns();
  std::string project_name = GetCmakeVarValue(dir_path, "project");
  m_TreeView.append_column(project_name, view().m_col_name);
  int row_id = 0;
  Gtk::TreeModel::Row row;
  list_dirs(dir_path, row, row_id);
  m_refTreeModel->set_sort_column(0, Gtk::SortType::SORT_ASCENDING);
  INFO("Folder opened");
}

bool Directories::Controller::IsIgnored(std::string path) {
  std::transform(path.begin(), path.end(), path.begin(), ::tolower);
  //  std::cout << "ignored?: " << path << std::endl;
  if (config().IsException(path)) {
    return false;
  }
  if (config().IsIgnored(path)) {
    return true;
  }
  return false;
}
void Directories::Controller::
list_dirs(const boost::filesystem::path& dir_path,
          Gtk::TreeModel::Row &parent,
          unsigned row_id) {
  boost::filesystem::directory_iterator end_itr;
  unsigned dir_counter = row_id;
  unsigned file_counter = 0;
  Gtk::TreeModel::Row child;
  Gtk::TreeModel::Row row;

  // Fill the treeview
  for ( boost::filesystem::directory_iterator itr( dir_path );
        itr != end_itr;
        ++itr ) {
    if (!IsIgnored(itr->path().filename().string())) {
      if (boost::filesystem::is_directory(itr->status())) {
        if (count(itr->path().string()) > count(dir_path.string())) {  // is child
          child = *(m_refTreeModel->append(parent.children()));
          std::string col_id("a"+itr->path().filename().string());
          child[view().m_col_id] = col_id;
          child[view().m_col_name] =  itr->path().filename().string();
          child[view().m_col_path] = itr->path().string();
          list_dirs(itr->path(), child, row_id);
        } else {
          row = *(m_refTreeModel->append());
          std::string col_id("a"+itr->path().filename().string());
          row[view().m_col_path] = itr->path().string();
          row[view().m_col_id] = col_id;
          row[view().m_col_name] =  itr->path().filename().string();
          list_dirs(itr->path(), parent, row_id);
        }
      } else {  // is a file
        child = *(m_refTreeModel->append(parent.children()));
        std::string col_id("b"+itr->path().filename().string());
        child[view().m_col_id] = col_id;
        child[view().m_col_name] = itr->path().filename().string();
        child[view().m_col_path] = itr->path().string();
      }
    }
  }
}
int Directories::Controller::count(const std::string path) {
  int count = 0;
  for (int i = 0; i < path.size(); i++)
    if (path[i] == '/') count++;
  return count;
}

  std::string Directories::Controller::
  GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_name) {
    INFO("fetches cmake variable value for: "+command_name);
    std::string project_name;
    std::string project_name_var;
    boost::filesystem::directory_iterator end_itr;
    for (boost::filesystem::directory_iterator itr( dir_path );
         itr != end_itr;
         ++itr ) {
      if (itr->path().filename().string() == "CMakeLists.txt") {
        std::ifstream ifs(itr->path().string());
        std::string line;
        while (std::getline(ifs, line)) {
          if (line.find(command_name+"(", 0) != std::string::npos
              || line.find(command_name+" (", 0) != std::string::npos ) {
	    size_t variable_start = line.find("{", 0);
	    size_t variable_end = line.find("}", variable_start);
	    project_name_var = line.substr(variable_start+1,
					   (variable_end)-variable_start-1);
            boost::algorithm::trim(project_name_var);
            if (variable_start == std::string::npos) { //  not a variabel
              variable_start = line.find("(", 0);

	      variable_end = line.find(' ', variable_start);
	      if(variable_end != std::string::npos){
		return line.substr(variable_start+1,
				   (variable_end)-variable_start-1);
	      }
	      variable_end = line.find("#", variable_start);
	      if(variable_end != std::string::npos){
		return line.substr(variable_start+1,
				   (variable_end)-variable_start-1);
	      }
	      variable_end = line.find(")", variable_start);
              return line.substr(variable_start+1,
                                 (variable_end)-variable_start-1);
             if (variable_start == std::string::npos) { //  not a variable
               variable_start = line.find("(", 0);
               variable_end = line.find(")", variable_start);
               INFO("Wasn't a variable, returning value");
               return line.substr(variable_start+1,
                                  (variable_end)-variable_start-1);
            }
            break;
          }
        }
	}
        std::ifstream ifs2(itr->path().string());
        while (std::getline(ifs2, line)) {
          if (line.find("set(", 0) != std::string::npos
              || line.find("set (", 0) != std::string::npos) {
            if( line.find(project_name_var, 0) != std::string::npos) {
              size_t variable_start = line.find(project_name_var, 0)
                +project_name_var.length();
              size_t variable_end = line.find(")", variable_start);
              project_name = line.substr(variable_start+1,
                                         variable_end-variable_start-1);
              boost::algorithm::trim(project_name);
              INFO("found variable, returning value");
              return project_name;
            }
          }
        }
        break;
      }
    }
    INFO("Couldn't find value in CMakeLists.txt");
    return "no project name";
  }

  Directories::Config::Config() {
  }
  Directories::Config::Config(Directories::Config& cfg) :
    ignore_list_(cfg.ignore_list()), exception_list_(cfg.exception_list()) {
  }

  void Directories::Config::AddIgnore(std::string filter) {
    ignore_list_.push_back(filter);
  }

  void Directories::Config::AddException(std::string filter) {
    exception_list_.push_back(filter);
  }

  bool Directories::Config::IsIgnored(std::string str) {
    for ( auto &i : ignore_list() )
      if (str.find(i, 0) != std::string::npos)
        return true;
    return false;
  }

  bool Directories::Config::IsException(std::string str) {
    for ( std::string &i : exception_list() )
      if (i == str)
        return true;
    return false;
  }
<commit_msg>added some debugging in directories<commit_after>#include "directories.h"
#include "logging.h"

Directories::Controller::Controller(Directories::Config& cfg) :
  config_(cfg) {
  DEBUG("adding treeview to scrolledwindow");
  m_ScrolledWindow.add(m_TreeView);
  m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
}

void Directories::Controller::
open_folder(const boost::filesystem::path& dir_path) {
  INFO("Open folder");
  m_refTreeModel = Gtk::TreeStore::create(view());
  m_TreeView.set_model(m_refTreeModel);
  m_TreeView.remove_all_columns();
  DEBUG("Getting project name from CMakeLists.txt");
  std::string project_name = GetCmakeVarValue(dir_path, "project");
  m_TreeView.append_column(project_name, view().m_col_name);
  int row_id = 0;
  Gtk::TreeModel::Row row;
  DEBUG("Listing directories");
  list_dirs(dir_path, row, row_id);
  DEBUG("Sorting directories");
  m_refTreeModel->set_sort_column(0, Gtk::SortType::SORT_ASCENDING);
  DEBUG("Folder opened");
}

bool Directories::Controller::IsIgnored(std::string path) {
  DEBUG("Checking if file-/directory is filtered");
  std::transform(path.begin(), path.end(), path.begin(), ::tolower);
  //  std::cout << "ignored?: " << path << std::endl;
  if (config().IsException(path)) {
    return false;
  }
  if (config().IsIgnored(path)) {
    return true;
  }
  return false;
}
void Directories::Controller::
list_dirs(const boost::filesystem::path& dir_path,
          Gtk::TreeModel::Row &parent,
          unsigned row_id) {

  boost::filesystem::directory_iterator end_itr;
  unsigned dir_counter = row_id;
  unsigned file_counter = 0;
  Gtk::TreeModel::Row child;
  Gtk::TreeModel::Row row;
  DEBUG_VAR(dir_path);
  // Fill the treeview
  for ( boost::filesystem::directory_iterator itr( dir_path );
        itr != end_itr;
        ++itr ) {
    if (!IsIgnored(itr->path().filename().string())) {
      if (boost::filesystem::is_directory(itr->status())) {
        if (count(itr->path().string()) > count(dir_path.string())) {  // is child
          child = *(m_refTreeModel->append(parent.children()));
          std::string col_id("a"+itr->path().filename().string());
          child[view().m_col_id] = col_id;
          child[view().m_col_name] =  itr->path().filename().string();
          child[view().m_col_path] = itr->path().string();
          list_dirs(itr->path(), child, row_id);
        } else {
          row = *(m_refTreeModel->append());
          std::string col_id("a"+itr->path().filename().string());
          row[view().m_col_path] = itr->path().string();
          row[view().m_col_id] = col_id;
          row[view().m_col_name] =  itr->path().filename().string();
          list_dirs(itr->path(), parent, row_id);
        }
      } else {  // is a file
        child = *(m_refTreeModel->append(parent.children()));
        std::string col_id("b"+itr->path().filename().string());
        child[view().m_col_id] = col_id;
        child[view().m_col_name] = itr->path().filename().string();
        child[view().m_col_path] = itr->path().string();
      }
    }
  }
}
int Directories::Controller::count(const std::string path) {
  int count = 0;
  for (int i = 0; i < path.size(); i++)
    if (path[i] == '/') count++;
  return count;
}

  std::string Directories::Controller::
  GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_name) {
    INFO("fetches cmake variable value for: "+command_name);
    std::string project_name;
    std::string project_name_var;
    boost::filesystem::directory_iterator end_itr;
    for (boost::filesystem::directory_iterator itr( dir_path );
         itr != end_itr;
         ++itr ) {
      if (itr->path().filename().string() == "CMakeLists.txt") {
        std::ifstream ifs(itr->path().string());
        std::string line;
        while (std::getline(ifs, line)) {
          if (line.find(command_name+"(", 0) != std::string::npos
              || line.find(command_name+" (", 0) != std::string::npos ) {
	    size_t variable_start = line.find("{", 0);
	    size_t variable_end = line.find("}", variable_start);
	    project_name_var = line.substr(variable_start+1,
					   (variable_end)-variable_start-1);
            boost::algorithm::trim(project_name_var);
            if (variable_start == std::string::npos) { //  not a variabel
              variable_start = line.find("(", 0);

	      variable_end = line.find(' ', variable_start);
	      if(variable_end != std::string::npos){
		return line.substr(variable_start+1,
				   (variable_end)-variable_start-1);
	      }
	      variable_end = line.find("#", variable_start);
	      if(variable_end != std::string::npos){
		return line.substr(variable_start+1,
				   (variable_end)-variable_start-1);
	      }
	      variable_end = line.find(")", variable_start);
              return line.substr(variable_start+1,
                                 (variable_end)-variable_start-1);
             if (variable_start == std::string::npos) { //  not a variable
               variable_start = line.find("(", 0);
               variable_end = line.find(")", variable_start);
               INFO("Wasn't a variable, returning value");
               return line.substr(variable_start+1,
                                  (variable_end)-variable_start-1);
            }
            break;
          }
        }
	}
        std::ifstream ifs2(itr->path().string());
        while (std::getline(ifs2, line)) {
          if (line.find("set(", 0) != std::string::npos
              || line.find("set (", 0) != std::string::npos) {
            if( line.find(project_name_var, 0) != std::string::npos) {
              size_t variable_start = line.find(project_name_var, 0)
                +project_name_var.length();
              size_t variable_end = line.find(")", variable_start);
              project_name = line.substr(variable_start+1,
                                         variable_end-variable_start-1);
              boost::algorithm::trim(project_name);
              INFO("found variable, returning value");
              return project_name;
            }
          }
        }
        break;
      }
    }
    INFO("Couldn't find value in CMakeLists.txt");
    return "no project name";
  }

  Directories::Config::Config() {
  }
  Directories::Config::Config(Directories::Config& cfg) :
    ignore_list_(cfg.ignore_list()), exception_list_(cfg.exception_list()) {
  }

  void Directories::Config::AddIgnore(std::string filter) {
    ignore_list_.push_back(filter);
  }

  void Directories::Config::AddException(std::string filter) {
    exception_list_.push_back(filter);
  }

  bool Directories::Config::IsIgnored(std::string str) {
    for ( auto &i : ignore_list() )
      if (str.find(i, 0) != std::string::npos)
        return true;
    return false;
  }

  bool Directories::Config::IsException(std::string str) {
    for ( std::string &i : exception_list() )
      if (i == str)
        return true;
    return false;
  }
<|endoftext|>


<commit_before>#include "Histogram.h"
#include "Matrix.h"

void Histogram::Init(Local<Object> target) {
  Nan::Persistent<Object> inner;
  Local<Object> obj = Nan::New<Object>();
  inner.Reset(obj);

  Nan::SetMethod(obj, "calcHist", CalcHist);
  Nan::SetMethod(obj, "emd", Emd);

  target->Set(Nan::New("histogram").ToLocalChecked(), obj);
}

NAN_METHOD(Histogram::CalcHist) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the image
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat inputImage = m0->mat;

    //int dims = 3;
    // Arg 1 is the channel
    Local<Array> nodeChannels = Local<Array>::Cast(info[1]->ToObject());
    const unsigned int dims = nodeChannels->Length();
    int channels[dims];
    for (unsigned int i = 0; i < dims; i++) {
      channels[i] = nodeChannels->Get(i)->IntegerValue();
    }

    //int channels[] = {0, 1, 2};

    // Arg 2 is histogram sizes in each dimension
    Local<Array> nodeHistSizes = Local<Array>::Cast(info[2]->ToObject());
    int histSize[dims];
    for (unsigned int i = 0; i < dims; i++) {
      histSize[i] = nodeHistSizes->Get(i)->IntegerValue();
    }

    // Arg 3 is array of the histogram bin boundaries in each dimension

    Local<Array> nodeRanges = Local<Array>::Cast(info[3]->ToObject());
    /// Set the ranges ( for B,G,R) )
    float histRanges[dims][2];

    for (unsigned int i = 0; i < dims; i++) {
      Local<Array> nodeRange = Local<Array>::Cast(nodeRanges->Get(i)->ToObject());
      float lower = nodeRange->Get(0)->NumberValue();
      float higher = nodeRange->Get(1)->NumberValue();
      histRanges[i][0] = lower;
      histRanges[i][1] = higher;
    }

    float first_range[] = { histRanges[0][0], histRanges[0][1] };
    float second_range[] = { 0, 0};
    float third_range[] = { 0, 0};

    if(dims >= 2){
      second_range[0] = histRanges[1][0];
      second_range[1] = histRanges[1][1];
    }
    if(dims >= 3){
      third_range[0] = histRanges[2][0];
      third_range[1] = histRanges[2][1];
    }

    const float* histRanges1[] = {first_range, second_range, third_range};

    //const float** histRanges1 = const_cast<const float**>(histRanges);

    // Arg 4 is uniform flag
    bool uniform = info[4]->BooleanValue();

    // Make a mat to hold the result image
    cv::Mat outputHist;

    // Perform calcHist
    cv::calcHist(&inputImage, 1, channels, cv::Mat(), outputHist, dims, histSize, histRanges1, uniform);

    // Wrap the output image
    /*Local<Object> outMatrixWrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
    Matrix *outMatrix = Nan::ObjectWrap::Unwrap<Matrix>(outMatrixWrap);
    outMatrix->mat = outputHist;

    info.GetReturnValue().Set(outMatrixWrap);*/

    v8::Local<v8::Array> arr = Nan::New<Array>(histSize[0]);

    if(dims < 1 || dims > 3){
      return Nan::ThrowTypeError("OPENCV nodejs binding error : only dimensions from 1 to 3 are allowed");
    }

    for (unsigned int i=0; i < (unsigned int) histSize[0]; i++) {
      if(dims <= 1){
        arr->Set(i, Nan::New<Number>(outputHist.at<float>(i)));
      } else {
        v8::Local<v8::Array> arr2 = Nan::New<Array>(dims);
        for (unsigned int j=0; j < (unsigned int) histSize[1]; j++) {
          if(dims <= 2){
            arr2->Set(j, Nan::New<Number>(outputHist.at<float>(i,j)));
          } else {
            v8::Local<v8::Array> arr3 = Nan::New<Array>(dims);
            for (unsigned int k=0; k < (unsigned int) histSize[1]; k++) {
              arr3->Set(k, Nan::New<Number>(outputHist.at<float>(i,j,k)));
            }
            arr2->Set(j, arr3);
          }
        }
        arr->Set(i, arr2);
      }
    }

    info.GetReturnValue().Set(arr);
  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}

std::vector<std::vector<float>> nodeArrayToVec(Local<Object> input){
    std::vector<std::vector<float>> ret;
    Local<Array> nodeMatrix = Local<Array>::Cast(input);
    const unsigned int size = nodeMatrix->Length();
    for (unsigned int i = 0; i < size; i++) {
      Local<Array> nodeRow = Local<Array>::Cast(nodeMatrix->Get(i)->ToObject());
      std::vector<float> row;
      const unsigned int size2 = nodeRow->Length();
      for (unsigned int j = 0; j < size2; j++) {
        row.push_back(nodeRow->Get(j)->NumberValue());
      }
      ret.push_back(row);
    }

    return ret;
}

// cv::distanceTransform
NAN_METHOD(Histogram::Emd) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the first signature
    //std::vector<std::vector<float>> sig1 = nodeArrayToVec(info[0]->ToObject());
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat sig1 = m0->mat;

    // Arg 1 is the second signature
    //std::vector<std::vector<float>> sig2 = nodeArrayToVec(info[1]->ToObject());
    Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[1]->ToObject());
    cv::Mat sig2 = m1->mat;

    // Arg 2 is the distance type
    int distType = info[2]->IntegerValue();

    float emd;

    // Arg 3 is the cost matrix
    if (info.Length() > 3) {
      Matrix* m3 = Nan::ObjectWrap::Unwrap<Matrix>(info[3]->ToObject());
      cv::Mat costs = m3->mat;

      emd = cv::EMD(sig1, sig2, distType, costs);
      info.GetReturnValue().Set(emd);
    } else {
      emd = cv::EMD(sig1, sig2, distType);
    }

    //printf("similarity %5.5f %%\n, DistanceType is %i\n", (1-emd)*100, distType);
    info.GetReturnValue().Set(emd);

  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}
<commit_msg>cleanup code following https://stackoverflow.com/questions/45868943/convert-node-array-variable-lenght-to-a-const-float-to-call-opencv-calchist/45870887#45870887<commit_after>#include "Histogram.h"
#include "Matrix.h"

void Histogram::Init(Local<Object> target) {
  Nan::Persistent<Object> inner;
  Local<Object> obj = Nan::New<Object>();
  inner.Reset(obj);

  Nan::SetMethod(obj, "calcHist", CalcHist);
  Nan::SetMethod(obj, "emd", Emd);

  target->Set(Nan::New("histogram").ToLocalChecked(), obj);
}

NAN_METHOD(Histogram::CalcHist) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the image
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat inputImage = m0->mat;

    //int dims = 3;
    // Arg 1 is the channel
    Local<Array> nodeChannels = Local<Array>::Cast(info[1]->ToObject());
    const unsigned int dims = nodeChannels->Length();
    int channels[dims];
    for (unsigned int i = 0; i < dims; i++) {
      channels[i] = nodeChannels->Get(i)->IntegerValue();
    }

    //int channels[] = {0, 1, 2};

    // Arg 2 is histogram sizes in each dimension
    Local<Array> nodeHistSizes = Local<Array>::Cast(info[2]->ToObject());
    int histSize[dims];
    for (unsigned int i = 0; i < dims; i++) {
      histSize[i] = nodeHistSizes->Get(i)->IntegerValue();
    }

    // Arg 3 is array of the histogram bin boundaries in each dimension

    Local<Array> nodeRanges = Local<Array>::Cast(info[3]->ToObject());
    /// Set the ranges ( for B,G,R) )
    float histRanges[dims][2];
    const float* ranges[dims];

    for (unsigned int i = 0; i < dims; i++) {
      Local<Array> nodeRange = Local<Array>::Cast(nodeRanges->Get(i)->ToObject());
      float lower = nodeRange->Get(0)->NumberValue();
      float higher = nodeRange->Get(1)->NumberValue();
      histRanges[i][0] = lower;
      histRanges[i][1] = higher;
      ranges[i] = histRanges[i];
    }

    //const float** histRanges1 = const_cast<const float**>(histRanges);

    // Arg 4 is uniform flag
    bool uniform = info[4]->BooleanValue();

    // Make a mat to hold the result image
    cv::Mat outputHist;

    // Perform calcHist
    cv::calcHist(&inputImage, 1, channels, cv::Mat(), outputHist, dims, histSize, ranges, uniform);

    // Wrap the output image
    /*Local<Object> outMatrixWrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked();
    Matrix *outMatrix = Nan::ObjectWrap::Unwrap<Matrix>(outMatrixWrap);
    outMatrix->mat = outputHist;

    info.GetReturnValue().Set(outMatrixWrap);*/

    v8::Local<v8::Array> arr = Nan::New<Array>(histSize[0]);

    if(dims < 1 || dims > 3){
      return Nan::ThrowTypeError("OPENCV nodejs binding error : only dimensions from 1 to 3 are allowed");
    }

    for (unsigned int i=0; i < (unsigned int) histSize[0]; i++) {
      if(dims <= 1){
        arr->Set(i, Nan::New<Number>(outputHist.at<float>(i)));
      } else {
        v8::Local<v8::Array> arr2 = Nan::New<Array>(dims);
        for (unsigned int j=0; j < (unsigned int) histSize[1]; j++) {
          if(dims <= 2){
            arr2->Set(j, Nan::New<Number>(outputHist.at<float>(i,j)));
          } else {
            v8::Local<v8::Array> arr3 = Nan::New<Array>(dims);
            for (unsigned int k=0; k < (unsigned int) histSize[1]; k++) {
              arr3->Set(k, Nan::New<Number>(outputHist.at<float>(i,j,k)));
            }
            arr2->Set(j, arr3);
          }
        }
        arr->Set(i, arr2);
      }
    }

    info.GetReturnValue().Set(arr);
  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}

std::vector<std::vector<float>> nodeArrayToVec(Local<Object> input){
    std::vector<std::vector<float>> ret;
    Local<Array> nodeMatrix = Local<Array>::Cast(input);
    const unsigned int size = nodeMatrix->Length();
    for (unsigned int i = 0; i < size; i++) {
      Local<Array> nodeRow = Local<Array>::Cast(nodeMatrix->Get(i)->ToObject());
      std::vector<float> row;
      const unsigned int size2 = nodeRow->Length();
      for (unsigned int j = 0; j < size2; j++) {
        row.push_back(nodeRow->Get(j)->NumberValue());
      }
      ret.push_back(row);
    }

    return ret;
}

// cv::distanceTransform
NAN_METHOD(Histogram::Emd) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the first signature
    //std::vector<std::vector<float>> sig1 = nodeArrayToVec(info[0]->ToObject());
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat sig1 = m0->mat;

    // Arg 1 is the second signature
    //std::vector<std::vector<float>> sig2 = nodeArrayToVec(info[1]->ToObject());
    Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[1]->ToObject());
    cv::Mat sig2 = m1->mat;

    // Arg 2 is the distance type
    int distType = info[2]->IntegerValue();

    float emd;

    // Arg 3 is the cost matrix
    if (info.Length() > 3) {
      Matrix* m3 = Nan::ObjectWrap::Unwrap<Matrix>(info[3]->ToObject());
      cv::Mat costs = m3->mat;

      emd = cv::EMD(sig1, sig2, distType, costs);
      info.GetReturnValue().Set(emd);
    } else {
      emd = cv::EMD(sig1, sig2, distType);
    }

    //printf("similarity %5.5f %%\n, DistanceType is %i\n", (1-emd)*100, distType);
    info.GetReturnValue().Set(emd);

  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}
<|endoftext|>


<commit_before>#include "Histogram.h"
#include "Matrix.h"

void Histogram::Init(Local<Object> target) {
  Nan::Persistent<Object> inner;
  Local<Object> obj = Nan::New<Object>();
  inner.Reset(obj);

  Nan::SetMethod(obj, "calcHist", CalcHist);
  Nan::SetMethod(obj, "emd", Emd);

  target->Set(Nan::New("histogram").ToLocalChecked(), obj);
}

NAN_METHOD(Histogram::CalcHist) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the image
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat inputImage = m0->mat;

    // Arg 1 is the channel
    Local<Array> nodeChannels = Local<Array>::Cast(info[1]->ToObject());
    const unsigned int dims = nodeChannels->Length();
    int channels[dims];
    for (unsigned int i = 0; i < dims; i++) {
      channels[i] = nodeChannels->Get(i)->IntegerValue();
    }

    // Arg 2 is histogram sizes in each dimension
    Local<Array> nodeHistSizes = Local<Array>::Cast(info[2]->ToObject());
    int histSize[dims];
    for (unsigned int i = 0; i < dims; i++) {
      histSize[i] = nodeHistSizes->Get(i)->IntegerValue();
    }

    // Arg 3 is array of the histogram bin boundaries in each dimension
    Local<Array> nodeRanges = Local<Array>::Cast(info[3]->ToObject());
    /// Set the ranges ( for B,G,R) )
    float histRanges[dims][2];
    const float* ranges[dims];

    for (unsigned int i = 0; i < dims; i++) {
      Local<Array> nodeRange = Local<Array>::Cast(nodeRanges->Get(i)->ToObject());
      float lower = nodeRange->Get(0)->NumberValue();
      float higher = nodeRange->Get(1)->NumberValue();
      histRanges[i][0] = lower;
      histRanges[i][1] = higher;
      ranges[i] = histRanges[i];
    }

    // Arg 4 is uniform flag
    bool uniform = info[4]->BooleanValue();

    // Make a mat to hold the result image
    cv::Mat outputHist;

    // Perform calcHist
    cv::calcHist(&inputImage, 1, channels, cv::Mat(), outputHist, dims, histSize, ranges, uniform);

    v8::Local<v8::Array> arr = Nan::New<Array>(histSize[0]);

    if(dims < 1 || dims > 3){
      return Nan::ThrowTypeError("OPENCV nodejs binding error : only dimensions from 1 to 3 are allowed");
    }

    for (unsigned int i=0; i < (unsigned int) histSize[0]; i++) {
      if(dims <= 1){
        arr->Set(i, Nan::New<Number>(outputHist.at<float>(i)));
      } else {
        v8::Local<v8::Array> arr2 = Nan::New<Array>(dims);
        for (unsigned int j=0; j < (unsigned int) histSize[1]; j++) {
          if(dims <= 2){
            arr2->Set(j, Nan::New<Number>(outputHist.at<float>(i,j)));
          } else {
            v8::Local<v8::Array> arr3 = Nan::New<Array>(dims);
            for (unsigned int k=0; k < (unsigned int) histSize[1]; k++) {
              arr3->Set(k, Nan::New<Number>(outputHist.at<float>(i,j,k)));
            }
            arr2->Set(j, arr3);
          }
        }
        arr->Set(i, arr2);
      }
    }

    info.GetReturnValue().Set(arr);
  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}

// cv::distanceTransform
NAN_METHOD(Histogram::Emd) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the first signature
    //std::vector<std::vector<float>> sig1 = nodeArrayToVec(info[0]->ToObject());
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat sig1 = m0->mat;

    // Arg 1 is the second signature
    //std::vector<std::vector<float>> sig2 = nodeArrayToVec(info[1]->ToObject());
    Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[1]->ToObject());
    cv::Mat sig2 = m1->mat;

    // Arg 2 is the distance type
    int distType = info[2]->IntegerValue();

    float emd;

    // Arg 3 is the cost matrix
    if (info.Length() > 3) {
      Matrix* m3 = Nan::ObjectWrap::Unwrap<Matrix>(info[3]->ToObject());
      cv::Mat costs = m3->mat;

      emd = cv::EMD(sig1, sig2, distType, costs);
      info.GetReturnValue().Set(emd);
    } else {
      emd = cv::EMD(sig1, sig2, distType);
    }

    //printf("similarity %5.5f %%\n, DistanceType is %i\n", (1-emd)*100, distType);
    info.GetReturnValue().Set(emd);

  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}
<commit_msg>Histogram - fix VS compilation by setting constant size arrays.<commit_after>#include "Histogram.h"
#include "Matrix.h"

void Histogram::Init(Local<Object> target) {
  Nan::Persistent<Object> inner;
  Local<Object> obj = Nan::New<Object>();
  inner.Reset(obj);

  Nan::SetMethod(obj, "calcHist", CalcHist);
  Nan::SetMethod(obj, "emd", Emd);

  target->Set(Nan::New("histogram").ToLocalChecked(), obj);
}

NAN_METHOD(Histogram::CalcHist) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the image
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat inputImage = m0->mat;

    // Arg 1 is the channel
    Local<Array> nodeChannels = Local<Array>::Cast(info[1]->ToObject());
    // vs does not like this const, no need for it?
    /*const */unsigned int dims = nodeChannels->Length();

    if(dims < 1 || dims > 3){
      return Nan::ThrowTypeError("OPENCV nodejs binding error : only dimensions from 1 to 3 are allowed");
    }

    // in vs, can't create an array of non-constant size; but since we have dims<3, just use 3..
    int channels[3];
    for (unsigned int i = 0; i < dims; i++) {
      channels[i] = nodeChannels->Get(i)->IntegerValue();
    }

    // Arg 2 is histogram sizes in each dimension
    Local<Array> nodeHistSizes = Local<Array>::Cast(info[2]->ToObject());
    int histSize[3];
    for (unsigned int i = 0; i < dims; i++) {
      histSize[i] = nodeHistSizes->Get(i)->IntegerValue();
    }

    // Arg 3 is array of the histogram bin boundaries in each dimension
    Local<Array> nodeRanges = Local<Array>::Cast(info[3]->ToObject());
    /// Set the ranges ( for B,G,R) )
    float histRanges[3][2];
    const float* ranges[3];

    for (unsigned int i = 0; i < dims; i++) {
      Local<Array> nodeRange = Local<Array>::Cast(nodeRanges->Get(i)->ToObject());
      float lower = nodeRange->Get(0)->NumberValue();
      float higher = nodeRange->Get(1)->NumberValue();
      histRanges[i][0] = lower;
      histRanges[i][1] = higher;
      ranges[i] = histRanges[i];
    }

    // Arg 4 is uniform flag
    bool uniform = info[4]->BooleanValue();

    // Make a mat to hold the result image
    cv::Mat outputHist;

    // Perform calcHist
    cv::calcHist(&inputImage, 1, channels, cv::Mat(), outputHist, dims, histSize, ranges, uniform);

    v8::Local<v8::Array> arr = Nan::New<Array>(histSize[0]);

    for (unsigned int i=0; i < (unsigned int) histSize[0]; i++) {
      if(dims <= 1){
        arr->Set(i, Nan::New<Number>(outputHist.at<float>(i)));
      } else {
        v8::Local<v8::Array> arr2 = Nan::New<Array>(dims);
        for (unsigned int j=0; j < (unsigned int) histSize[1]; j++) {
          if(dims <= 2){
            arr2->Set(j, Nan::New<Number>(outputHist.at<float>(i,j)));
          } else {
            v8::Local<v8::Array> arr3 = Nan::New<Array>(dims);
            for (unsigned int k=0; k < (unsigned int) histSize[1]; k++) {
              arr3->Set(k, Nan::New<Number>(outputHist.at<float>(i,j,k)));
            }
            arr2->Set(j, arr3);
          }
        }
        arr->Set(i, arr2);
      }
    }

    info.GetReturnValue().Set(arr);
  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}

// cv::distanceTransform
NAN_METHOD(Histogram::Emd) {
  Nan::EscapableHandleScope scope;

  try {
    // Arg 0 is the first signature
    //std::vector<std::vector<float>> sig1 = nodeArrayToVec(info[0]->ToObject());
    Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
    cv::Mat sig1 = m0->mat;

    // Arg 1 is the second signature
    //std::vector<std::vector<float>> sig2 = nodeArrayToVec(info[1]->ToObject());
    Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[1]->ToObject());
    cv::Mat sig2 = m1->mat;

    // Arg 2 is the distance type
    int distType = info[2]->IntegerValue();

    float emd;

    // Arg 3 is the cost matrix
    if (info.Length() > 3) {
      Matrix* m3 = Nan::ObjectWrap::Unwrap<Matrix>(info[3]->ToObject());
      cv::Mat costs = m3->mat;

      emd = cv::EMD(sig1, sig2, distType, costs);
      info.GetReturnValue().Set(emd);
    } else {
      emd = cv::EMD(sig1, sig2, distType);
    }

    //printf("similarity %5.5f %%\n, DistanceType is %i\n", (1-emd)*100, distType);
    info.GetReturnValue().Set(emd);

  } catch (cv::Exception &e) {
    const char *err_msg = e.what();
    Nan::ThrowError(err_msg);
    return;
  }
}
<|endoftext|>