<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.

// Tests for CppBoundClass, in conjunction with CppBindingExample.  Binds
// a CppBindingExample class into JavaScript in a custom test shell and tests
// the binding from the outside by loading JS into the shell.

#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSettings.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebViewClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebData.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
#include "webkit/glue/cpp_binding_example.h"
#include "webkit/glue/webkit_glue.h"

using WebKit::WebFrame;
using WebKit::WebView;
using webkit_glue::CppArgumentList;
using webkit_glue::CppBindingExample;
using webkit_glue::CppVariant;

namespace {

class CppBindingExampleSubObject : public CppBindingExample {
 public:
  CppBindingExampleSubObject() {
    sub_value_.Set("sub!");
    BindProperty("sub_value", &sub_value_);
  }
 private:
  CppVariant sub_value_;
};

class CppBindingExampleWithOptionalFallback : public CppBindingExample {
 public:
  CppBindingExampleWithOptionalFallback() {
    BindProperty("sub_object", sub_object_.GetAsCppVariant());
  }

  void set_fallback_method_enabled(bool state) {
    BindFallbackCallback(state ?
        base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod,
                   base::Unretained(this))
        : CppBoundClass::Callback());
  }

  // The fallback method does nothing, but because of it the JavaScript keeps
  // running when a nonexistent method is called on an object.
  void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
  }

 private:
  CppBindingExampleSubObject sub_object_;
};

class TestWebFrameClient : public WebKit::WebFrameClient {
 public:
  virtual void didClearWindowObject(WebKit::WebFrame* frame) OVERRIDE {
    example_bound_class_.BindToJavascript(frame, "example");
  }
  void set_fallback_method_enabled(bool use_fallback) {
    example_bound_class_.set_fallback_method_enabled(use_fallback);
  }
 private:
  CppBindingExampleWithOptionalFallback example_bound_class_;
};

class TestWebViewClient : public WebKit::WebViewClient {
};

class CppBoundClassTest : public testing::Test, public WebKit::WebFrameClient {
 public:
  CppBoundClassTest() : webview_(NULL) { }

  virtual void SetUp() OVERRIDE {
    webview_ = WebView::create(&webview_client_);
    webview_->settings()->setJavaScriptEnabled(true);
    webview_->initializeMainFrame(&webframe_client_);
    webframe_client_.set_fallback_method_enabled(useFallback());

    WebKit::WebURLRequest urlRequest;
    urlRequest.initialize();
    urlRequest.setURL(GURL("about:blank"));
    webframe()->loadRequest(urlRequest);
  }

  virtual void TearDown() OVERRIDE {
    if (webview_)
      webview_->close();
  }

  WebFrame* webframe() {
    return webview_->mainFrame();
  }

  // Wraps the given JavaScript snippet in ");
    webframe()->loadHTMLString(html, GURL("about:blank"));
    MessageLoop::current()->RunAllPending();
  }

  // Executes the specified JavaScript and checks to be sure that the resulting
  // document text is exactly "SUCCESS".
  void CheckJavaScriptSuccess(const std::string& javascript) {
    ExecuteJavaScript(javascript);
    EXPECT_EQ("SUCCESS",
              UTF16ToASCII(webkit_glue::DumpDocumentText(webframe())));
  }

  // Executes the specified JavaScript and checks that the resulting document
  // text is empty.
  void CheckJavaScriptFailure(const std::string& javascript) {
    ExecuteJavaScript(javascript);
    EXPECT_EQ("", UTF16ToASCII(webkit_glue::DumpDocumentText(webframe())));
  }

  // Constructs a JavaScript snippet that evaluates and compares the left and
  // right expressions, printing "SUCCESS" to the page if they are equal and
  // printing their actual values if they are not.  Any strings in the
  // expressions should be enclosed in single quotes, and no double quotes
  // should appear in either expression (even if escaped). (If a test case
  // is added that needs fancier quoting, Json::valueToQuotedString could be
  // used here.  For now, it's not worth adding the dependency.)
  std::string BuildJSCondition(std::string left, std::string right) {
    return "var leftval = " + left + ";" +
           "var rightval = " + right + ";" +
           "if (leftval == rightval) {" +
           "  document.writeln('SUCCESS');" +
           "} else {" +
           "  document.writeln(\"" +
                left + " [\" + leftval + \"] != " +
                right + " [\" + rightval + \"]\");" +
           "}";
  }

 protected:
  virtual bool useFallback() {
    return false;
  }

 private:
  WebView* webview_;
  TestWebFrameClient webframe_client_;
  TestWebViewClient webview_client_;
};

class CppBoundClassWithFallbackMethodTest : public CppBoundClassTest {
 protected:
  virtual bool useFallback() {
    return true;
  }
};

// Ensures that the example object has been bound to JS.
TEST_F(CppBoundClassTest, ObjectExists) {
  std::string js = BuildJSCondition("typeof window.example", "'object'");
  CheckJavaScriptSuccess(js);

  // An additional check to test our test.
  js = BuildJSCondition("typeof window.invalid_object", "'undefined'");
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, PropertiesAreInitialized) {
  std::string js = BuildJSCondition("example.my_value", "10");
  CheckJavaScriptSuccess(js);

  js = BuildJSCondition("example.my_other_value", "'Reinitialized!'");
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, SubOject) {
  std::string js = BuildJSCondition("typeof window.example.sub_object",
                                    "'object'");
  CheckJavaScriptSuccess(js);

  js = BuildJSCondition("example.sub_object.sub_value", "'sub!'");
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, SetAndGetProperties) {
  // The property on the left will be set to the value on the right, then
  // checked to make sure it holds that same value.
  static const std::string tests[] = {
    "example.my_value", "7",
    "example.my_value", "'test'",
    "example.my_other_value", "3.14",
    "example.my_other_value", "false",
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i += 2) {
    std::string left = tests[i];
    std::string right = tests[i + 1];
    // left = right;
    std::string js = left;
    js.append(" = ");
    js.append(right);
    js.append(";");
    js.append(BuildJSCondition(left, right));
    CheckJavaScriptSuccess(js);
  }
}

TEST_F(CppBoundClassTest, SetAndGetPropertiesWithCallbacks) {
  // TODO(dglazkov): fix NPObject issues around failing property setters and
  // getters and add tests for situations when GetProperty or SetProperty fail.
  std::string js = "var result = 'SUCCESS';\n"
    "example.my_value_with_callback = 10;\n"
    "if (example.my_value_with_callback != 10)\n"
    "  result = 'FAIL: unable to set property.';\n"
    "example.my_value_with_callback = 11;\n"
    "if (example.my_value_with_callback != 11)\n"
    "  result = 'FAIL: unable to set property again';\n"
    "if (example.same != 42)\n"
    "  result = 'FAIL: same property should always be 42';\n"
    "example.same = 24;\n"
    "if (example.same != 42)\n"
    "  result = 'FAIL: same property should always be 42';\n"
    "document.writeln(result);\n";
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, InvokeMethods) {
  // The expression on the left is expected to return the value on the right.
  static const std::string tests[] = {
    "example.echoValue(true)", "true",
    "example.echoValue(13)", "13",
    "example.echoValue(2.718)", "2.718",
    "example.echoValue('yes')", "'yes'",
    "example.echoValue()", "null",     // Too few arguments

    "example.echoType(false)", "true",
    "example.echoType(19)", "3.14159",
    "example.echoType(9.876)", "3.14159",
    "example.echoType('test string')", "'Success!'",
    "example.echoType()", "null",      // Too few arguments

    // Comparing floats that aren't integer-valued is usually problematic due
    // to rounding, but exact powers of 2 should also be safe.
    "example.plus(2.5, 18.0)", "20.5",
    "example.plus(2, 3.25)", "5.25",
    "example.plus(2, 3)", "5",
    "example.plus()", "null",             // Too few arguments
    "example.plus(1)", "null",            // Too few arguments
    "example.plus(1, 'test')", "null",    // Wrong argument type
    "example.plus('test', 2)", "null",    // Wrong argument type
    "example.plus('one', 'two')", "null", // Wrong argument type
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i+= 2) {
    std::string left = tests[i];
    std::string right = tests[i + 1];
    std::string js = BuildJSCondition(left, right);
    CheckJavaScriptSuccess(js);
  }

  std::string js = "example.my_value = 3.25; example.my_other_value = 1.25;";
  js.append(BuildJSCondition(
      "example.plus(example.my_value, example.my_other_value)", "4.5"));
  CheckJavaScriptSuccess(js);
}

// Tests that invoking a nonexistent method with no fallback method stops the
// script's execution
TEST_F(CppBoundClassTest,
       InvokeNonexistentMethodNoFallback) {
  std::string js = "example.nonExistentMethod();document.writeln('SUCCESS');";
  CheckJavaScriptFailure(js);
}

// Ensures existent methods can be invoked successfully when the fallback method
// is used
TEST_F(CppBoundClassWithFallbackMethodTest,
       InvokeExistentMethodsWithFallback) {
  std::string js = BuildJSCondition("example.echoValue(34)", "34");
  CheckJavaScriptSuccess(js);
}

}  // namespace
<commit_msg>Set user agent in cpp bindings test<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.

// Tests for CppBoundClass, in conjunction with CppBindingExample.  Binds
// a CppBindingExample class into JavaScript in a custom test shell and tests
// the binding from the outside by loading JS into the shell.

#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSettings.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebViewClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebData.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
#include "webkit/glue/cpp_binding_example.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/user_agent/user_agent.h"
#include "webkit/user_agent/user_agent_util.h"

using WebKit::WebFrame;
using WebKit::WebView;
using webkit_glue::CppArgumentList;
using webkit_glue::CppBindingExample;
using webkit_glue::CppVariant;

namespace {

class CppBindingExampleSubObject : public CppBindingExample {
 public:
  CppBindingExampleSubObject() {
    sub_value_.Set("sub!");
    BindProperty("sub_value", &sub_value_);
  }
 private:
  CppVariant sub_value_;
};

class CppBindingExampleWithOptionalFallback : public CppBindingExample {
 public:
  CppBindingExampleWithOptionalFallback() {
    BindProperty("sub_object", sub_object_.GetAsCppVariant());
  }

  void set_fallback_method_enabled(bool state) {
    BindFallbackCallback(state ?
        base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod,
                   base::Unretained(this))
        : CppBoundClass::Callback());
  }

  // The fallback method does nothing, but because of it the JavaScript keeps
  // running when a nonexistent method is called on an object.
  void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
  }

 private:
  CppBindingExampleSubObject sub_object_;
};

class TestWebFrameClient : public WebKit::WebFrameClient {
 public:
  virtual void didClearWindowObject(WebKit::WebFrame* frame) OVERRIDE {
    example_bound_class_.BindToJavascript(frame, "example");
  }
  void set_fallback_method_enabled(bool use_fallback) {
    example_bound_class_.set_fallback_method_enabled(use_fallback);
  }
 private:
  CppBindingExampleWithOptionalFallback example_bound_class_;
};

class TestWebViewClient : public WebKit::WebViewClient {
};

class CppBoundClassTest : public testing::Test, public WebKit::WebFrameClient {
 public:
  CppBoundClassTest() : webview_(NULL) { }

  virtual void SetUp() OVERRIDE {
    webview_ = WebView::create(&webview_client_);
    webview_->settings()->setJavaScriptEnabled(true);
    webview_->initializeMainFrame(&webframe_client_);
    webframe_client_.set_fallback_method_enabled(useFallback());
    webkit_glue::SetUserAgent(webkit_glue::BuildUserAgentFromProduct(
        "TestShell/0.0.0.0"), false);

    WebKit::WebURLRequest urlRequest;
    urlRequest.initialize();
    urlRequest.setURL(GURL("about:blank"));
    webframe()->loadRequest(urlRequest);
  }

  virtual void TearDown() OVERRIDE {
    if (webview_)
      webview_->close();
  }

  WebFrame* webframe() {
    return webview_->mainFrame();
  }

  // Wraps the given JavaScript snippet in ");
    webframe()->loadHTMLString(html, GURL("about:blank"));
    MessageLoop::current()->RunAllPending();
  }

  // Executes the specified JavaScript and checks to be sure that the resulting
  // document text is exactly "SUCCESS".
  void CheckJavaScriptSuccess(const std::string& javascript) {
    ExecuteJavaScript(javascript);
    EXPECT_EQ("SUCCESS",
              UTF16ToASCII(webkit_glue::DumpDocumentText(webframe())));
  }

  // Executes the specified JavaScript and checks that the resulting document
  // text is empty.
  void CheckJavaScriptFailure(const std::string& javascript) {
    ExecuteJavaScript(javascript);
    EXPECT_EQ("", UTF16ToASCII(webkit_glue::DumpDocumentText(webframe())));
  }

  // Constructs a JavaScript snippet that evaluates and compares the left and
  // right expressions, printing "SUCCESS" to the page if they are equal and
  // printing their actual values if they are not.  Any strings in the
  // expressions should be enclosed in single quotes, and no double quotes
  // should appear in either expression (even if escaped). (If a test case
  // is added that needs fancier quoting, Json::valueToQuotedString could be
  // used here.  For now, it's not worth adding the dependency.)
  std::string BuildJSCondition(std::string left, std::string right) {
    return "var leftval = " + left + ";" +
           "var rightval = " + right + ";" +
           "if (leftval == rightval) {" +
           "  document.writeln('SUCCESS');" +
           "} else {" +
           "  document.writeln(\"" +
                left + " [\" + leftval + \"] != " +
                right + " [\" + rightval + \"]\");" +
           "}";
  }

 protected:
  virtual bool useFallback() {
    return false;
  }

 private:
  WebView* webview_;
  TestWebFrameClient webframe_client_;
  TestWebViewClient webview_client_;
};

class CppBoundClassWithFallbackMethodTest : public CppBoundClassTest {
 protected:
  virtual bool useFallback() {
    return true;
  }
};

// Ensures that the example object has been bound to JS.
TEST_F(CppBoundClassTest, ObjectExists) {
  std::string js = BuildJSCondition("typeof window.example", "'object'");
  CheckJavaScriptSuccess(js);

  // An additional check to test our test.
  js = BuildJSCondition("typeof window.invalid_object", "'undefined'");
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, PropertiesAreInitialized) {
  std::string js = BuildJSCondition("example.my_value", "10");
  CheckJavaScriptSuccess(js);

  js = BuildJSCondition("example.my_other_value", "'Reinitialized!'");
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, SubOject) {
  std::string js = BuildJSCondition("typeof window.example.sub_object",
                                    "'object'");
  CheckJavaScriptSuccess(js);

  js = BuildJSCondition("example.sub_object.sub_value", "'sub!'");
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, SetAndGetProperties) {
  // The property on the left will be set to the value on the right, then
  // checked to make sure it holds that same value.
  static const std::string tests[] = {
    "example.my_value", "7",
    "example.my_value", "'test'",
    "example.my_other_value", "3.14",
    "example.my_other_value", "false",
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i += 2) {
    std::string left = tests[i];
    std::string right = tests[i + 1];
    // left = right;
    std::string js = left;
    js.append(" = ");
    js.append(right);
    js.append(";");
    js.append(BuildJSCondition(left, right));
    CheckJavaScriptSuccess(js);
  }
}

TEST_F(CppBoundClassTest, SetAndGetPropertiesWithCallbacks) {
  // TODO(dglazkov): fix NPObject issues around failing property setters and
  // getters and add tests for situations when GetProperty or SetProperty fail.
  std::string js = "var result = 'SUCCESS';\n"
    "example.my_value_with_callback = 10;\n"
    "if (example.my_value_with_callback != 10)\n"
    "  result = 'FAIL: unable to set property.';\n"
    "example.my_value_with_callback = 11;\n"
    "if (example.my_value_with_callback != 11)\n"
    "  result = 'FAIL: unable to set property again';\n"
    "if (example.same != 42)\n"
    "  result = 'FAIL: same property should always be 42';\n"
    "example.same = 24;\n"
    "if (example.same != 42)\n"
    "  result = 'FAIL: same property should always be 42';\n"
    "document.writeln(result);\n";
  CheckJavaScriptSuccess(js);
}

TEST_F(CppBoundClassTest, InvokeMethods) {
  // The expression on the left is expected to return the value on the right.
  static const std::string tests[] = {
    "example.echoValue(true)", "true",
    "example.echoValue(13)", "13",
    "example.echoValue(2.718)", "2.718",
    "example.echoValue('yes')", "'yes'",
    "example.echoValue()", "null",     // Too few arguments

    "example.echoType(false)", "true",
    "example.echoType(19)", "3.14159",
    "example.echoType(9.876)", "3.14159",
    "example.echoType('test string')", "'Success!'",
    "example.echoType()", "null",      // Too few arguments

    // Comparing floats that aren't integer-valued is usually problematic due
    // to rounding, but exact powers of 2 should also be safe.
    "example.plus(2.5, 18.0)", "20.5",
    "example.plus(2, 3.25)", "5.25",
    "example.plus(2, 3)", "5",
    "example.plus()", "null",             // Too few arguments
    "example.plus(1)", "null",            // Too few arguments
    "example.plus(1, 'test')", "null",    // Wrong argument type
    "example.plus('test', 2)", "null",    // Wrong argument type
    "example.plus('one', 'two')", "null", // Wrong argument type
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i+= 2) {
    std::string left = tests[i];
    std::string right = tests[i + 1];
    std::string js = BuildJSCondition(left, right);
    CheckJavaScriptSuccess(js);
  }

  std::string js = "example.my_value = 3.25; example.my_other_value = 1.25;";
  js.append(BuildJSCondition(
      "example.plus(example.my_value, example.my_other_value)", "4.5"));
  CheckJavaScriptSuccess(js);
}

// Tests that invoking a nonexistent method with no fallback method stops the
// script's execution
TEST_F(CppBoundClassTest,
       InvokeNonexistentMethodNoFallback) {
  std::string js = "example.nonExistentMethod();document.writeln('SUCCESS');";
  CheckJavaScriptFailure(js);
}

// Ensures existent methods can be invoked successfully when the fallback method
// is used
TEST_F(CppBoundClassWithFallbackMethodTest,
       InvokeExistentMethodsWithFallback) {
  std::string js = BuildJSCondition("example.echoValue(34)", "34");
  CheckJavaScriptSuccess(js);
}

}  // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/web_contents_preferences.h"

#include <algorithm>
#include <string>
#include <vector>

#include "atom/browser/native_window.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/web_preferences.h"
#include "native_mate/dictionary.h"
#include "net/base/filename_util.h"

#if defined(OS_WIN)
#include "ui/gfx/switches.h"
#endif

DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPreferences);

namespace atom {

// static
std::vector<WebContentsPreferences*> WebContentsPreferences::instances_;

WebContentsPreferences::WebContentsPreferences(
    content::WebContents* web_contents,
    const mate::Dictionary& web_preferences)
    : web_contents_(web_contents) {
  v8::Isolate* isolate = web_preferences.isolate();
  mate::Dictionary copied(isolate, web_preferences.GetHandle()->Clone());
  // Following fields should not be stored.
  copied.Delete("embedder");
  copied.Delete("isGuest");
  copied.Delete("session");

  mate::ConvertFromV8(isolate, copied.GetHandle(), &web_preferences_);
  web_contents->SetUserData(UserDataKey(), this);

  instances_.push_back(this);
}

WebContentsPreferences::~WebContentsPreferences() {
  instances_.erase(
      std::remove(instances_.begin(), instances_.end(), this),
      instances_.end());
}

void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
  web_preferences_.MergeDictionary(&extend);
}

// static
content::WebContents* WebContentsPreferences::GetWebContentsFromProcessID(
    int process_id) {
  for (WebContentsPreferences* preferences : instances_) {
    content::WebContents* web_contents = preferences->web_contents_;
    if (web_contents->GetRenderProcessHost()->GetID() == process_id)
      return web_contents;
  }
  return nullptr;
}

// static
void WebContentsPreferences::AppendExtraCommandLineSwitches(
    content::WebContents* web_contents, base::CommandLine* command_line) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  base::DictionaryValue& web_preferences = self->web_preferences_;

  bool b;
#if defined(OS_WIN)
  // Check if DirectWrite is disabled.
  if (web_preferences.GetBoolean(options::kDirectWrite, &b) && !b)
    command_line->AppendSwitch(::switches::kDisableDirectWrite);
#endif

  // Check if plugins are enabled.
  if (web_preferences.GetBoolean("plugins", &b) && b)
    command_line->AppendSwitch(switches::kEnablePlugins);

  // Experimental flags.
  if (web_preferences.GetBoolean(options::kExperimentalFeatures, &b) && b)
    command_line->AppendSwitch(
        ::switches::kEnableExperimentalWebPlatformFeatures);
  if (web_preferences.GetBoolean(options::kExperimentalCanvasFeatures, &b) && b)
    command_line->AppendSwitch(::switches::kEnableExperimentalCanvasFeatures);

  // Check if we have node integration specified.
  bool node_integration = true;
  web_preferences.GetBoolean(options::kNodeIntegration, &node_integration);
  command_line->AppendSwitchASCII(switches::kNodeIntegration,
                                  node_integration ? "true" : "false");

  // The preload script.
  base::FilePath::StringType preload;
  if (web_preferences.GetString(options::kPreloadScript, &preload)) {
    if (base::FilePath(preload).IsAbsolute())
      command_line->AppendSwitchNative(switches::kPreloadScript, preload);
    else
      LOG(ERROR) << "preload script must have absolute path.";
  } else if (web_preferences.GetString(options::kPreloadURL, &preload)) {
    // Translate to file path if there is "preload-url" option.
    base::FilePath preload_path;
    if (net::FileURLToFilePath(GURL(preload), &preload_path))
      command_line->AppendSwitchPath(switches::kPreloadScript, preload_path);
    else
      LOG(ERROR) << "preload url must be file:// protocol.";
  }

  // --background-color.
  std::string color;
  if (web_preferences.GetString(options::kBackgroundColor, &color))
    command_line->AppendSwitchASCII(switches::kBackgroundColor, color);

  // The zoom factor.
  double zoom_factor = 1.0;
  if (web_preferences.GetDouble(options::kZoomFactor, &zoom_factor) &&
      zoom_factor != 1.0)
    command_line->AppendSwitchASCII(switches::kZoomFactor,
                                    base::DoubleToString(zoom_factor));

  // --guest-instance-id, which is used to identify guest WebContents.
  int guest_instance_id;
  if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id))
    command_line->AppendSwitchASCII(switches::kGuestInstanceID,
                                    base::IntToString(guest_instance_id));

  // Pass the opener's window id.
  int opener_id;
  if (web_preferences.GetInteger(options::kOpenerID, &opener_id))
    command_line->AppendSwitchASCII(switches::kOpenerID,
                                    base::IntToString(opener_id));

#if defined(OS_MACOSX)
  // Enable scroll bounce.
  bool scroll_bounce;
  if (web_preferences.GetBoolean(options::kScrollBounce, &scroll_bounce) &&
      scroll_bounce)
    command_line->AppendSwitch(switches::kScrollBounce);
#endif

  // Enable blink features.
  std::string blink_features;
  if (web_preferences.GetString(options::kBlinkFeatures, &blink_features))
    command_line->AppendSwitchASCII(::switches::kEnableBlinkFeatures,
                                    blink_features);

  NativeWindow* window = NativeWindow::FromWebContents(web_contents);

  // Inherit initial visibilty state from parent window in webviews
  if (guest_instance_id && !window) {
    auto manager = WebViewManager::GetWebViewManager(web_contents);
    if (manager) {
      content::WebContents* embedder = manager->GetEmbedder(guest_instance_id);
      if (embedder)
        window = NativeWindow::FromWebContents(embedder);
    }
  }

  // The initial visibility state.
  if (window) {
    bool visible = window->IsVisible() && !window->IsMinimized();
    if (!visible)  // Default state is visible.
      command_line->AppendSwitch("hidden-page");
  }
}

// static
void WebContentsPreferences::OverrideWebkitPrefs(
    content::WebContents* web_contents, content::WebPreferences* prefs) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  bool b;
  if (self->web_preferences_.GetBoolean("javascript", &b))
    prefs->javascript_enabled = b;
  if (self->web_preferences_.GetBoolean("images", &b))
    prefs->images_enabled = b;
  if (self->web_preferences_.GetBoolean("textAreasAreResizable", &b))
    prefs->text_areas_are_resizable = b;
  if (self->web_preferences_.GetBoolean("webgl", &b))
    prefs->experimental_webgl_enabled = b;
  if (self->web_preferences_.GetBoolean("webSecurity", &b)) {
    prefs->web_security_enabled = b;
    prefs->allow_displaying_insecure_content = !b;
    prefs->allow_running_insecure_content = !b;
  }
  if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", &b))
    prefs->allow_displaying_insecure_content = b;
  if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b))
    prefs->allow_running_insecure_content = b;
  const base::DictionaryValue* fonts = nullptr;
  if (self->web_preferences_.GetDictionary("defaultFontFamily", &fonts)) {
    base::string16 font;
    if (fonts->GetString("standard", &font))
      prefs->standard_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("serif", &font))
      prefs->serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("sansSerif", &font))
      prefs->sans_serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("monospace", &font))
      prefs->fixed_font_family_map[content::kCommonScript] = font;
  }
  int size;
  if (self->web_preferences_.GetInteger("defaultFontSize", &size))
    prefs->default_font_size = size;
  if (self->web_preferences_.GetInteger("defaultMonospaceFontSize", &size))
    prefs->default_fixed_font_size = size;
  if (self->web_preferences_.GetInteger("minimumFontSize", &size))
    prefs->minimum_font_size = size;
  std::string encoding;
  if (self->web_preferences_.GetString("defaultEncoding", &encoding))
    prefs->default_encoding = encoding;
}

}  // namespace atom
<commit_msg>Tweak comment<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/web_contents_preferences.h"

#include <algorithm>
#include <string>
#include <vector>

#include "atom/browser/native_window.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/web_preferences.h"
#include "native_mate/dictionary.h"
#include "net/base/filename_util.h"

#if defined(OS_WIN)
#include "ui/gfx/switches.h"
#endif

DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPreferences);

namespace atom {

// static
std::vector<WebContentsPreferences*> WebContentsPreferences::instances_;

WebContentsPreferences::WebContentsPreferences(
    content::WebContents* web_contents,
    const mate::Dictionary& web_preferences)
    : web_contents_(web_contents) {
  v8::Isolate* isolate = web_preferences.isolate();
  mate::Dictionary copied(isolate, web_preferences.GetHandle()->Clone());
  // Following fields should not be stored.
  copied.Delete("embedder");
  copied.Delete("isGuest");
  copied.Delete("session");

  mate::ConvertFromV8(isolate, copied.GetHandle(), &web_preferences_);
  web_contents->SetUserData(UserDataKey(), this);

  instances_.push_back(this);
}

WebContentsPreferences::~WebContentsPreferences() {
  instances_.erase(
      std::remove(instances_.begin(), instances_.end(), this),
      instances_.end());
}

void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
  web_preferences_.MergeDictionary(&extend);
}

// static
content::WebContents* WebContentsPreferences::GetWebContentsFromProcessID(
    int process_id) {
  for (WebContentsPreferences* preferences : instances_) {
    content::WebContents* web_contents = preferences->web_contents_;
    if (web_contents->GetRenderProcessHost()->GetID() == process_id)
      return web_contents;
  }
  return nullptr;
}

// static
void WebContentsPreferences::AppendExtraCommandLineSwitches(
    content::WebContents* web_contents, base::CommandLine* command_line) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  base::DictionaryValue& web_preferences = self->web_preferences_;

  bool b;
#if defined(OS_WIN)
  // Check if DirectWrite is disabled.
  if (web_preferences.GetBoolean(options::kDirectWrite, &b) && !b)
    command_line->AppendSwitch(::switches::kDisableDirectWrite);
#endif

  // Check if plugins are enabled.
  if (web_preferences.GetBoolean("plugins", &b) && b)
    command_line->AppendSwitch(switches::kEnablePlugins);

  // Experimental flags.
  if (web_preferences.GetBoolean(options::kExperimentalFeatures, &b) && b)
    command_line->AppendSwitch(
        ::switches::kEnableExperimentalWebPlatformFeatures);
  if (web_preferences.GetBoolean(options::kExperimentalCanvasFeatures, &b) && b)
    command_line->AppendSwitch(::switches::kEnableExperimentalCanvasFeatures);

  // Check if we have node integration specified.
  bool node_integration = true;
  web_preferences.GetBoolean(options::kNodeIntegration, &node_integration);
  command_line->AppendSwitchASCII(switches::kNodeIntegration,
                                  node_integration ? "true" : "false");

  // The preload script.
  base::FilePath::StringType preload;
  if (web_preferences.GetString(options::kPreloadScript, &preload)) {
    if (base::FilePath(preload).IsAbsolute())
      command_line->AppendSwitchNative(switches::kPreloadScript, preload);
    else
      LOG(ERROR) << "preload script must have absolute path.";
  } else if (web_preferences.GetString(options::kPreloadURL, &preload)) {
    // Translate to file path if there is "preload-url" option.
    base::FilePath preload_path;
    if (net::FileURLToFilePath(GURL(preload), &preload_path))
      command_line->AppendSwitchPath(switches::kPreloadScript, preload_path);
    else
      LOG(ERROR) << "preload url must be file:// protocol.";
  }

  // --background-color.
  std::string color;
  if (web_preferences.GetString(options::kBackgroundColor, &color))
    command_line->AppendSwitchASCII(switches::kBackgroundColor, color);

  // The zoom factor.
  double zoom_factor = 1.0;
  if (web_preferences.GetDouble(options::kZoomFactor, &zoom_factor) &&
      zoom_factor != 1.0)
    command_line->AppendSwitchASCII(switches::kZoomFactor,
                                    base::DoubleToString(zoom_factor));

  // --guest-instance-id, which is used to identify guest WebContents.
  int guest_instance_id;
  if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id))
    command_line->AppendSwitchASCII(switches::kGuestInstanceID,
                                    base::IntToString(guest_instance_id));

  // Pass the opener's window id.
  int opener_id;
  if (web_preferences.GetInteger(options::kOpenerID, &opener_id))
    command_line->AppendSwitchASCII(switches::kOpenerID,
                                    base::IntToString(opener_id));

#if defined(OS_MACOSX)
  // Enable scroll bounce.
  bool scroll_bounce;
  if (web_preferences.GetBoolean(options::kScrollBounce, &scroll_bounce) &&
      scroll_bounce)
    command_line->AppendSwitch(switches::kScrollBounce);
#endif

  // Enable blink features.
  std::string blink_features;
  if (web_preferences.GetString(options::kBlinkFeatures, &blink_features))
    command_line->AppendSwitchASCII(::switches::kEnableBlinkFeatures,
                                    blink_features);

  NativeWindow* window = NativeWindow::FromWebContents(web_contents);

  // Use parent window for webviews
  if (guest_instance_id && !window) {
    auto manager = WebViewManager::GetWebViewManager(web_contents);
    if (manager) {
      content::WebContents* embedder = manager->GetEmbedder(guest_instance_id);
      if (embedder)
        window = NativeWindow::FromWebContents(embedder);
    }
  }

  // The initial visibility state.
  if (window) {
    bool visible = window->IsVisible() && !window->IsMinimized();
    if (!visible)  // Default state is visible.
      command_line->AppendSwitch("hidden-page");
  }
}

// static
void WebContentsPreferences::OverrideWebkitPrefs(
    content::WebContents* web_contents, content::WebPreferences* prefs) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  bool b;
  if (self->web_preferences_.GetBoolean("javascript", &b))
    prefs->javascript_enabled = b;
  if (self->web_preferences_.GetBoolean("images", &b))
    prefs->images_enabled = b;
  if (self->web_preferences_.GetBoolean("textAreasAreResizable", &b))
    prefs->text_areas_are_resizable = b;
  if (self->web_preferences_.GetBoolean("webgl", &b))
    prefs->experimental_webgl_enabled = b;
  if (self->web_preferences_.GetBoolean("webSecurity", &b)) {
    prefs->web_security_enabled = b;
    prefs->allow_displaying_insecure_content = !b;
    prefs->allow_running_insecure_content = !b;
  }
  if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", &b))
    prefs->allow_displaying_insecure_content = b;
  if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b))
    prefs->allow_running_insecure_content = b;
  const base::DictionaryValue* fonts = nullptr;
  if (self->web_preferences_.GetDictionary("defaultFontFamily", &fonts)) {
    base::string16 font;
    if (fonts->GetString("standard", &font))
      prefs->standard_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("serif", &font))
      prefs->serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("sansSerif", &font))
      prefs->sans_serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("monospace", &font))
      prefs->fixed_font_family_map[content::kCommonScript] = font;
  }
  int size;
  if (self->web_preferences_.GetInteger("defaultFontSize", &size))
    prefs->default_font_size = size;
  if (self->web_preferences_.GetInteger("defaultMonospaceFontSize", &size))
    prefs->default_fixed_font_size = size;
  if (self->web_preferences_.GetInteger("minimumFontSize", &size))
    prefs->minimum_font_size = size;
  std::string encoding;
  if (self->web_preferences_.GetString("defaultEncoding", &encoding))
    prefs->default_encoding = encoding;
}

}  // namespace atom
<|endoftext|>


<commit_before>/*
 * StatsProbe.cpp
 *
 *  Created on:
 *      Author: garkenyon
 */

#include "MPITestProbe.hpp"
#include "../PetaVision/src/io/StatsProbe.hpp"
#include "../PetaVision/src/layers/HyPerLayer.hpp"
#include <float.h>      // FLT_MAX/MIN
#include <string.h>

namespace PV {

/**
 * @filename
 * @type
 * @msg
 */
MPITestProbe::MPITestProbe(const char * filename, HyPerCol * hc, PVBufType buf_type, const char * msg)
   : StatsProbe(filename, hc, buf_type, msg)
{
	cumSum = 0.0f;
	cumAvg = 0.0f;
}

/**
 * @type
 * @msg
 */
MPITestProbe::MPITestProbe(PVBufType buf_type, const char * msg)
   : StatsProbe(buf_type, msg)
{
	cumSum = 0.0f;
	cumAvg = 0.0f;
}

/**
 * @time
 * @l
 */
int MPITestProbe::outputState(float time, HyPerLayer * l)
{
	int status = StatsProbe::outputState(time, l);

	fprintf(fp, "%s t==%9.3f cumSum==%f cumAvg==%f \n", msg, time,
              (float) cumSum, (float) cumAvg);
	fflush(fp);

	return 0;
}

}
<commit_msg>added functionality to probe<commit_after>/*
 * StatsProbe.cpp
 *
 *  Created on:
 *      Author: garkenyon
 */

#include "MPITestProbe.hpp"
#include "../PetaVision/src/io/StatsProbe.hpp"
#include "../PetaVision/src/layers/HyPerLayer.hpp"
#include <float.h>      // FLT_MAX/MIN
#include <string.h>

namespace PV {

/**
 * @filename
 * @type
 * @msg
 */
MPITestProbe::MPITestProbe(const char * filename, HyPerCol * hc, PVBufType buf_type, const char * msg)
   : StatsProbe(filename, hc, buf_type, msg)
{
	cumSum = 0.0f;
	cumAvg = 0.0f;
}

/**
 * @type
 * @msg
 */
MPITestProbe::MPITestProbe(PVBufType buf_type, const char * msg)
   : StatsProbe(buf_type, msg)
{
	cumSum = 0.0f;
	cumAvg = 0.0f;
}

/**
 * @time
 * @l
 */
int MPITestProbe::outputState(float time, HyPerLayer * l)
{
	int status = StatsProbe::outputState(time, l);
	cumSum += sum;
	cumAvg += avg;
	fprintf(fp, "%s t==%9.3f cumSum==%f cumAvg==%f \n", msg, time,
              (float) cumSum, (float) cumAvg);
	fflush(fp);

	return 0;
}

}
<|endoftext|>


<commit_before>#include "AboutView.h"
#include "Colors.h"
#include <Application.h>
#include <stdio.h>
#include "Settings.h"

SAboutView::SAboutView (BRect rect, BBitmap *becasso, BBitmap *sum, bool startup)
: BView (rect, "SAboutView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW)
{
	fBecasso = becasso;
	fSum = sum;
	SetViewColor (Grey28);
	fStartup = startup;
	fAddOnString[0] = 0;
	url = NULL;
	doc = NULL;
	if (!startup)
	{
		url = new BButton (BRect (126, 178, 196, 196), "url", lstring (1, "URL"), new BMessage ('aURL'));
		doc = new BButton (BRect (204, 178, 274, 196), "doc", lstring (2, "Manual"), new BMessage ('aDOC'));
		url->SetTarget (be_app);
		doc->SetTarget (be_app);
		AddChild (url);
		AddChild (doc);
	}
}

SAboutView::~SAboutView ()
{
	delete fBecasso;
	delete fSum;
}

void SAboutView::Draw (BRect updateRect)
{
	if (updateRect != BRect (85, 170, 250, 195))
	{
		if (fBecasso)
			DrawBitmap (fBecasso, BPoint (25, 10));
		if (fSum)
			DrawBitmap (fSum, BPoint (10, 115));
		SetLowColor (Grey28);
		SetHighColor (Grey8);
		char verstring[80];
		extern const char *Version;
		extern int gGlobalAlpha;
		extern char gAlphaMask[128];
		SetFontSize (13);
		sprintf (verstring, lstring (3, "Version %s, built %s"), Version, __DATE__);
	//	sprintf (verstring, "MacWorld Demo Version");
		DrawString (verstring, BPoint (85, 124));
		SetFontSize (11);
		DrawString ("© 1997-2001 ∑ Sum Software", BPoint (85, 138));
		if (!gGlobalAlpha)
		{
			SetHighColor (Red);
			SetFontSize (13);
			DrawString (lstring (4, "Unregistered Version"), BPoint (85, 155));
		}
		else
		{
			SetHighColor (Grey8);
			DrawString (lstring (7, "Registered to"), BPoint (85, 152));
			SetHighColor (Black);
			SetFontSize (12);
			DrawString (gAlphaMask, BPoint (85, 168));
		}
	//	DrawString ("Add-On developers beta version", BPoint (85, 158));
	//	DrawString ("This is a ", BPoint (85, 158));
	//	SetHighColor (Red);
	//	DrawString ("time limited");
	//	SetHighColor (Grey8);
	//	DrawString (" demo that will");
	//	DrawString ("stop working on January 1st, 1998", BPoint (85, 172));
	}
	if (fStartup)
	{
		SetLowColor (Grey28);
		SetHighColor (Grey8);
		SetFontSize (12);
		DrawString (lstring (5, "Initializing Add-Ons:"), BPoint (85, 182));
		SetFontSize (11);
		DrawString (fAddOnString, BPoint (85, 194));
	}
}

void SAboutView::SetInitString (const char *s)
{
	strcpy (fAddOnString, s);
//	printf ("Set to %s\n", s);
	Invalidate (BRect (85, 170, 250, 195));
}<commit_msg>Changed "Registered to" to "Released under the MIT license" on Haiku<commit_after>#include "AboutView.h"
#include "Colors.h"
#include <Application.h>
#include <stdio.h>
#include "Settings.h"

SAboutView::SAboutView (BRect rect, BBitmap *becasso, BBitmap *sum, bool startup)
: BView (rect, "SAboutView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW)
{
	fBecasso = becasso;
	fSum = sum;
	SetViewColor (Grey28);
	fStartup = startup;
	fAddOnString[0] = 0;
	url = NULL;
	doc = NULL;
	if (!startup)
	{
		url = new BButton (BRect (126, 178, 196, 196), "url", lstring (1, "URL"), new BMessage ('aURL'));
		doc = new BButton (BRect (204, 178, 274, 196), "doc", lstring (2, "Manual"), new BMessage ('aDOC'));
		url->SetTarget (be_app);
		doc->SetTarget (be_app);
		AddChild (url);
		AddChild (doc);
	}
}

SAboutView::~SAboutView ()
{
	delete fBecasso;
	delete fSum;
}

void SAboutView::Draw (BRect updateRect)
{
	if (updateRect != BRect (85, 170, 250, 195))
	{
		if (fBecasso)
			DrawBitmap (fBecasso, BPoint (25, 10));
		if (fSum)
			DrawBitmap (fSum, BPoint (10, 115));
		SetLowColor (Grey28);
		SetHighColor (Grey8);
		char verstring[80];
		extern const char *Version;
		extern int gGlobalAlpha;
		extern char gAlphaMask[128];
		SetFontSize (13);
		sprintf (verstring, lstring (3, "Version %s, built %s"), Version, __DATE__);
	//	sprintf (verstring, "MacWorld Demo Version");
		DrawString (verstring, BPoint (85, 124));
		SetFontSize (11);
		DrawString ("© 1997-2001 ∑ Sum Software", BPoint (85, 138));
		if (!gGlobalAlpha)
		{
			SetHighColor (Red);
			SetFontSize (13);
			DrawString (lstring (4, "Unregistered Version"), BPoint (85, 155));
		}
		else
		{
			SetHighColor (Grey8);
			#if defined(__HAIKU__)
			DrawString ("Released under the MIT license", BPoint (85, 152));
			#else
			DrawString (lstring (7, "Registered to"), BPoint (85, 152));
			SetHighColor (Black);
			SetFontSize (12);
			DrawString (gAlphaMask, BPoint (85, 168));
			#endif
		}
	//	DrawString ("Add-On developers beta version", BPoint (85, 158));
	//	DrawString ("This is a ", BPoint (85, 158));
	//	SetHighColor (Red);
	//	DrawString ("time limited");
	//	SetHighColor (Grey8);
	//	DrawString (" demo that will");
	//	DrawString ("stop working on January 1st, 1998", BPoint (85, 172));
	}
	if (fStartup)
	{
		SetLowColor (Grey28);
		SetHighColor (Grey8);
		SetFontSize (12);
		DrawString (lstring (5, "Initializing Add-Ons:"), BPoint (85, 182));
		SetFontSize (11);
		DrawString (fAddOnString, BPoint (85, 194));
	}
}

void SAboutView::SetInitString (const char *s)
{
	strcpy (fAddOnString, s);
//	printf ("Set to %s\n", s);
	Invalidate (BRect (85, 170, 250, 195));
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/

#include "formclasswizardparameters.h"
#include "formtemplatewizardpage.h"

#include <utils/codegeneration.h>

#include <QtCore/QTextStream>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>

static const char *uiMemberC = "m_ui";
static const char *uiNamespaceC = "Ui";

namespace Designer {
namespace Internal {

FormClassWizardParameters::FormClassWizardParameters() :
    embedding(PointerAggregatedUiClass),
    languageChange(true)
{
}

bool FormClassWizardParameters::generateCpp(QString *header, QString *source, int indentation) const
{
    const QString indent = QString(indentation, QLatin1Char(' '));
    QString formBaseClass;
    QString uiClassName;
    if (!FormTemplateWizardPage::getUIXmlData(uiTemplate, &formBaseClass, &uiClassName)) {
        qWarning("Unable to determine the form base class from %s.", uiTemplate.toUtf8().constData());
        return false;
    }

    // Build the ui class (Ui::Foo) name relative to the namespace (which is the same):
    const QString colonColon = QLatin1String("::");
    const int lastSeparator = uiClassName.lastIndexOf(colonColon);
    if (lastSeparator != -1)
        uiClassName.remove(0, lastSeparator + colonColon.size());
    uiClassName.insert(0, QLatin1String(uiNamespaceC) + colonColon);

    // Do we have namespaces?
    QStringList namespaceList = className.split(colonColon);
    if (namespaceList.empty()) // Paranoia!
        return false;

    const QString unqualifiedClassName = namespaceList.takeLast();

    // Include guards
    const QString guard = Core::Utils::headerGuard(headerFile);

    QString uiInclude = QLatin1String("ui_");
    uiInclude += QFileInfo(uiFile).baseName();
    uiInclude += QLatin1String(".h");

    // 1) Header file
    QTextStream headerStr(header);
    headerStr << "#ifndef " << guard
              << "\n#define " <<  guard << '\n' << '\n';

    // Include 'ui_'
    if (embedding != PointerAggregatedUiClass) {
        Core::Utils::writeIncludeFileDirective(uiInclude, false, headerStr);
    } else {
        // Todo: Can we obtain the header from the code model for custom widgets?
        // Alternatively, from Designer.
        if (formBaseClass.startsWith(QLatin1Char('Q'))) {
            QString baseInclude = QLatin1String("QtGui/");
            baseInclude += formBaseClass;
            Core::Utils::writeIncludeFileDirective(baseInclude, true, headerStr);
        }
    }

    const QString namespaceIndent = Core::Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr);

    // Forward-declare the UI class
    if (embedding == PointerAggregatedUiClass) {
          headerStr << '\n'
                  << namespaceIndent << "namespace " <<  uiNamespaceC << " {\n"
                  << namespaceIndent << indent << "class " << FormTemplateWizardPage::stripNamespaces(uiClassName) << ";\n"
                  << namespaceIndent << "}\n";
    }

    // Class declaration
    headerStr << '\n' << namespaceIndent << "class " << unqualifiedClassName
              << " : public " << formBaseClass;
    if (embedding == InheritedUiClass) {
        headerStr << ", private " << uiClassName;
    }
    headerStr << " {\n" << namespaceIndent << indent << "Q_OBJECT\n"
              << namespaceIndent << indent << "Q_DISABLE_COPY(" << unqualifiedClassName << ")\n"
              << namespaceIndent << "public:\n"
              << namespaceIndent << indent << "explicit " << unqualifiedClassName << "(QWidget *parent = 0);\n";
    if (embedding == PointerAggregatedUiClass)
        headerStr << namespaceIndent << indent << "virtual ~" << unqualifiedClassName << "();\n";
    // retranslation
    if (languageChange)
        headerStr << '\n' << namespaceIndent << "protected:\n"
                  << namespaceIndent << indent << "virtual void changeEvent(QEvent *e);\n";
    // Member variable
    if (embedding != InheritedUiClass) {
        headerStr << '\n' << namespaceIndent << "private:\n"
                  << namespaceIndent << indent << uiClassName << ' ';
        if (embedding == PointerAggregatedUiClass)
            headerStr << '*';
        headerStr << uiMemberC << ";\n";
    }
    headerStr << namespaceIndent << "};\n\n";
    Core::Utils::writeClosingNameSpaces(namespaceList, indent, headerStr);
    headerStr << "#endif // "<<  guard << '\n';

    // 2) Source file
    QTextStream sourceStr(source);
    Core::Utils::writeIncludeFileDirective(headerFile, false, sourceStr);
    if (embedding == PointerAggregatedUiClass)
        Core::Utils::writeIncludeFileDirective(uiInclude, false, sourceStr);
    // NameSpaces(
    Core::Utils::writeOpeningNameSpaces(namespaceList, indent, sourceStr);
    // Constructor with setupUi
    sourceStr << '\n' << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName << "(QWidget *parent) :\n"
               << namespaceIndent << indent << formBaseClass << "(parent)";
    if (embedding == PointerAggregatedUiClass)
        sourceStr << ",\n"  << namespaceIndent << indent <<  uiMemberC << "(new " << uiClassName << ")\n";
    sourceStr <<  namespaceIndent << "{\n" <<  namespaceIndent << indent;
    if (embedding != InheritedUiClass)
        sourceStr << uiMemberC << (embedding == PointerAggregatedUiClass ? "->" : ".");
    sourceStr << "setupUi(this);\n" << namespaceIndent << "}\n";
    // Deleting destructor for ptr
    if (embedding == PointerAggregatedUiClass) {
        sourceStr << '\n' <<  namespaceIndent << unqualifiedClassName << "::~" << unqualifiedClassName
                  << "()\n" << namespaceIndent << "{\n"
                  << namespaceIndent << indent << "delete " << uiMemberC << ";\n"
                  << namespaceIndent << "}\n";
    }
    // retranslation
    if (languageChange) {
        sourceStr  << '\n' << namespaceIndent << "void " << unqualifiedClassName << "::" << "changeEvent(QEvent *e)\n"
        << namespaceIndent << "{\n"
        << namespaceIndent << indent << "switch (e->type()) {\n" << namespaceIndent << indent << "case QEvent::LanguageChange:\n"
        << namespaceIndent << indent << indent;
        if (embedding != InheritedUiClass)
            sourceStr << uiMemberC << (embedding == PointerAggregatedUiClass ? "->" : ".");
        sourceStr << "retranslateUi(this);\n"
                  << namespaceIndent << indent <<  indent << "break;\n"
                  << namespaceIndent << indent << "default:\n"
                  << namespaceIndent << indent << indent << "break;\n"
                  << namespaceIndent << indent << "}\n"
                  << namespaceIndent << "}\n";
    }
    Core::Utils::writeClosingNameSpaces(namespaceList, indent, sourceStr);
    return true;
}

} // namespace Internal
} // namespace Designer
<commit_msg>Fixes: Form Class Wizard: Generate call to base class implementation of changeEvent().<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/

#include "formclasswizardparameters.h"
#include "formtemplatewizardpage.h"

#include <utils/codegeneration.h>

#include <QtCore/QTextStream>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>

static const char *uiMemberC = "m_ui";
static const char *uiNamespaceC = "Ui";

namespace Designer {
namespace Internal {

FormClassWizardParameters::FormClassWizardParameters() :
    embedding(PointerAggregatedUiClass),
    languageChange(true)
{
}

bool FormClassWizardParameters::generateCpp(QString *header, QString *source, int indentation) const
{
    const QString indent = QString(indentation, QLatin1Char(' '));
    QString formBaseClass;
    QString uiClassName;
    if (!FormTemplateWizardPage::getUIXmlData(uiTemplate, &formBaseClass, &uiClassName)) {
        qWarning("Unable to determine the form base class from %s.", uiTemplate.toUtf8().constData());
        return false;
    }

    // Build the ui class (Ui::Foo) name relative to the namespace (which is the same):
    const QString colonColon = QLatin1String("::");
    const int lastSeparator = uiClassName.lastIndexOf(colonColon);
    if (lastSeparator != -1)
        uiClassName.remove(0, lastSeparator + colonColon.size());
    uiClassName.insert(0, QLatin1String(uiNamespaceC) + colonColon);

    // Do we have namespaces?
    QStringList namespaceList = className.split(colonColon);
    if (namespaceList.empty()) // Paranoia!
        return false;

    const QString unqualifiedClassName = namespaceList.takeLast();

    // Include guards
    const QString guard = Core::Utils::headerGuard(headerFile);

    QString uiInclude = QLatin1String("ui_");
    uiInclude += QFileInfo(uiFile).baseName();
    uiInclude += QLatin1String(".h");

    // 1) Header file
    QTextStream headerStr(header);
    headerStr << "#ifndef " << guard
              << "\n#define " <<  guard << '\n' << '\n';

    // Include 'ui_'
    if (embedding != PointerAggregatedUiClass) {
        Core::Utils::writeIncludeFileDirective(uiInclude, false, headerStr);
    } else {
        // Todo: Can we obtain the header from the code model for custom widgets?
        // Alternatively, from Designer.
        if (formBaseClass.startsWith(QLatin1Char('Q'))) {
            QString baseInclude = QLatin1String("QtGui/");
            baseInclude += formBaseClass;
            Core::Utils::writeIncludeFileDirective(baseInclude, true, headerStr);
        }
    }

    const QString namespaceIndent = Core::Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr);

    // Forward-declare the UI class
    if (embedding == PointerAggregatedUiClass) {
          headerStr << '\n'
                  << namespaceIndent << "namespace " <<  uiNamespaceC << " {\n"
                  << namespaceIndent << indent << "class " << FormTemplateWizardPage::stripNamespaces(uiClassName) << ";\n"
                  << namespaceIndent << "}\n";
    }

    // Class declaration
    headerStr << '\n' << namespaceIndent << "class " << unqualifiedClassName
              << " : public " << formBaseClass;
    if (embedding == InheritedUiClass) {
        headerStr << ", private " << uiClassName;
    }
    headerStr << " {\n" << namespaceIndent << indent << "Q_OBJECT\n"
              << namespaceIndent << indent << "Q_DISABLE_COPY(" << unqualifiedClassName << ")\n"
              << namespaceIndent << "public:\n"
              << namespaceIndent << indent << "explicit " << unqualifiedClassName << "(QWidget *parent = 0);\n";
    if (embedding == PointerAggregatedUiClass)
        headerStr << namespaceIndent << indent << "virtual ~" << unqualifiedClassName << "();\n";
    // retranslation
    if (languageChange)
        headerStr << '\n' << namespaceIndent << "protected:\n"
                  << namespaceIndent << indent << "virtual void changeEvent(QEvent *e);\n";
    // Member variable
    if (embedding != InheritedUiClass) {
        headerStr << '\n' << namespaceIndent << "private:\n"
                  << namespaceIndent << indent << uiClassName << ' ';
        if (embedding == PointerAggregatedUiClass)
            headerStr << '*';
        headerStr << uiMemberC << ";\n";
    }
    headerStr << namespaceIndent << "};\n\n";
    Core::Utils::writeClosingNameSpaces(namespaceList, indent, headerStr);
    headerStr << "#endif // "<<  guard << '\n';

    // 2) Source file
    QTextStream sourceStr(source);
    Core::Utils::writeIncludeFileDirective(headerFile, false, sourceStr);
    if (embedding == PointerAggregatedUiClass)
        Core::Utils::writeIncludeFileDirective(uiInclude, false, sourceStr);
    // NameSpaces(
    Core::Utils::writeOpeningNameSpaces(namespaceList, indent, sourceStr);
    // Constructor with setupUi
    sourceStr << '\n' << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName << "(QWidget *parent) :\n"
               << namespaceIndent << indent << formBaseClass << "(parent)";
    if (embedding == PointerAggregatedUiClass)
        sourceStr << ",\n"  << namespaceIndent << indent <<  uiMemberC << "(new " << uiClassName << ")\n";
    sourceStr <<  namespaceIndent << "{\n" <<  namespaceIndent << indent;
    if (embedding != InheritedUiClass)
        sourceStr << uiMemberC << (embedding == PointerAggregatedUiClass ? "->" : ".");
    sourceStr << "setupUi(this);\n" << namespaceIndent << "}\n";
    // Deleting destructor for ptr
    if (embedding == PointerAggregatedUiClass) {
        sourceStr << '\n' <<  namespaceIndent << unqualifiedClassName << "::~" << unqualifiedClassName
                  << "()\n" << namespaceIndent << "{\n"
                  << namespaceIndent << indent << "delete " << uiMemberC << ";\n"
                  << namespaceIndent << "}\n";
    }
    // retranslation
    if (languageChange) {
        sourceStr  << '\n' << namespaceIndent << "void " << unqualifiedClassName << "::" << "changeEvent(QEvent *e)\n"
        << namespaceIndent << "{\n"
        << namespaceIndent << indent << formBaseClass << "::changeEvent(e);\n"
        << namespaceIndent << indent << "switch (e->type()) {\n" << namespaceIndent << indent << "case QEvent::LanguageChange:\n"
        << namespaceIndent << indent << indent;
        if (embedding != InheritedUiClass)
            sourceStr << uiMemberC << (embedding == PointerAggregatedUiClass ? "->" : ".");
        sourceStr << "retranslateUi(this);\n"
                  << namespaceIndent << indent <<  indent << "break;\n"
                  << namespaceIndent << indent << "default:\n"
                  << namespaceIndent << indent << indent << "break;\n"
                  << namespaceIndent << indent << "}\n"
                  << namespaceIndent << "}\n";
    }
    Core::Utils::writeClosingNameSpaces(namespaceList, indent, sourceStr);
    return true;
}

} // namespace Internal
} // namespace Designer
<|endoftext|>


<commit_before>#include "gprop.h"

bool siren_gprop_install(mrb_state* mrb, struct RClass* rclass)
{
  rclass = mrb_define_module(mrb, "GProp");
  mrb_define_class_method(mrb, rclass, "volume", siren_gprop_volume, ARGS_REQ(1));
  mrb_define_class_method(mrb, rclass, "cog",    siren_gprop_cog,    ARGS_REQ(1));
  mrb_define_class_method(mrb, rclass, "area",   siren_gprop_area,   ARGS_REQ(1));
  return true;
}

mrb_value siren_gprop_volume(mrb_state* mrb, mrb_value self)
{
  mrb_value target;
  int argc = mrb_get_args(mrb, "o", &target);

  TopoDS_Shape* shape = siren_shape_get(mrb, target);

  GProp_GProps gprops;
  BRepGProp::VolumeProperties(*shape, gprops);
  Standard_Real vol = gprops.Mass();

  return mrb_float_value(mrb, (mrb_float)vol);
}

mrb_value siren_gprop_cog(mrb_state* mrb, mrb_value self)
{
  mrb_value target;
  int argc = mrb_get_args(mrb, "o", &target);

  TopoDS_Shape* shape = siren_shape_get(mrb, target);

  GProp_GProps gprops;
  BRepGProp::VolumeProperties(*shape, gprops);
  gp_Pnt cog = gprops.CentreOfMass();

  return siren_vec_new(mrb, cog.X(), cog.Y(), cog.Z());
}

mrb_value siren_gprop_area(mrb_state* mrb, mrb_value self)
{
  mrb_value target;
  int argc = mrb_get_args(mrb, "o", &target);

  TopoDS_Shape* shape = siren_shape_get(mrb, target);

  GProp_GProps System;
  BRepGProp::SurfaceProperties(*shape, System);
  Standard_Real Area = System.Mass();

  return mrb_float_value(mrb, Area);
}

<commit_msg>Refactored.<commit_after>#include "gprop.h"

bool siren_gprop_install(mrb_state* mrb, struct RClass* rclass)
{
  rclass = mrb_define_module(mrb, "GProp");
  mrb_define_class_method(mrb, rclass, "volume", siren_gprop_volume, ARGS_REQ(1));
  mrb_define_class_method(mrb, rclass, "cog",    siren_gprop_cog,    ARGS_REQ(1));
  mrb_define_class_method(mrb, rclass, "area",   siren_gprop_area,   ARGS_REQ(1));
  return true;
}

mrb_value siren_gprop_volume(mrb_state* mrb, mrb_value self)
{
  mrb_value target;
  int argc = mrb_get_args(mrb, "o", &target);

  TopoDS_Shape* shape = siren_shape_get(mrb, target);

  GProp_GProps gprops;
  BRepGProp::VolumeProperties(*shape, gprops);
  Standard_Real vol = gprops.Mass();

  return mrb_float_value(mrb, (mrb_float)vol);
}

mrb_value siren_gprop_cog(mrb_state* mrb, mrb_value self)
{
  mrb_value target;
  int argc = mrb_get_args(mrb, "o", &target);

  TopoDS_Shape* shape = siren_shape_get(mrb, target);

  GProp_GProps gprops;
  BRepGProp::VolumeProperties(*shape, gprops);
  gp_Pnt cog = gprops.CentreOfMass();

  return siren_vec_new(mrb, cog.X(), cog.Y(), cog.Z());
}

mrb_value siren_gprop_area(mrb_state* mrb, mrb_value self)
{
  mrb_value target;
  int argc = mrb_get_args(mrb, "o", &target);

  TopoDS_Shape* shape = siren_shape_get(mrb, target);

  GProp_GProps gprops;
  BRepGProp::SurfaceProperties(*shape, gprops);
  Standard_Real area = gprops.Mass();

  return mrb_float_value(mrb, area);
}

<|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 "webkit/glue/plugins/plugin_lib.h"

#include <dlfcn.h>
#include <elf.h>

#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "webkit/glue/plugins/plugin_list.h"

// These headers must be included in this order to make the declaration gods
// happy.
#include "base/third_party/nspr/prcpucfg_linux.h"

namespace {

// Copied from nsplugindefs.h instead of including the file since it has a bunch
// of dependencies.
enum nsPluginVariable {
  nsPluginVariable_NameString        = 1,
  nsPluginVariable_DescriptionString = 2
};

// Read the ELF header and return true if it is usable on
// the current architecture (e.g. 32-bit ELF on 32-bit build).
// Returns false on other errors as well.
bool ELFMatchesCurrentArchitecture(const FilePath& filename) {
  FILE* file = fopen(filename.value().c_str(), "rb");
  if (!file)
    return false;

  char buffer[5];
  if (fread(buffer, 5, 1, file) != 1) {
    fclose(file);
    return false;
  }
  fclose(file);

  if (buffer[0] != ELFMAG0 ||
      buffer[1] != ELFMAG1 ||
      buffer[2] != ELFMAG2 ||
      buffer[3] != ELFMAG3) {
    // Not an ELF file, perhaps?
    return false;
  }

  int elf_class = buffer[EI_CLASS];
#if defined(ARCH_CPU_32_BITS)
  if (elf_class == ELFCLASS32)
    return true;
#elif defined(ARCH_CPU_64_BITS)
  if (elf_class == ELFCLASS64)
    return true;
#endif

  return false;
}

// TODO(thestig) This is a hack to work around the crash in bug 25245. Remove
// this once we read plugins out of process.
bool SkipPluginUnloadHack(const WebPluginInfo& info) {
  std::string filename = info.path.BaseName().value();
  return (filename.find("npo3dautoplugin") != std::string::npos);  // O3D
}

}  // anonymous namespace
namespace NPAPI {

bool PluginLib::ReadWebPluginInfo(const FilePath& filename,
                                  WebPluginInfo* info) {
  // The file to reference is:
  // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUnix.cpp

  // Skip files that aren't appropriate for our architecture.
  if (!ELFMatchesCurrentArchitecture(filename))
    return false;

  void* dl = base::LoadNativeLibrary(filename);
  if (!dl)
    return false;

  info->path = filename;

  // See comments in plugin_lib_mac regarding this symbol.
  typedef const char* (*NP_GetMimeDescriptionType)();
  NP_GetMimeDescriptionType NP_GetMIMEDescription =
      reinterpret_cast<NP_GetMimeDescriptionType>(
          dlsym(dl, "NP_GetMIMEDescription"));
  const char* mime_description = NULL;
  if (NP_GetMIMEDescription)
    mime_description = NP_GetMIMEDescription();

  if (mime_description)
    ParseMIMEDescription(mime_description, &info->mime_types);

  // The plugin name and description live behind NP_GetValue calls.
  typedef NPError (*NP_GetValueType)(void* unused,
                                     nsPluginVariable variable,
                                     void* value_out);
  NP_GetValueType NP_GetValue =
      reinterpret_cast<NP_GetValueType>(dlsym(dl, "NP_GetValue"));
  if (NP_GetValue) {
    const char* name = NULL;
    NP_GetValue(NULL, nsPluginVariable_NameString, &name);
    if (name)
      info->name = UTF8ToWide(name);

    const char* description = NULL;
    NP_GetValue(NULL, nsPluginVariable_DescriptionString, &description);
    if (description)
      info->desc = UTF8ToWide(description);
  }

  if (!SkipPluginUnloadHack(*info))
    base::UnloadNativeLibrary(dl);

  return true;
}

// static
void PluginLib::ParseMIMEDescription(
    const std::string& description,
    std::vector<WebPluginMimeType>* mime_types) {
  // We parse the description here into WebPluginMimeType structures.
  // Naively from the NPAPI docs you'd think you could use
  // string-splitting, but the Firefox parser turns out to do something
  // different: find the first colon, then the second, then a semi.
  //
  // See ParsePluginMimeDescription near
  // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUtils.h#53

  std::string::size_type ofs = 0;
  for (;;) {
    WebPluginMimeType mime_type;

    std::string::size_type end = description.find(':', ofs);
    if (end == std::string::npos)
      break;
    mime_type.mime_type = description.substr(ofs, end - ofs);
    ofs = end + 1;

    end = description.find(':', ofs);
    if (end == std::string::npos)
      break;
    const std::string extensions = description.substr(ofs, end - ofs);
    SplitString(extensions, ',', &mime_type.file_extensions);
    ofs = end + 1;

    end = description.find(';', ofs);
    // It's ok for end to run off the string here.  If there's no
    // trailing semicolon we consume the remainder of the string.
    if (end != std::string::npos) {
      mime_type.description = UTF8ToWide(description.substr(ofs, end - ofs));
    } else {
      mime_type.description = UTF8ToWide(description.substr(ofs));
    }
    mime_types->push_back(mime_type);
    if (end == std::string::npos)
      break;
    ofs = end + 1;
  }
}

}  // namespace NPAPI
<commit_msg>linux: Do not unload plugin in the browser process, it's not safe.<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 "webkit/glue/plugins/plugin_lib.h"

#include <dlfcn.h>
#include <elf.h>

#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "webkit/glue/plugins/plugin_list.h"

// These headers must be included in this order to make the declaration gods
// happy.
#include "base/third_party/nspr/prcpucfg_linux.h"

namespace {

// Copied from nsplugindefs.h instead of including the file since it has a bunch
// of dependencies.
enum nsPluginVariable {
  nsPluginVariable_NameString        = 1,
  nsPluginVariable_DescriptionString = 2
};

// Read the ELF header and return true if it is usable on
// the current architecture (e.g. 32-bit ELF on 32-bit build).
// Returns false on other errors as well.
bool ELFMatchesCurrentArchitecture(const FilePath& filename) {
  FILE* file = fopen(filename.value().c_str(), "rb");
  if (!file)
    return false;

  char buffer[5];
  if (fread(buffer, 5, 1, file) != 1) {
    fclose(file);
    return false;
  }
  fclose(file);

  if (buffer[0] != ELFMAG0 ||
      buffer[1] != ELFMAG1 ||
      buffer[2] != ELFMAG2 ||
      buffer[3] != ELFMAG3) {
    // Not an ELF file, perhaps?
    return false;
  }

  int elf_class = buffer[EI_CLASS];
#if defined(ARCH_CPU_32_BITS)
  if (elf_class == ELFCLASS32)
    return true;
#elif defined(ARCH_CPU_64_BITS)
  if (elf_class == ELFCLASS64)
    return true;
#endif

  return false;
}

}  // anonymous namespace
namespace NPAPI {

bool PluginLib::ReadWebPluginInfo(const FilePath& filename,
                                  WebPluginInfo* info) {
  // The file to reference is:
  // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUnix.cpp

  // Skip files that aren't appropriate for our architecture.
  if (!ELFMatchesCurrentArchitecture(filename))
    return false;

  void* dl = base::LoadNativeLibrary(filename);
  if (!dl)
    return false;

  info->path = filename;

  // See comments in plugin_lib_mac regarding this symbol.
  typedef const char* (*NP_GetMimeDescriptionType)();
  NP_GetMimeDescriptionType NP_GetMIMEDescription =
      reinterpret_cast<NP_GetMimeDescriptionType>(
          dlsym(dl, "NP_GetMIMEDescription"));
  const char* mime_description = NULL;
  if (NP_GetMIMEDescription)
    mime_description = NP_GetMIMEDescription();

  if (mime_description)
    ParseMIMEDescription(mime_description, &info->mime_types);

  // The plugin name and description live behind NP_GetValue calls.
  typedef NPError (*NP_GetValueType)(void* unused,
                                     nsPluginVariable variable,
                                     void* value_out);
  NP_GetValueType NP_GetValue =
      reinterpret_cast<NP_GetValueType>(dlsym(dl, "NP_GetValue"));
  if (NP_GetValue) {
    const char* name = NULL;
    NP_GetValue(NULL, nsPluginVariable_NameString, &name);
    if (name)
      info->name = UTF8ToWide(name);

    const char* description = NULL;
    NP_GetValue(NULL, nsPluginVariable_DescriptionString, &description);
    if (description)
      info->desc = UTF8ToWide(description);
  }

  // Intentionally not unloading the plugin here, it can lead to crashes.

  return true;
}

// static
void PluginLib::ParseMIMEDescription(
    const std::string& description,
    std::vector<WebPluginMimeType>* mime_types) {
  // We parse the description here into WebPluginMimeType structures.
  // Naively from the NPAPI docs you'd think you could use
  // string-splitting, but the Firefox parser turns out to do something
  // different: find the first colon, then the second, then a semi.
  //
  // See ParsePluginMimeDescription near
  // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUtils.h#53

  std::string::size_type ofs = 0;
  for (;;) {
    WebPluginMimeType mime_type;

    std::string::size_type end = description.find(':', ofs);
    if (end == std::string::npos)
      break;
    mime_type.mime_type = description.substr(ofs, end - ofs);
    ofs = end + 1;

    end = description.find(':', ofs);
    if (end == std::string::npos)
      break;
    const std::string extensions = description.substr(ofs, end - ofs);
    SplitString(extensions, ',', &mime_type.file_extensions);
    ofs = end + 1;

    end = description.find(';', ofs);
    // It's ok for end to run off the string here.  If there's no
    // trailing semicolon we consume the remainder of the string.
    if (end != std::string::npos) {
      mime_type.description = UTF8ToWide(description.substr(ofs, end - ofs));
    } else {
      mime_type.description = UTF8ToWide(description.substr(ofs));
    }
    mime_types->push_back(mime_type);
    if (end == std::string::npos)
      break;
    ofs = end + 1;
  }
}

}  // namespace NPAPI
<|endoftext|>


<commit_before>#include "subprocess.h"
#include "sys.h"
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
#include <signal.h>
#include <cerrno>
#include <system_error>
#include <algorithm>

namespace wobble {
namespace subprocess {

Child::~Child()
{
    switch (m_stdin_action)
    {
        case Redirect::PIPE:
            if (m_stdin[1] != -1) ::close(m_stdin[1]);
            break;
        default:
            break;
    }

    switch (m_stdout_action)
    {
        case Redirect::PIPE:
            if (m_stdout[0] != -1) ::close(m_stdout[0]);
            break;
        default:
            break;
    }

    switch (m_stderr_action)
    {
        case Redirect::PIPE:
            if (m_stderr[0] != -1) ::close(m_stderr[0]);
            break;
        default:
            break;
    }
}

int Child::returncode() const
{
    return WEXITSTATUS(m_returncode);
}

int Child::get_stdin() const
{
    if (m_stdin[1] == -1)
        throw std::runtime_error("stdin() called on Child but stdin was not redirected to a pipe or file descriptor");
    return m_stdin[1];
}

int Child::get_stdout() const
{
    if (m_stdout[0] == -1)
        throw std::runtime_error("stdout() called on Child but stdout was not redirected to a pipe or file descriptor");
    return m_stdout[0];
}

int Child::get_stderr() const
{
    if (m_stderr[0] == -1)
        throw std::runtime_error("stderr() called on Child but stderr was not redirected to a pipe or file descriptor");
    return m_stderr[0];
}

void Child::set_stdin(int fd)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdin after the child process has started");
    m_stdin[0] = m_stdin[1] = fd;
    m_stdin_action = Redirect::FD;
}

void Child::set_stdout(int fd)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdout after the child process has started");
    m_stdout[0] = m_stdout[1] = fd;
    m_stdout_action = Redirect::FD;
}

void Child::set_stderr(int fd)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stderr after the child process has started");
    m_stderr[0] = m_stderr[1] = fd;
    m_stderr_action = Redirect::FD;
}

void Child::set_stdin(Redirect val)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdin after the child process has started");
    m_stdin_action = val;
}

void Child::set_stdout(Redirect val)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdin after the child process has started");
    m_stdout_action = val;
}

void Child::set_stderr(Redirect val)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stderr after the child process has started");
    m_stderr_action = val;
}

void Child::pre_fork()
{
    switch (m_stdin_action)
    {
        case Redirect::PIPE:
            if (pipe(m_stdin) == -1)
                throw std::system_error(errno, std::system_category(), "failed to create a pipe for stdin");
            break;
        default:
            break;
    }

    switch (m_stdout_action)
    {
        case Redirect::PIPE:
            if (pipe(m_stdout) == -1)
                throw std::system_error(errno, std::system_category(), "failed to create a pipe for stdout");
            break;
        default:
            break;
    }

    switch (m_stderr_action)
    {
        case Redirect::PIPE:
            if (pipe(m_stderr) == -1)
                throw std::system_error(errno, std::system_category(), "failed to create a pipe for stderr");
            break;
        default:
            break;
    }
}

void Child::post_fork_parent()
{
    switch (m_stdin_action)
    {
        case Redirect::PIPE:
            if (close(m_stdin[0]) == -1)
                throw std::system_error(errno, std::system_category(), "failed close read end of stdin pipe in parent process");
            m_stdin[0] = -1;
            break;
        default:
            break;
    }

    switch (m_stdout_action)
    {
        case Redirect::PIPE:
            if (close(m_stdout[1]) == -1)
                throw std::system_error(errno, std::system_category(), "failed close read end of stdout pipe in parent process");
            m_stdout[1] = -1;
            break;
        default:
            break;
    }

    switch (m_stderr_action)
    {
        case Redirect::PIPE:
            if (close(m_stderr[1]) == -1)
                throw std::system_error(errno, std::system_category(), "failed close read end of stderr pipe in parent process");
            m_stderr[1] = -1;
            break;
        default:
            break;
    }
}

static void redirect(int newfd, int oldfd, const char* errmsg)
{
    if (dup2(newfd, oldfd) == -1)
        throw std::system_error(errno, std::system_category(), errmsg);
    if (close(newfd) == -1 )
        throw std::system_error(errno, std::system_category(), errmsg);
}

void Child::post_fork_child()
{
    {
        sys::File fd_devnull("/dev/null");

        switch (m_stdin_action)
        {
            case Redirect::FD:
                redirect(m_stdin[0], STDIN_FILENO, "failed to redirect stdin");
                break;
            case Redirect::PIPE:
                if (close(m_stdin[1]) == -1)
                    throw std::system_error(errno, std::system_category(), "failed close write end of stdin pipe in child process");
                redirect(m_stdin[0], STDIN_FILENO, "failed to redirect stdin");
                break;
            case Redirect::DEVNULL:
                if (fd_devnull == -1)
                    fd_devnull.open(O_RDWR);
                if (dup2(fd_devnull, STDIN_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stdin to /dev/null");
                break;
            default:
                break;
        }

        switch (m_stdout_action)
        {
            case Redirect::FD:
                redirect(m_stdout[1], STDOUT_FILENO, "failed to redirect stdout");
                break;
            case Redirect::PIPE:
                if (close(m_stdout[0]) == -1)
                    throw std::system_error(errno, std::system_category(), "failed close read end of stdout pipe in child process");
                redirect(m_stdout[1], STDOUT_FILENO, "failed to redirect stdout");
                break;
            case Redirect::DEVNULL:
                if (fd_devnull == -1)
                    fd_devnull.open(O_RDWR);
                if (dup2(fd_devnull, STDOUT_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stdout to /dev/null");
                break;
            default:
                break;
        }

        switch (m_stderr_action)
        {
            case Redirect::FD:
                redirect(m_stderr[1], STDERR_FILENO, "failed to redirect stderr");
                break;
            case Redirect::PIPE:
                if (close(m_stderr[0]) == -1)
                    throw std::system_error(errno, std::system_category(), "failed close read end of stderr pipe in child process");
                redirect(m_stderr[1], STDERR_FILENO, "failed to redirect stderr");
                break;
            case Redirect::DEVNULL:
                if (fd_devnull == -1)
                    fd_devnull.open(O_RDWR);
                if (dup2(fd_devnull, STDERR_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stderr to /dev/null");
                break;
            case Redirect::STDOUT:
                if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stderr to stdout");
            default:
                break;
        }
    }

    // Close parent file descriptors if requested
    if (close_fds)
    {
        errno = 0;
        long max = sysconf(_SC_OPEN_MAX);
        if (errno == 0)
        {
            for (long i = 3; i < max; ++i)
            {
                if (std::find(pass_fds.begin(), pass_fds.end(), i) != pass_fds.end())
                    continue;
                ::close(i);
            }
        }
        errno = 0;
    }

    // Honor cwd
    if (!cwd.empty())
    {
        if (chdir(cwd.c_str()) == -1)
            throw std::system_error(errno, std::system_category(), "failed to chdir to " + cwd);
    }

    // Honor start_new_session
    if (start_new_session)
        if (setsid() == (pid_t)-1)
            throw std::system_error(errno, std::system_category(), "cannot call setsid()");
}

void Child::fork()
{
    if (!pass_fds.empty())
        close_fds = true;

    pre_fork();

    pid_t pid;
    if ((pid = ::fork()) == 0)
    {
        try {
            post_fork_child();
        } catch (std::system_error& e) {
            fprintf(::stderr, "Child process setup failed: %s\n", e.what());
            _exit(EX_OSERR);
        } catch (std::exception& e) {
            fprintf(::stderr, "Child process setup failed: %s\n", e.what());
            _exit(EX_SOFTWARE);
        }
        _exit(main());
    } else if (pid < 0) {
        throw std::system_error(errno, std::system_category(), "failed to fork()");
    } else {
        m_pid = pid;
        post_fork_parent();
    }
}

bool Child::poll()
{
    if (m_pid == 0)
        throw std::runtime_error("poll called before Child process was started");

    if (m_terminated)
        return true;

    pid_t res = waitpid(m_pid, &m_returncode, WNOHANG);
    if (res == -1)
        throw std::system_error(
                errno, std::system_category(),
                "failed to waitpid(" + std::to_string(m_pid) + ")");

    if (res == m_pid)
    {
        m_terminated = true;
        return true;
    }

    return false;
}

void Child::wait()
{
    if (m_pid == 0)
        throw std::runtime_error("wait called before Child process was started");

    if (m_terminated)
        return;

    pid_t res = waitpid(m_pid, &m_returncode, 0);
    if (res == -1)
        throw std::system_error(
                errno, std::system_category(),
                "failed to waitpid(" + std::to_string(m_pid) + ")");

    m_terminated = true;
}

void Child::send_signal(int sig)
{
    if (::kill(m_pid, sig) == -1)
        throw std::system_error(
                errno, std::system_category(),
                "cannot send signal " + std::to_string(sig) + " to child PID " + std::to_string(m_pid));
}

void Child::terminate() { send_signal(SIGTERM); }

void Child::kill() { send_signal(SIGKILL); }

int Popen::main() noexcept
{
    try {
        const char* path;
        if (executable.empty())
            path = args[0].c_str();
        else
            path = executable.c_str();

        const char** exec_args = new const char*[args.size() + 1];
        for (unsigned i = 0; i < args.size(); ++i)
            exec_args[i] = args[i].c_str();
        exec_args[args.size()] = nullptr;

        if (execvp(path, (char* const*)exec_args) == -1)
            throw std::system_error(
                    errno, std::system_category(),
                    "execvp failed");

        throw std::runtime_error("process flow continued after execvp did not fail");
    } catch (std::system_error& e) {
        fprintf(::stderr, "Child process setup failed: %s\n", e.what());
        return EX_OSERR;
    } catch (std::exception& e) {
        fprintf(::stderr, "Child process setup failed: %s\n", e.what());
        return EX_SOFTWARE;
    }
}

}
}
<commit_msg>Do not leak exec_args if execvp fails<commit_after>#include "subprocess.h"
#include "sys.h"
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
#include <signal.h>
#include <cerrno>
#include <system_error>
#include <algorithm>

namespace wobble {
namespace subprocess {

Child::~Child()
{
    switch (m_stdin_action)
    {
        case Redirect::PIPE:
            if (m_stdin[1] != -1) ::close(m_stdin[1]);
            break;
        default:
            break;
    }

    switch (m_stdout_action)
    {
        case Redirect::PIPE:
            if (m_stdout[0] != -1) ::close(m_stdout[0]);
            break;
        default:
            break;
    }

    switch (m_stderr_action)
    {
        case Redirect::PIPE:
            if (m_stderr[0] != -1) ::close(m_stderr[0]);
            break;
        default:
            break;
    }
}

int Child::returncode() const
{
    return WEXITSTATUS(m_returncode);
}

int Child::get_stdin() const
{
    if (m_stdin[1] == -1)
        throw std::runtime_error("stdin() called on Child but stdin was not redirected to a pipe or file descriptor");
    return m_stdin[1];
}

int Child::get_stdout() const
{
    if (m_stdout[0] == -1)
        throw std::runtime_error("stdout() called on Child but stdout was not redirected to a pipe or file descriptor");
    return m_stdout[0];
}

int Child::get_stderr() const
{
    if (m_stderr[0] == -1)
        throw std::runtime_error("stderr() called on Child but stderr was not redirected to a pipe or file descriptor");
    return m_stderr[0];
}

void Child::set_stdin(int fd)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdin after the child process has started");
    m_stdin[0] = m_stdin[1] = fd;
    m_stdin_action = Redirect::FD;
}

void Child::set_stdout(int fd)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdout after the child process has started");
    m_stdout[0] = m_stdout[1] = fd;
    m_stdout_action = Redirect::FD;
}

void Child::set_stderr(int fd)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stderr after the child process has started");
    m_stderr[0] = m_stderr[1] = fd;
    m_stderr_action = Redirect::FD;
}

void Child::set_stdin(Redirect val)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdin after the child process has started");
    m_stdin_action = val;
}

void Child::set_stdout(Redirect val)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stdin after the child process has started");
    m_stdout_action = val;
}

void Child::set_stderr(Redirect val)
{
    if (m_pid != 0)
        throw std::runtime_error("cannot redirect stderr after the child process has started");
    m_stderr_action = val;
}

void Child::pre_fork()
{
    switch (m_stdin_action)
    {
        case Redirect::PIPE:
            if (pipe(m_stdin) == -1)
                throw std::system_error(errno, std::system_category(), "failed to create a pipe for stdin");
            break;
        default:
            break;
    }

    switch (m_stdout_action)
    {
        case Redirect::PIPE:
            if (pipe(m_stdout) == -1)
                throw std::system_error(errno, std::system_category(), "failed to create a pipe for stdout");
            break;
        default:
            break;
    }

    switch (m_stderr_action)
    {
        case Redirect::PIPE:
            if (pipe(m_stderr) == -1)
                throw std::system_error(errno, std::system_category(), "failed to create a pipe for stderr");
            break;
        default:
            break;
    }
}

void Child::post_fork_parent()
{
    switch (m_stdin_action)
    {
        case Redirect::PIPE:
            if (close(m_stdin[0]) == -1)
                throw std::system_error(errno, std::system_category(), "failed close read end of stdin pipe in parent process");
            m_stdin[0] = -1;
            break;
        default:
            break;
    }

    switch (m_stdout_action)
    {
        case Redirect::PIPE:
            if (close(m_stdout[1]) == -1)
                throw std::system_error(errno, std::system_category(), "failed close read end of stdout pipe in parent process");
            m_stdout[1] = -1;
            break;
        default:
            break;
    }

    switch (m_stderr_action)
    {
        case Redirect::PIPE:
            if (close(m_stderr[1]) == -1)
                throw std::system_error(errno, std::system_category(), "failed close read end of stderr pipe in parent process");
            m_stderr[1] = -1;
            break;
        default:
            break;
    }
}

static void redirect(int newfd, int oldfd, const char* errmsg)
{
    if (dup2(newfd, oldfd) == -1)
        throw std::system_error(errno, std::system_category(), errmsg);
    if (close(newfd) == -1 )
        throw std::system_error(errno, std::system_category(), errmsg);
}

void Child::post_fork_child()
{
    {
        sys::File fd_devnull("/dev/null");

        switch (m_stdin_action)
        {
            case Redirect::FD:
                redirect(m_stdin[0], STDIN_FILENO, "failed to redirect stdin");
                break;
            case Redirect::PIPE:
                if (close(m_stdin[1]) == -1)
                    throw std::system_error(errno, std::system_category(), "failed close write end of stdin pipe in child process");
                redirect(m_stdin[0], STDIN_FILENO, "failed to redirect stdin");
                break;
            case Redirect::DEVNULL:
                if (fd_devnull == -1)
                    fd_devnull.open(O_RDWR);
                if (dup2(fd_devnull, STDIN_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stdin to /dev/null");
                break;
            default:
                break;
        }

        switch (m_stdout_action)
        {
            case Redirect::FD:
                redirect(m_stdout[1], STDOUT_FILENO, "failed to redirect stdout");
                break;
            case Redirect::PIPE:
                if (close(m_stdout[0]) == -1)
                    throw std::system_error(errno, std::system_category(), "failed close read end of stdout pipe in child process");
                redirect(m_stdout[1], STDOUT_FILENO, "failed to redirect stdout");
                break;
            case Redirect::DEVNULL:
                if (fd_devnull == -1)
                    fd_devnull.open(O_RDWR);
                if (dup2(fd_devnull, STDOUT_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stdout to /dev/null");
                break;
            default:
                break;
        }

        switch (m_stderr_action)
        {
            case Redirect::FD:
                redirect(m_stderr[1], STDERR_FILENO, "failed to redirect stderr");
                break;
            case Redirect::PIPE:
                if (close(m_stderr[0]) == -1)
                    throw std::system_error(errno, std::system_category(), "failed close read end of stderr pipe in child process");
                redirect(m_stderr[1], STDERR_FILENO, "failed to redirect stderr");
                break;
            case Redirect::DEVNULL:
                if (fd_devnull == -1)
                    fd_devnull.open(O_RDWR);
                if (dup2(fd_devnull, STDERR_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stderr to /dev/null");
                break;
            case Redirect::STDOUT:
                if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
                    throw std::system_error(errno, std::system_category(), "failed to redirect stderr to stdout");
            default:
                break;
        }
    }

    // Close parent file descriptors if requested
    if (close_fds)
    {
        errno = 0;
        long max = sysconf(_SC_OPEN_MAX);
        if (errno == 0)
        {
            for (long i = 3; i < max; ++i)
            {
                if (std::find(pass_fds.begin(), pass_fds.end(), i) != pass_fds.end())
                    continue;
                ::close(i);
            }
        }
        errno = 0;
    }

    // Honor cwd
    if (!cwd.empty())
    {
        if (chdir(cwd.c_str()) == -1)
            throw std::system_error(errno, std::system_category(), "failed to chdir to " + cwd);
    }

    // Honor start_new_session
    if (start_new_session)
        if (setsid() == (pid_t)-1)
            throw std::system_error(errno, std::system_category(), "cannot call setsid()");
}

void Child::fork()
{
    if (!pass_fds.empty())
        close_fds = true;

    pre_fork();

    pid_t pid;
    if ((pid = ::fork()) == 0)
    {
        try {
            post_fork_child();
        } catch (std::system_error& e) {
            fprintf(::stderr, "Child process setup failed: %s\n", e.what());
            _exit(EX_OSERR);
        } catch (std::exception& e) {
            fprintf(::stderr, "Child process setup failed: %s\n", e.what());
            _exit(EX_SOFTWARE);
        }
        _exit(main());
    } else if (pid < 0) {
        throw std::system_error(errno, std::system_category(), "failed to fork()");
    } else {
        m_pid = pid;
        post_fork_parent();
    }
}

bool Child::poll()
{
    if (m_pid == 0)
        throw std::runtime_error("poll called before Child process was started");

    if (m_terminated)
        return true;

    pid_t res = waitpid(m_pid, &m_returncode, WNOHANG);
    if (res == -1)
        throw std::system_error(
                errno, std::system_category(),
                "failed to waitpid(" + std::to_string(m_pid) + ")");

    if (res == m_pid)
    {
        m_terminated = true;
        return true;
    }

    return false;
}

void Child::wait()
{
    if (m_pid == 0)
        throw std::runtime_error("wait called before Child process was started");

    if (m_terminated)
        return;

    pid_t res = waitpid(m_pid, &m_returncode, 0);
    if (res == -1)
        throw std::system_error(
                errno, std::system_category(),
                "failed to waitpid(" + std::to_string(m_pid) + ")");

    m_terminated = true;
}

void Child::send_signal(int sig)
{
    if (::kill(m_pid, sig) == -1)
        throw std::system_error(
                errno, std::system_category(),
                "cannot send signal " + std::to_string(sig) + " to child PID " + std::to_string(m_pid));
}

void Child::terminate() { send_signal(SIGTERM); }

void Child::kill() { send_signal(SIGKILL); }

int Popen::main() noexcept
{
    try {
        const char* path;
        if (executable.empty())
            path = args[0].c_str();
        else
            path = executable.c_str();

        const char** exec_args = new const char*[args.size() + 1];
        for (unsigned i = 0; i < args.size(); ++i)
            exec_args[i] = args[i].c_str();
        exec_args[args.size()] = nullptr;

        if (execvp(path, (char* const*)exec_args) == -1)
        {
            delete[] exec_args;
            throw std::system_error(
                    errno, std::system_category(),
                    "execvp failed");
        }

        delete[] exec_args;
        throw std::runtime_error("process flow continued after execvp did not fail");
    } catch (std::system_error& e) {
        fprintf(::stderr, "Child process setup failed: %s\n", e.what());
        return EX_OSERR;
    } catch (std::exception& e) {
        fprintf(::stderr, "Child process setup failed: %s\n", e.what());
        return EX_SOFTWARE;
    }
}

}
}
<|endoftext|>