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

#include "chrome/renderer/extensions/miscellaneous_bindings.h"

#include <map>
#include <string>

#include "base/basictypes.h"
#include "base/lazy_instance.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/message_bundle.h"
#include "chrome/common/url_constants.h"
#include "chrome/renderer/extensions/chrome_v8_context.h"
#include "chrome/renderer/extensions/chrome_v8_context_set.h"
#include "chrome/renderer/extensions/chrome_v8_extension.h"
#include "chrome/renderer/extensions/dispatcher.h"
#include "chrome/renderer/extensions/event_bindings.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "grit/renderer_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSuppression.h"
#include "v8/include/v8.h"

// Message passing API example (in a content script):
// var extension =
//    new chrome.Extension('00123456789abcdef0123456789abcdef0123456');
// var port = extension.connect();
// port.postMessage('Can you hear me now?');
// port.onmessage.addListener(function(msg, port) {
//   alert('response=' + msg);
//   port.postMessage('I got your reponse');
// });

using content::RenderThread;

namespace {

struct ExtensionData {
  struct PortData {
    int ref_count;  // how many contexts have a handle to this port
    PortData() : ref_count(0) {}
  };
  std::map<int, PortData> ports;  // port ID -> data
};

static base::LazyInstance<ExtensionData> g_extension_data =
    LAZY_INSTANCE_INITIALIZER;

static bool HasPortData(int port_id) {
  return g_extension_data.Get().ports.find(port_id) !=
      g_extension_data.Get().ports.end();
}

static ExtensionData::PortData& GetPortData(int port_id) {
  return g_extension_data.Get().ports[port_id];
}

static void ClearPortData(int port_id) {
  g_extension_data.Get().ports.erase(port_id);
}

const char kPortClosedError[] = "Attempting to use a disconnected port object";

class ExtensionImpl : public extensions::ChromeV8Extension {
 public:
  explicit ExtensionImpl(extensions::Dispatcher* dispatcher)
      : extensions::ChromeV8Extension(dispatcher) {
    RouteStaticFunction("CloseChannel", &CloseChannel);
    RouteStaticFunction("PortAddRef", &PortAddRef);
    RouteStaticFunction("PortRelease", &PortRelease);
    RouteStaticFunction("PostMessage", &PostMessage);
    RouteStaticFunction("BindToGC", &BindToGC);
  }

  ~ExtensionImpl() {}

  // Sends a message along the given channel.
  static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) {
    content::RenderView* renderview = GetCurrentRenderView();
    if (!renderview)
      return v8::Undefined();

    if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) {
      int port_id = args[0]->Int32Value();
      if (!HasPortData(port_id)) {
        return v8::ThrowException(v8::Exception::Error(
          v8::String::New(kPortClosedError)));
      }
      std::string message = *v8::String::Utf8Value(args[1]->ToString());
      renderview->Send(new ExtensionHostMsg_PostMessage(
          renderview->GetRoutingID(), port_id, message));
    }
    return v8::Undefined();
  }

  // Forcefully disconnects a port.
  static v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) {
    if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsBoolean()) {
      int port_id = args[0]->Int32Value();
      if (!HasPortData(port_id)) {
        return v8::Undefined();
      }
      // Send via the RenderThread because the RenderView might be closing.
      bool notify_browser = args[1]->BooleanValue();
      if (notify_browser)
        content::RenderThread::Get()->Send(
            new ExtensionHostMsg_CloseChannel(port_id, false));
      ClearPortData(port_id);
    }
    return v8::Undefined();
  }

  // A new port has been created for a context.  This occurs both when script
  // opens a connection, and when a connection is opened to this script.
  static v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) {
    if (args.Length() >= 1 && args[0]->IsInt32()) {
      int port_id = args[0]->Int32Value();
      ++GetPortData(port_id).ref_count;
    }
    return v8::Undefined();
  }

  // The frame a port lived in has been destroyed.  When there are no more
  // frames with a reference to a given port, we will disconnect it and notify
  // the other end of the channel.
  static v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) {
    if (args.Length() >= 1 && args[0]->IsInt32()) {
      int port_id = args[0]->Int32Value();
      if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) {
        // Send via the RenderThread because the RenderView might be closing.
        content::RenderThread::Get()->Send(
            new ExtensionHostMsg_CloseChannel(port_id, false));
        ClearPortData(port_id);
      }
    }
    return v8::Undefined();
  }

  struct GCCallbackArgs {
    v8::Persistent<v8::Object> object;
    v8::Persistent<v8::Function> callback;
  };

  static void GCCallback(v8::Persistent<v8::Value> object, void* parameter) {
    v8::HandleScope handle_scope;
    GCCallbackArgs* args = reinterpret_cast<GCCallbackArgs*>(parameter);
    WebKit::WebScopedMicrotaskSuppression suppression;
    args->callback->Call(args->callback->CreationContext()->Global(), 0, NULL);
    args->callback.Dispose();
    args->object.Dispose();
    delete args;
  }

  // Binds a callback to be invoked when the given object is garbage collected.
  static v8::Handle<v8::Value> BindToGC(const v8::Arguments& args) {
    if (args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction()) {
      GCCallbackArgs* context = new GCCallbackArgs;
      context->callback = v8::Persistent<v8::Function>::New(
          v8::Handle<v8::Function>::Cast(args[1]));
      context->object = v8::Persistent<v8::Object>::New(
          v8::Handle<v8::Object>::Cast(args[0]));
      context->object.MakeWeak(context, GCCallback);
    } else {
      NOTREACHED();
    }
    return v8::Undefined();
  }
};

}  // namespace

namespace extensions {

ChromeV8Extension* MiscellaneousBindings::Get(Dispatcher* dispatcher) {
  return new ExtensionImpl(dispatcher);
}

// static
void MiscellaneousBindings::DispatchOnConnect(
    const ChromeV8ContextSet::ContextSet& contexts,
    int target_port_id,
    const std::string& channel_name,
    const std::string& tab_json,
    const std::string& source_extension_id,
    const std::string& target_extension_id,
    content::RenderView* restrict_to_render_view) {
  v8::HandleScope handle_scope;

  bool port_created = false;

  for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
       it != contexts.end(); ++it) {
    if (restrict_to_render_view &&
        restrict_to_render_view != (*it)->GetRenderView()) {
      continue;
    }

    std::vector<v8::Handle<v8::Value> > arguments;
    arguments.push_back(v8::Integer::New(target_port_id));
    arguments.push_back(v8::String::New(channel_name.c_str(),
                                        channel_name.size()));
    arguments.push_back(v8::String::New(tab_json.c_str(),
                                        tab_json.size()));
    arguments.push_back(v8::String::New(source_extension_id.c_str(),
                                        source_extension_id.size()));
    arguments.push_back(v8::String::New(target_extension_id.c_str(),
                                        target_extension_id.size()));
    v8::Handle<v8::Value> retval;
    v8::TryCatch try_catch;
    if (!(*it)->CallChromeHiddenMethod("Port.dispatchOnConnect",
                                      arguments.size(), &arguments[0],
                                      &retval)) {
      continue;
    }

    if (try_catch.HasCaught()) {
      LOG(ERROR) << "Exception caught when calling Port.dispatchOnConnect.";
      continue;
    }

    CHECK(!retval.IsEmpty());
    CHECK(retval->IsBoolean());
    if (retval->BooleanValue())
      port_created = true;
  }

  // If we didn't create a port, notify the other end of the channel (treat it
  // as a disconnect).
  if (!port_created) {
    content::RenderThread::Get()->Send(
        new ExtensionHostMsg_CloseChannel(target_port_id, true));
  }
}

// static
void MiscellaneousBindings::DeliverMessage(
    const ChromeV8ContextSet::ContextSet& contexts,
    int target_port_id,
    const std::string& message,
    content::RenderView* restrict_to_render_view) {
  v8::HandleScope handle_scope;

  for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
       it != contexts.end(); ++it) {
    if (restrict_to_render_view &&
        restrict_to_render_view != (*it)->GetRenderView()) {
      continue;
    }

    // Check to see whether the context has this port before bothering to create
    // the message.
    v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id);
    v8::Handle<v8::Value> has_port;
    v8::TryCatch try_catch;
    if (!(*it)->CallChromeHiddenMethod("Port.hasPort", 1, &port_id_handle,
                                       &has_port)) {
      continue;
    }

    if (try_catch.HasCaught()) {
      LOG(ERROR) << "Exception caught when calling Port.hasPort.";
      continue;
    }

    CHECK(!has_port.IsEmpty());
    if (!has_port->BooleanValue())
      continue;

    std::vector<v8::Handle<v8::Value> > arguments;
    arguments.push_back(v8::String::New(message.c_str(), message.size()));
    arguments.push_back(port_id_handle);
    CHECK((*it)->CallChromeHiddenMethod("Port.dispatchOnMessage",
                                        arguments.size(),
                                        &arguments[0],
                                        NULL));
  }
}

// static
void MiscellaneousBindings::DispatchOnDisconnect(
    const ChromeV8ContextSet::ContextSet& contexts,
    int port_id,
    bool connection_error,
    content::RenderView* restrict_to_render_view) {
  v8::HandleScope handle_scope;

  for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
       it != contexts.end(); ++it) {
    if (restrict_to_render_view &&
        restrict_to_render_view != (*it)->GetRenderView()) {
      continue;
    }

    std::vector<v8::Handle<v8::Value> > arguments;
    arguments.push_back(v8::Integer::New(port_id));
    arguments.push_back(v8::Boolean::New(connection_error));
    (*it)->CallChromeHiddenMethod("Port.dispatchOnDisconnect",
                                  arguments.size(), &arguments[0],
                                  NULL);
  }
}

}  // namespace extensions
<commit_msg>Change a CHECK in MiscellaneousBindings::DispatchOnConnect to a non-fatal warning.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/extensions/miscellaneous_bindings.h"

#include <map>
#include <string>

#include "base/basictypes.h"
#include "base/lazy_instance.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/message_bundle.h"
#include "chrome/common/url_constants.h"
#include "chrome/renderer/extensions/chrome_v8_context.h"
#include "chrome/renderer/extensions/chrome_v8_context_set.h"
#include "chrome/renderer/extensions/chrome_v8_extension.h"
#include "chrome/renderer/extensions/dispatcher.h"
#include "chrome/renderer/extensions/event_bindings.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "grit/renderer_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSuppression.h"
#include "v8/include/v8.h"

// Message passing API example (in a content script):
// var extension =
//    new chrome.Extension('00123456789abcdef0123456789abcdef0123456');
// var port = extension.connect();
// port.postMessage('Can you hear me now?');
// port.onmessage.addListener(function(msg, port) {
//   alert('response=' + msg);
//   port.postMessage('I got your reponse');
// });

using content::RenderThread;

namespace {

struct ExtensionData {
  struct PortData {
    int ref_count;  // how many contexts have a handle to this port
    PortData() : ref_count(0) {}
  };
  std::map<int, PortData> ports;  // port ID -> data
};

static base::LazyInstance<ExtensionData> g_extension_data =
    LAZY_INSTANCE_INITIALIZER;

static bool HasPortData(int port_id) {
  return g_extension_data.Get().ports.find(port_id) !=
      g_extension_data.Get().ports.end();
}

static ExtensionData::PortData& GetPortData(int port_id) {
  return g_extension_data.Get().ports[port_id];
}

static void ClearPortData(int port_id) {
  g_extension_data.Get().ports.erase(port_id);
}

const char kPortClosedError[] = "Attempting to use a disconnected port object";

class ExtensionImpl : public extensions::ChromeV8Extension {
 public:
  explicit ExtensionImpl(extensions::Dispatcher* dispatcher)
      : extensions::ChromeV8Extension(dispatcher) {
    RouteStaticFunction("CloseChannel", &CloseChannel);
    RouteStaticFunction("PortAddRef", &PortAddRef);
    RouteStaticFunction("PortRelease", &PortRelease);
    RouteStaticFunction("PostMessage", &PostMessage);
    RouteStaticFunction("BindToGC", &BindToGC);
  }

  ~ExtensionImpl() {}

  // Sends a message along the given channel.
  static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) {
    content::RenderView* renderview = GetCurrentRenderView();
    if (!renderview)
      return v8::Undefined();

    if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) {
      int port_id = args[0]->Int32Value();
      if (!HasPortData(port_id)) {
        return v8::ThrowException(v8::Exception::Error(
          v8::String::New(kPortClosedError)));
      }
      std::string message = *v8::String::Utf8Value(args[1]->ToString());
      renderview->Send(new ExtensionHostMsg_PostMessage(
          renderview->GetRoutingID(), port_id, message));
    }
    return v8::Undefined();
  }

  // Forcefully disconnects a port.
  static v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) {
    if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsBoolean()) {
      int port_id = args[0]->Int32Value();
      if (!HasPortData(port_id)) {
        return v8::Undefined();
      }
      // Send via the RenderThread because the RenderView might be closing.
      bool notify_browser = args[1]->BooleanValue();
      if (notify_browser)
        content::RenderThread::Get()->Send(
            new ExtensionHostMsg_CloseChannel(port_id, false));
      ClearPortData(port_id);
    }
    return v8::Undefined();
  }

  // A new port has been created for a context.  This occurs both when script
  // opens a connection, and when a connection is opened to this script.
  static v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) {
    if (args.Length() >= 1 && args[0]->IsInt32()) {
      int port_id = args[0]->Int32Value();
      ++GetPortData(port_id).ref_count;
    }
    return v8::Undefined();
  }

  // The frame a port lived in has been destroyed.  When there are no more
  // frames with a reference to a given port, we will disconnect it and notify
  // the other end of the channel.
  static v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) {
    if (args.Length() >= 1 && args[0]->IsInt32()) {
      int port_id = args[0]->Int32Value();
      if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) {
        // Send via the RenderThread because the RenderView might be closing.
        content::RenderThread::Get()->Send(
            new ExtensionHostMsg_CloseChannel(port_id, false));
        ClearPortData(port_id);
      }
    }
    return v8::Undefined();
  }

  struct GCCallbackArgs {
    v8::Persistent<v8::Object> object;
    v8::Persistent<v8::Function> callback;
  };

  static void GCCallback(v8::Persistent<v8::Value> object, void* parameter) {
    v8::HandleScope handle_scope;
    GCCallbackArgs* args = reinterpret_cast<GCCallbackArgs*>(parameter);
    WebKit::WebScopedMicrotaskSuppression suppression;
    args->callback->Call(args->callback->CreationContext()->Global(), 0, NULL);
    args->callback.Dispose();
    args->object.Dispose();
    delete args;
  }

  // Binds a callback to be invoked when the given object is garbage collected.
  static v8::Handle<v8::Value> BindToGC(const v8::Arguments& args) {
    if (args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction()) {
      GCCallbackArgs* context = new GCCallbackArgs;
      context->callback = v8::Persistent<v8::Function>::New(
          v8::Handle<v8::Function>::Cast(args[1]));
      context->object = v8::Persistent<v8::Object>::New(
          v8::Handle<v8::Object>::Cast(args[0]));
      context->object.MakeWeak(context, GCCallback);
    } else {
      NOTREACHED();
    }
    return v8::Undefined();
  }
};

}  // namespace

namespace extensions {

ChromeV8Extension* MiscellaneousBindings::Get(Dispatcher* dispatcher) {
  return new ExtensionImpl(dispatcher);
}

// static
void MiscellaneousBindings::DispatchOnConnect(
    const ChromeV8ContextSet::ContextSet& contexts,
    int target_port_id,
    const std::string& channel_name,
    const std::string& tab_json,
    const std::string& source_extension_id,
    const std::string& target_extension_id,
    content::RenderView* restrict_to_render_view) {
  v8::HandleScope handle_scope;

  bool port_created = false;

  for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
       it != contexts.end(); ++it) {
    if (restrict_to_render_view &&
        restrict_to_render_view != (*it)->GetRenderView()) {
      continue;
    }

    std::vector<v8::Handle<v8::Value> > arguments;
    arguments.push_back(v8::Integer::New(target_port_id));
    arguments.push_back(v8::String::New(channel_name.c_str(),
                                        channel_name.size()));
    arguments.push_back(v8::String::New(tab_json.c_str(),
                                        tab_json.size()));
    arguments.push_back(v8::String::New(source_extension_id.c_str(),
                                        source_extension_id.size()));
    arguments.push_back(v8::String::New(target_extension_id.c_str(),
                                        target_extension_id.size()));
    v8::Handle<v8::Value> retval;
    v8::TryCatch try_catch;
    if (!(*it)->CallChromeHiddenMethod("Port.dispatchOnConnect",
                                      arguments.size(), &arguments[0],
                                      &retval)) {
      continue;
    }

    if (try_catch.HasCaught()) {
      LOG(ERROR) << "Exception caught when calling Port.dispatchOnConnect.";
      continue;
    }

    if (retval.IsEmpty()) {
      LOG(ERROR) << "Empty return value from Port.dispatchOnConnect.";
      continue;
    }

    CHECK(retval->IsBoolean());
    if (retval->BooleanValue())
      port_created = true;
  }

  // If we didn't create a port, notify the other end of the channel (treat it
  // as a disconnect).
  if (!port_created) {
    content::RenderThread::Get()->Send(
        new ExtensionHostMsg_CloseChannel(target_port_id, true));
  }
}

// static
void MiscellaneousBindings::DeliverMessage(
    const ChromeV8ContextSet::ContextSet& contexts,
    int target_port_id,
    const std::string& message,
    content::RenderView* restrict_to_render_view) {
  v8::HandleScope handle_scope;

  for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
       it != contexts.end(); ++it) {
    if (restrict_to_render_view &&
        restrict_to_render_view != (*it)->GetRenderView()) {
      continue;
    }

    // Check to see whether the context has this port before bothering to create
    // the message.
    v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id);
    v8::Handle<v8::Value> has_port;
    v8::TryCatch try_catch;
    if (!(*it)->CallChromeHiddenMethod("Port.hasPort", 1, &port_id_handle,
                                       &has_port)) {
      continue;
    }

    if (try_catch.HasCaught()) {
      LOG(ERROR) << "Exception caught when calling Port.hasPort.";
      continue;
    }

    CHECK(!has_port.IsEmpty());
    if (!has_port->BooleanValue())
      continue;

    std::vector<v8::Handle<v8::Value> > arguments;
    arguments.push_back(v8::String::New(message.c_str(), message.size()));
    arguments.push_back(port_id_handle);
    CHECK((*it)->CallChromeHiddenMethod("Port.dispatchOnMessage",
                                        arguments.size(),
                                        &arguments[0],
                                        NULL));
  }
}

// static
void MiscellaneousBindings::DispatchOnDisconnect(
    const ChromeV8ContextSet::ContextSet& contexts,
    int port_id,
    bool connection_error,
    content::RenderView* restrict_to_render_view) {
  v8::HandleScope handle_scope;

  for (ChromeV8ContextSet::ContextSet::const_iterator it = contexts.begin();
       it != contexts.end(); ++it) {
    if (restrict_to_render_view &&
        restrict_to_render_view != (*it)->GetRenderView()) {
      continue;
    }

    std::vector<v8::Handle<v8::Value> > arguments;
    arguments.push_back(v8::Integer::New(port_id));
    arguments.push_back(v8::Boolean::New(connection_error));
    (*it)->CallChromeHiddenMethod("Port.dispatchOnDisconnect",
                                  arguments.size(), &arguments[0],
                                  NULL);
  }
}

}  // namespace extensions
<|endoftext|>


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

#include "base/file_util.h"
#include "chrome/renderer/print_web_view_helper.h"
#include "chrome/test/render_view_test.h"
#include "printing/image.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"

using WebKit::WebFrame;
using WebKit::WebString;
using WebKit::WebView;

namespace {

const char kPrintWithJSHTML[] =
    "HelloWorld";

}  // namespace

// Tests that printing pages work and sending and receiving messages through
// that channel all works.
TEST_F(RenderViewTest, OnPrintPages) {
  // Lets simulate a print pages with Hello world.
  LoadHTML("
Hello World!
");
  PrintWebViewHelper::Get(view_)->OnPrintPages();

  VerifyPageCount(1);
  VerifyPagesPrinted(true);
}

// Duplicate of OnPrintPagesTest only using javascript to print.
TEST_F(RenderViewTest, PrintWithJavascript) {
  // HTML contains a call to window.print()
  LoadHTML(kPrintWithJSHTML);

  VerifyPageCount(1);
  VerifyPagesPrinted(true);
}

// Tests that the renderer blocks window.print() calls if they occur too
// frequently.
TEST_F(RenderViewTest, BlockScriptInitiatedPrinting) {
  // Pretend user will cancel printing.
  render_thread_.set_print_dialog_user_response(false);
  // Try to print with window.print() a few times.
  LoadHTML(kPrintWithJSHTML);
  LoadHTML(kPrintWithJSHTML);
  LoadHTML(kPrintWithJSHTML);
  VerifyPagesPrinted(false);

  // Pretend user will print. (but printing is blocked.)
  render_thread_.set_print_dialog_user_response(true);
  LoadHTML(kPrintWithJSHTML);
  VerifyPagesPrinted(false);

  // Unblock script initiated printing and verify printing works.
  PrintWebViewHelper::Get(view_)->ResetScriptedPrintCount();
  render_thread_.printer()->ResetPrinter();
  LoadHTML(kPrintWithJSHTML);
  VerifyPageCount(1);
  VerifyPagesPrinted(true);
}

#if defined(OS_WIN) || defined(OS_MACOSX)
// TODO(estade): I don't think this test is worth porting to Linux. We will have
// to rip out and replace most of the IPC code if we ever plan to improve
// printing, and the comment below by sverrir suggests that it doesn't do much
// for us anyway.
TEST_F(RenderViewTest, PrintWithIframe) {
  // Document that populates an iframe.
  const char html[] =
      "Lorem Ipsum:"
      "";

  LoadHTML(html);

  // Find the frame and set it as the focused one.  This should mean that that
  // the printout should only contain the contents of that frame.
  WebFrame* sub1_frame =
      view_->webview()->findFrameByName(WebString::fromUTF8("sub1"));
  ASSERT_TRUE(sub1_frame);
  view_->webview()->setFocusedFrame(sub1_frame);
  ASSERT_NE(view_->webview()->focusedFrame(),
            view_->webview()->mainFrame());

  // Initiate printing.
  PrintWebViewHelper::Get(view_)->OnPrintPages();

  // Verify output through MockPrinter.
  const MockPrinter* printer(render_thread_.printer());
  ASSERT_EQ(1, printer->GetPrintedPages());
  const printing::Image& image1(printer->GetPrintedPage(0)->image());

  // TODO(sverrir): Figure out a way to improve this test to actually print
  // only the content of the iframe.  Currently image1 will contain the full
  // page.
  EXPECT_NE(0, image1.size().width());
  EXPECT_NE(0, image1.size().height());
}
#endif

// Tests if we can print a page and verify its results.
// This test prints HTML pages into a pseudo printer and check their outputs,
// i.e. a simplified version of the PrintingLayoutTextTest UI test.
namespace {
// Test cases used in this test.
struct TestPageData {
  const char* page;
  size_t printed_pages;
  int width;
  int height;
  const char* checksum;
  const wchar_t* file;
};

const TestPageData kTestPages[] = {
  {""
  ""
  "<meta"
  "  http-equiv=\"Content-Type\""
  "  content=\"text/html; charset=utf-8\"/>"
  "<title>Test 1</title>"
  ""
  ""
  "
Hello World!
"
  "",
#if defined(OS_MACOSX)
  // Mac printing code compensates for the WebKit scale factor while generating
  // the metafile, so we expect smaller pages.
  1, 540, 720,
#else
  1, 675, 900,
#endif
  NULL,
  NULL,
  },
};
}  // namespace

// TODO(estade): need to port MockPrinter to get this on Linux. This involves
// hooking up Cairo to read a pdf stream, or accessing the cairo surface in the
// metafile directly.
#if defined(OS_WIN) || defined(OS_MACOSX)
TEST_F(RenderViewTest, PrintLayoutTest) {
  bool baseline = false;

  EXPECT_TRUE(render_thread_.printer() != NULL);
  for (size_t i = 0; i < arraysize(kTestPages); ++i) {
    // Load an HTML page and print it.
    LoadHTML(kTestPages[i].page);
    PrintWebViewHelper::Get(view_)->OnPrintPages();

    // MockRenderThread::Send() just calls MockRenderThread::OnMsgReceived().
    // So, all IPC messages sent in the above RenderView::OnPrintPages() call
    // has been handled by the MockPrinter object, i.e. this printing job
    // has been already finished.
    // So, we can start checking the output pages of this printing job.
    // Retrieve the number of pages actually printed.
    size_t pages = render_thread_.printer()->GetPrintedPages();
    EXPECT_EQ(kTestPages[i].printed_pages, pages);

    // Retrieve the width and height of the output page.
    int width = render_thread_.printer()->GetWidth(0);
    int height = render_thread_.printer()->GetHeight(0);

    // Check with margin for error.  This has been failing with a one pixel
    // offset on our buildbot.
    const int kErrorMargin = 5;  // 5%
    EXPECT_GT(kTestPages[i].width * (100 + kErrorMargin) / 100, width);
    EXPECT_LT(kTestPages[i].width * (100 - kErrorMargin) / 100, width);
    EXPECT_GT(kTestPages[i].height * (100 + kErrorMargin) / 100, height);
    EXPECT_LT(kTestPages[i].height* (100 - kErrorMargin) / 100, height);

    // Retrieve the checksum of the bitmap data from the pseudo printer and
    // compare it with the expected result.
    std::string bitmap_actual;
    EXPECT_TRUE(render_thread_.printer()->GetBitmapChecksum(0, &bitmap_actual));
    if (kTestPages[i].checksum)
      EXPECT_EQ(kTestPages[i].checksum, bitmap_actual);

    if (baseline) {
      // Save the source data and the bitmap data into temporary files to
      // create base-line results.
      FilePath source_path;
      file_util::CreateTemporaryFile(&source_path);
      render_thread_.printer()->SaveSource(0, source_path);

      FilePath bitmap_path;
      file_util::CreateTemporaryFile(&bitmap_path);
      render_thread_.printer()->SaveBitmap(0, bitmap_path);
    }
  }
}
#endif<commit_msg>Really fix build break<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "chrome/renderer/print_web_view_helper.h"
#include "chrome/test/render_view_test.h"
#include "printing/image.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"

using WebKit::WebFrame;
using WebKit::WebString;
using WebKit::WebView;

namespace {

const char kPrintWithJSHTML[] =
    "HelloWorld";

}  // namespace

// Tests that printing pages work and sending and receiving messages through
// that channel all works.
TEST_F(RenderViewTest, OnPrintPages) {
  // Lets simulate a print pages with Hello world.
  LoadHTML("
Hello World!
");
  PrintWebViewHelper::Get(view_)->OnPrintPages();

  VerifyPageCount(1);
  VerifyPagesPrinted(true);
}

// Duplicate of OnPrintPagesTest only using javascript to print.
TEST_F(RenderViewTest, PrintWithJavascript) {
  // HTML contains a call to window.print()
  LoadHTML(kPrintWithJSHTML);

  VerifyPageCount(1);
  VerifyPagesPrinted(true);
}

// Tests that the renderer blocks window.print() calls if they occur too
// frequently.
TEST_F(RenderViewTest, BlockScriptInitiatedPrinting) {
  // Pretend user will cancel printing.
  render_thread_.set_print_dialog_user_response(false);
  // Try to print with window.print() a few times.
  LoadHTML(kPrintWithJSHTML);
  LoadHTML(kPrintWithJSHTML);
  LoadHTML(kPrintWithJSHTML);
  VerifyPagesPrinted(false);

  // Pretend user will print. (but printing is blocked.)
  render_thread_.set_print_dialog_user_response(true);
  LoadHTML(kPrintWithJSHTML);
  VerifyPagesPrinted(false);

  // Unblock script initiated printing and verify printing works.
  PrintWebViewHelper::Get(view_)->ResetScriptedPrintCount();
  render_thread_.printer()->ResetPrinter();
  LoadHTML(kPrintWithJSHTML);
  VerifyPageCount(1);
  VerifyPagesPrinted(true);
}

#if defined(OS_WIN) || defined(OS_MACOSX)
// TODO(estade): I don't think this test is worth porting to Linux. We will have
// to rip out and replace most of the IPC code if we ever plan to improve
// printing, and the comment below by sverrir suggests that it doesn't do much
// for us anyway.
TEST_F(RenderViewTest, PrintWithIframe) {
  // Document that populates an iframe.
  const char html[] =
      "Lorem Ipsum:"
      "";

  LoadHTML(html);

  // Find the frame and set it as the focused one.  This should mean that that
  // the printout should only contain the contents of that frame.
  WebFrame* sub1_frame =
      view_->webview()->findFrameByName(WebString::fromUTF8("sub1"));
  ASSERT_TRUE(sub1_frame);
  view_->webview()->setFocusedFrame(sub1_frame);
  ASSERT_NE(view_->webview()->focusedFrame(),
            view_->webview()->mainFrame());

  // Initiate printing.
  PrintWebViewHelper::Get(view_)->OnPrintPages();

  // Verify output through MockPrinter.
  const MockPrinter* printer(render_thread_.printer());
  ASSERT_EQ(1, printer->GetPrintedPages());
  const printing::Image& image1(printer->GetPrintedPage(0)->image());

  // TODO(sverrir): Figure out a way to improve this test to actually print
  // only the content of the iframe.  Currently image1 will contain the full
  // page.
  EXPECT_NE(0, image1.size().width());
  EXPECT_NE(0, image1.size().height());
}
#endif

// Tests if we can print a page and verify its results.
// This test prints HTML pages into a pseudo printer and check their outputs,
// i.e. a simplified version of the PrintingLayoutTextTest UI test.
namespace {
// Test cases used in this test.
struct TestPageData {
  const char* page;
  size_t printed_pages;
  int width;
  int height;
  const char* checksum;
  const wchar_t* file;
};

const TestPageData kTestPages[] = {
  {""
  ""
  "<meta"
  "  http-equiv=\"Content-Type\""
  "  content=\"text/html; charset=utf-8\"/>"
  "<title>Test 1</title>"
  ""
  ""
  "
Hello World!
"
  "",
#if defined(OS_MACOSX)
  // Mac printing code compensates for the WebKit scale factor while generating
  // the metafile, so we expect smaller pages.
  1, 540, 720,
#else
  1, 675, 900,
#endif
  NULL,
  NULL,
  },
};
}  // namespace

// TODO(estade): need to port MockPrinter to get this on Linux. This involves
// hooking up Cairo to read a pdf stream, or accessing the cairo surface in the
// metafile directly.
#if defined(OS_WIN) || defined(OS_MACOSX)
TEST_F(RenderViewTest, PrintLayoutTest) {
  bool baseline = false;

  EXPECT_TRUE(render_thread_.printer() != NULL);
  for (size_t i = 0; i < arraysize(kTestPages); ++i) {
    // Load an HTML page and print it.
    LoadHTML(kTestPages[i].page);
    PrintWebViewHelper::Get(view_)->OnPrintPages();

    // MockRenderThread::Send() just calls MockRenderThread::OnMsgReceived().
    // So, all IPC messages sent in the above RenderView::OnPrintPages() call
    // has been handled by the MockPrinter object, i.e. this printing job
    // has been already finished.
    // So, we can start checking the output pages of this printing job.
    // Retrieve the number of pages actually printed.
    size_t pages = render_thread_.printer()->GetPrintedPages();
    EXPECT_EQ(kTestPages[i].printed_pages, pages);

    // Retrieve the width and height of the output page.
    int width = render_thread_.printer()->GetWidth(0);
    int height = render_thread_.printer()->GetHeight(0);

    // Check with margin for error.  This has been failing with a one pixel
    // offset on our buildbot.
    const int kErrorMargin = 5;  // 5%
    EXPECT_GT(kTestPages[i].width * (100 + kErrorMargin) / 100, width);
    EXPECT_LT(kTestPages[i].width * (100 - kErrorMargin) / 100, width);
    EXPECT_GT(kTestPages[i].height * (100 + kErrorMargin) / 100, height);
    EXPECT_LT(kTestPages[i].height* (100 - kErrorMargin) / 100, height);

    // Retrieve the checksum of the bitmap data from the pseudo printer and
    // compare it with the expected result.
    std::string bitmap_actual;
    EXPECT_TRUE(render_thread_.printer()->GetBitmapChecksum(0, &bitmap_actual));
    if (kTestPages[i].checksum)
      EXPECT_EQ(kTestPages[i].checksum, bitmap_actual);

    if (baseline) {
      // Save the source data and the bitmap data into temporary files to
      // create base-line results.
      FilePath source_path;
      file_util::CreateTemporaryFile(&source_path);
      render_thread_.printer()->SaveSource(0, source_path);

      FilePath bitmap_path;
      file_util::CreateTemporaryFile(&bitmap_path);
      render_thread_.printer()->SaveBitmap(0, bitmap_path);
    }
  }
}
#endif
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

#include "OgreGLES2FBOMultiRenderTarget.h"

namespace Ogre {

	GLES2FBOMultiRenderTarget::GLES2FBOMultiRenderTarget(GLES2FBOManager *manager, const String &name):
		MultiRenderTarget(name),
		fbo(manager, 0 /* TODO: multisampling on MRTs? */)
	{
	}
	GLES2FBOMultiRenderTarget::~GLES2FBOMultiRenderTarget()
	{
	}

	void GLES2FBOMultiRenderTarget::bindSurfaceImpl(size_t attachment, RenderTexture *target)
	{
#if GL_OES_packed_depth_stencil
		/// Check if the render target is in the rendertarget->FBO map
        GLES2FrameBufferObject *fbobj = 0;
        target->getCustomAttribute("FBO", &fbobj);
		assert(fbobj);
		fbo.bindSurface(attachment, fbobj->getSurface(0));
        GL_CHECK_ERROR;
#endif
		// Initialise?

		// Set width and height
		mWidth = fbo.getWidth();
		mHeight = fbo.getHeight();
	}

	void GLES2FBOMultiRenderTarget::unbindSurfaceImpl(size_t attachment)
	{
		fbo.unbindSurface(attachment);
        GL_CHECK_ERROR;

		// Set width and height
		mWidth = fbo.getWidth();
		mHeight = fbo.getHeight();
	}

	void GLES2FBOMultiRenderTarget::getCustomAttribute( const String& name, void *pData )
	{
		if(name=="FBO")
        {
            *static_cast<GLES2FrameBufferObject **>(pData) = &fbo;
        }
	}
	//-----------------------------------------------------------------------------
	bool GLES2FBOMultiRenderTarget::attachDepthBuffer( DepthBuffer *depthBuffer )
	{
		bool result;
		if( (result = MultiRenderTarget::attachDepthBuffer( depthBuffer )) )
			fbo.attachDepthBuffer( depthBuffer );

		return result;
	}
	//-----------------------------------------------------------------------------
	void GLES2FBOMultiRenderTarget::detachDepthBuffer()
	{
		fbo.detachDepthBuffer();
		MultiRenderTarget::detachDepthBuffer();
	}
	//-----------------------------------------------------------------------------
	void GLES2FBOMultiRenderTarget::_detachDepthBuffer()
	{
		fbo.detachDepthBuffer();
		MultiRenderTarget::_detachDepthBuffer();
	}
}
<commit_msg>Fix the GLES 2 build<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

#include "OgreGLES2FBOMultiRenderTarget.h"
#include "OgreLogManager.h"

namespace Ogre {

	GLES2FBOMultiRenderTarget::GLES2FBOMultiRenderTarget(GLES2FBOManager *manager, const String &name):
		MultiRenderTarget(name),
		fbo(manager, 0 /* TODO: multisampling on MRTs? */)
	{
	}
	GLES2FBOMultiRenderTarget::~GLES2FBOMultiRenderTarget()
	{
	}

	void GLES2FBOMultiRenderTarget::bindSurfaceImpl(size_t attachment, RenderTexture *target)
	{
#if GL_OES_packed_depth_stencil
		/// Check if the render target is in the rendertarget->FBO map
        GLES2FrameBufferObject *fbobj = 0;
        target->getCustomAttribute("FBO", &fbobj);
		assert(fbobj);
		fbo.bindSurface(attachment, fbobj->getSurface(0));
        GL_CHECK_ERROR;
#endif
		// Initialise?

		// Set width and height
		mWidth = fbo.getWidth();
		mHeight = fbo.getHeight();
	}

	void GLES2FBOMultiRenderTarget::unbindSurfaceImpl(size_t attachment)
	{
		fbo.unbindSurface(attachment);
        GL_CHECK_ERROR;

		// Set width and height
		mWidth = fbo.getWidth();
		mHeight = fbo.getHeight();
	}

	void GLES2FBOMultiRenderTarget::getCustomAttribute( const String& name, void *pData )
	{
		if(name=="FBO")
        {
            *static_cast<GLES2FrameBufferObject **>(pData) = &fbo;
        }
	}
	//-----------------------------------------------------------------------------
	bool GLES2FBOMultiRenderTarget::attachDepthBuffer( DepthBuffer *depthBuffer )
	{
		bool result;
		if( (result = MultiRenderTarget::attachDepthBuffer( depthBuffer )) )
			fbo.attachDepthBuffer( depthBuffer );

		return result;
	}
	//-----------------------------------------------------------------------------
	void GLES2FBOMultiRenderTarget::detachDepthBuffer()
	{
		fbo.detachDepthBuffer();
		MultiRenderTarget::detachDepthBuffer();
	}
	//-----------------------------------------------------------------------------
	void GLES2FBOMultiRenderTarget::_detachDepthBuffer()
	{
		fbo.detachDepthBuffer();
		MultiRenderTarget::_detachDepthBuffer();
	}
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkBox.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkBox.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkBox, "1.1");
vtkStandardNewMacro(vtkBox);

// Construct the box centered at the origin and each side length 1.0.
vtkBox::vtkBox()
{
  this->XMin[0] = -0.5;
  this->XMin[1] = -0.5;
  this->XMin[2] = -0.5;

  this->XMax[0] =  0.5;
  this->XMax[1] =  0.5;
  this->XMax[2] =  0.5;
}

// Set the bounds in various ways
void vtkBox::SetBounds(float xMin, float xMax,
                       float yMin, float yMax,
                       float zMin, float zMax)
{
  if ( this->XMin[0] != xMin || this->XMax[0] != xMax ||
       this->XMin[1] != yMin || this->XMax[1] != yMax ||
       this->XMin[2] != zMin || this->XMax[2] != yMax )
    {
    this->XMin[0] = xMin;
    this->XMax[0] = xMax;
    this->XMin[1] = yMin;
    this->XMax[1] = yMax;
    this->XMin[2] = zMin;
    this->XMax[2] = zMax;
    for (int i=0; i<3; i++)
      {
      if ( this->XMax[i] < this->XMin[i] )
        {
        this->XMax[i] = this->XMin[i];
        }
      }
    this->Modified();
    }
}

void vtkBox::SetBounds(float bounds[6])
{
  this->SetBounds(bounds[0],bounds[1], bounds[2],bounds[3],
                  bounds[4],bounds[5]);
}

void vtkBox::GetBounds(float &xMin, float &xMax,
                       float &yMin, float &yMax,
                       float &zMin, float &zMax)
{
  xMin = this->XMin[0];
  yMin = this->XMin[1];
  zMin = this->XMin[2];
  xMax = this->XMax[0];
  yMax = this->XMax[1];
  zMax = this->XMax[2];
}

void vtkBox::GetBounds(float bounds[6])
{
  for (int i=0; i<3; i++)
    {
    bounds[2*i] = this->XMin[i];
    bounds[2*i+1] = this->XMax[i];
    }
}

// Evaluate box equation. This differs from the similar vtkPlanes
// (with six planes) because of the "rounded" nature of the corners.
float vtkBox::EvaluateFunction(float x[3])
{
  float diff, dist, minDistance=(-VTK_LARGE_FLOAT), t, distance=0.0;
  int inside=1;
  for (int i=0; i<3; i++)
    {
    diff = this->XMax[i] - this->XMin[i];
    if ( diff != 0.0 )
      {
      t = (x[i]-this->XMin[i]) / (this->XMax[i]-this->XMin[i]);
      if ( t < 0.0 )
        {
        inside = 0;
        dist = this->XMin[i] - x[i];
        }
      else if ( t > 1.0 )
        {
        inside = 0;
        dist = x[i] - this->XMax[i];
        }
      else
        {//want negative distance, we are inside
        if ( t <= 0.5 )
          {
          dist = this->XMin[i] - x[i];
          }
        else
          {
          dist = x[i] - this->XMax[i];
          }
        if ( dist > minDistance ) //remember, it's negative
          {
          minDistance = dist;
          }
        }//if inside
      }
    else
      {
      dist = fabs(x[i]-this->XMin[i]);
      if ( x[i] != this->XMin[i] )
        {
        inside = 0;
        }
      }
    if ( dist > 0.0 )
      {
      distance += dist*dist;
      }
    }//for all coordinate directions

  distance = sqrt(distance);
  if ( inside )
    {
    return minDistance;
    }
  else
    {
    return distance;
    }
}

// Evaluate box gradient.
void vtkBox::EvaluateGradient(float x[3], float n[3])
{
  int i, dir[3], loc[3], minAxis, minDir;
  float dist, minDist=VTK_LARGE_FLOAT, center[3];

  // Compute the location of the point with respect to the box
  for (i=0; i<3; i++)
    {
    if ( x[i] < this->XMin[i] )
      {
      loc[i] = 0;
      }
    else if ( x[i] > this->XMax[i] )
      {
      loc[i] = 2;
      }
    else
      {
      loc[i] = 1;
      center[i] = (this->XMin[i] + this->XMax[i])/2.0;
      if ( x[i] <= center[i] )
        {
        dist = x[i] - this->XMin[i];
        dir[i] = -1;
        }
      else
        {
        dist = this->XMax[i] - x[i];
        dir[i] = 1;
        }
      if ( dist < minDist ) //remember, it's negative
        {
        minDist = dist;
        minAxis = i;
        minDir = dir[i];
        }
      }//if inside
    }//for all coordinate directions

  int indx = loc[0] + 3*loc[1] + 9*loc[2];

  n[0] = n[1] = n[2] = 0.0;
  switch (indx)
    {
    case 0:
      break;

    }
}

#define VTK_RIGHT 0
#define VTK_LEFT 1
#define VTK_MIDDLE 2

// Bounding box intersection modified from Graphics Gems Vol I. The method
// returns a non-zero value if the bounding box is hit. Origin[3] starts
// the ray, dir[3] is the vector components of the ray in the x-y-z
// directions, coord[3] is the location of hit, and t is the parametric
// coordinate along line. (Notes: the intersection ray dir[3] is NOT
// normalized.  Valid intersections will only occur between 0<=t<=1.)
char vtkBox::IntersectBox (float bounds[6], float origin[3], float dir[3],
                           float coord[3], float& t)
{
  char    inside=1;
  char    quadrant[3];
  int     i, whichPlane=0;
  float   maxT[3], candidatePlane[3];

  //  First find closest planes
  //
  for (i=0; i<3; i++)
    {
    if ( origin[i] < bounds[2*i] )
      {
      quadrant[i] = VTK_LEFT;
      candidatePlane[i] = bounds[2*i];
      inside = 0;
      }
    else if ( origin[i] > bounds[2*i+1] )
      {
      quadrant[i] = VTK_RIGHT;
      candidatePlane[i] = bounds[2*i+1];
      inside = 0;
      }
    else
      {
      quadrant[i] = VTK_MIDDLE;
      }
    }

  //  Check whether origin of ray is inside bbox
  //
  if (inside)
    {
    coord[0] = origin[0];
    coord[1] = origin[1];
    coord[2] = origin[2];
    t = 0;
    return 1;
    }

  //  Calculate parametric distances to plane
  //
  for (i=0; i<3; i++)
    {
    if ( quadrant[i] != VTK_MIDDLE && dir[i] != 0.0 )
      {
      maxT[i] = (candidatePlane[i]-origin[i]) / dir[i];
      }
    else
      {
      maxT[i] = -1.0;
      }
    }

  //  Find the largest parametric value of intersection
  //
  for (i=0; i<3; i++)
    {
    if ( maxT[whichPlane] < maxT[i] )
      {
      whichPlane = i;
      }
    }

  //  Check for valid intersection along line
  //
  if ( maxT[whichPlane] > 1.0 || maxT[whichPlane] < 0.0 )
    {
    return 0;
    }
  else
    {
    t = maxT[whichPlane];
    }

  //  Intersection point along line is okay.  Check bbox.
  //
  for (i=0; i<3; i++)
    {
    if (whichPlane != i)
      {
      coord[i] = origin[i] + maxT[whichPlane]*dir[i];
      if ( coord[i] < bounds[2*i] || coord[i] > bounds[2*i+1] )
        {
        return 0;
        }
      }
    else
      {
      coord[i] = candidatePlane[i];
      }
    }

    return 1;
}
#undef VTK_RIGHT
#undef VTK_LEFT
#undef VTK_MIDDLE

void vtkBox::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "XMin: (" << this->XMin[0] << ", "
               << this->XMin[1] << ", " << this->XMin[2] << ")\n";
  os << indent << "XMax: (" << this->XMax[0] << ", "
               << this->XMax[1] << ", " << this->XMax[2] << ")\n";
}
<commit_msg>ENH:Added vtkBox implicit function; gradient computed properly<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkBox.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkBox.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkBox, "1.2");
vtkStandardNewMacro(vtkBox);

// Construct the box centered at the origin and each side length 1.0.
vtkBox::vtkBox()
{
  this->XMin[0] = -0.5;
  this->XMin[1] = -0.5;
  this->XMin[2] = -0.5;

  this->XMax[0] =  0.5;
  this->XMax[1] =  0.5;
  this->XMax[2] =  0.5;
}

// Set the bounds in various ways
void vtkBox::SetBounds(float xMin, float xMax,
                       float yMin, float yMax,
                       float zMin, float zMax)
{
  if ( this->XMin[0] != xMin || this->XMax[0] != xMax ||
       this->XMin[1] != yMin || this->XMax[1] != yMax ||
       this->XMin[2] != zMin || this->XMax[2] != yMax )
    {
    this->XMin[0] = xMin;
    this->XMax[0] = xMax;
    this->XMin[1] = yMin;
    this->XMax[1] = yMax;
    this->XMin[2] = zMin;
    this->XMax[2] = zMax;
    for (int i=0; i<3; i++)
      {
      if ( this->XMax[i] < this->XMin[i] )
        {
        this->XMax[i] = this->XMin[i];
        }
      }
    this->Modified();
    }
}

void vtkBox::SetBounds(float bounds[6])
{
  this->SetBounds(bounds[0],bounds[1], bounds[2],bounds[3],
                  bounds[4],bounds[5]);
}

void vtkBox::GetBounds(float &xMin, float &xMax,
                       float &yMin, float &yMax,
                       float &zMin, float &zMax)
{
  xMin = this->XMin[0];
  yMin = this->XMin[1];
  zMin = this->XMin[2];
  xMax = this->XMax[0];
  yMax = this->XMax[1];
  zMax = this->XMax[2];
}

void vtkBox::GetBounds(float bounds[6])
{
  for (int i=0; i<3; i++)
    {
    bounds[2*i] = this->XMin[i];
    bounds[2*i+1] = this->XMax[i];
    }
}

// Evaluate box equation. This differs from the similar vtkPlanes
// (with six planes) because of the "rounded" nature of the corners.
float vtkBox::EvaluateFunction(float x[3])
{
  float diff, dist, minDistance=(-VTK_LARGE_FLOAT), t, distance=0.0;
  int inside=1;
  for (int i=0; i<3; i++)
    {
    diff = this->XMax[i] - this->XMin[i];
    if ( diff != 0.0 )
      {
      t = (x[i]-this->XMin[i]) / (this->XMax[i]-this->XMin[i]);
      if ( t < 0.0 )
        {
        inside = 0;
        dist = this->XMin[i] - x[i];
        }
      else if ( t > 1.0 )
        {
        inside = 0;
        dist = x[i] - this->XMax[i];
        }
      else
        {//want negative distance, we are inside
        if ( t <= 0.5 )
          {
          dist = this->XMin[i] - x[i];
          }
        else
          {
          dist = x[i] - this->XMax[i];
          }
        if ( dist > minDistance ) //remember, it's negative
          {
          minDistance = dist;
          }
        }//if inside
      }
    else
      {
      dist = fabs(x[i]-this->XMin[i]);
      if ( x[i] != this->XMin[i] )
        {
        inside = 0;
        }
      }
    if ( dist > 0.0 )
      {
      distance += dist*dist;
      }
    }//for all coordinate directions

  distance = sqrt(distance);
  if ( inside )
    {
    return minDistance;
    }
  else
    {
    return distance;
    }
}

// Evaluate box gradient.
void vtkBox::EvaluateGradient(float x[3], float n[3])
{
  int i, loc[3], minAxis=0;
  float dist, minDist=VTK_LARGE_FLOAT, center[3];
  float inDir[3], outDir[3];

  // Compute the location of the point with respect to the box.
  // Ultimately the point will lie in one of 27 separate regions around
  // or within the box. The gradient vector is computed differently in
  // each of the regions.
  inDir[0] = inDir[1] = inDir[2] = 0.0f;
  outDir[0] = outDir[1] = outDir[2] = 0.0f;
  for (i=0; i<3; i++)
    {
    center[i] = (this->XMin[i] + this->XMax[i])/2.0;
    if ( x[i] < this->XMin[i] )
      {
      loc[i] = 0;
      outDir[i] = -1.0f;
      }
    else if ( x[i] > this->XMax[i] )
      {
      loc[i] = 2;
      outDir[i] = 1.0f;
      }
    else
      {
      loc[i] = 1;
      if ( x[i] <= center[i] )
        {
        dist = x[i] - this->XMin[i];
        inDir[i] = -1.0f;
        }
      else
        {
        dist = this->XMax[i] - x[i];
        inDir[i] = 1.0f;
        }
      if ( dist < minDist ) //remember, it's negative
        {
        minDist = dist;
        minAxis = i;
        }
      }//if inside
    }//for all coordinate directions

  int indx = loc[0] + 3*loc[1] + 9*loc[2];

  switch (indx)
    {
    // verts - gradient points away from center point
    case 0: case 2: case 6: case 8: case 18: case 20: case 24: case 26:
      for (i=0; i<3; i++)
        {
        n[i] = x[i] - center[i];
        }
      vtkMath::Normalize(n);
      break;

    // edges - gradient points out from axis of cube
    case 1: case 3: case 5: case 7:
    case 9: case 11: case 15: case 17:
    case 19: case 21: case 23: case 25:
      for (i=0; i<3; i++)
        {
        if ( outDir[i] != 0.0f )
          {
          n[i] = x[i] - center[i];
          }
        else
          {
          n[i] = 0.0;
          }
        }
      vtkMath::Normalize(n);
      break;

    // faces - gradient points perpendicular to face
    case 4: case 10: case 12: case 14: case 16: case 22:
      for (i=0; i<3; i++)
        {
        n[i] = outDir[i];
        }
      break;

    // interior - gradient is perpendicular to closest face
    case 13:
      n[0] = n[1] = n[2] = 0.0;
      n[minAxis] = inDir[minAxis];
      break;
    }
}

#define VTK_RIGHT 0
#define VTK_LEFT 1
#define VTK_MIDDLE 2

// Bounding box intersection modified from Graphics Gems Vol I. The method
// returns a non-zero value if the bounding box is hit. Origin[3] starts
// the ray, dir[3] is the vector components of the ray in the x-y-z
// directions, coord[3] is the location of hit, and t is the parametric
// coordinate along line. (Notes: the intersection ray dir[3] is NOT
// normalized.  Valid intersections will only occur between 0<=t<=1.)
char vtkBox::IntersectBox (float bounds[6], float origin[3], float dir[3],
                           float coord[3], float& t)
{
  char    inside=1;
  char    quadrant[3];
  int     i, whichPlane=0;
  float   maxT[3], candidatePlane[3];

  //  First find closest planes
  //
  for (i=0; i<3; i++)
    {
    if ( origin[i] < bounds[2*i] )
      {
      quadrant[i] = VTK_LEFT;
      candidatePlane[i] = bounds[2*i];
      inside = 0;
      }
    else if ( origin[i] > bounds[2*i+1] )
      {
      quadrant[i] = VTK_RIGHT;
      candidatePlane[i] = bounds[2*i+1];
      inside = 0;
      }
    else
      {
      quadrant[i] = VTK_MIDDLE;
      }
    }

  //  Check whether origin of ray is inside bbox
  //
  if (inside)
    {
    coord[0] = origin[0];
    coord[1] = origin[1];
    coord[2] = origin[2];
    t = 0;
    return 1;
    }

  //  Calculate parametric distances to plane
  //
  for (i=0; i<3; i++)
    {
    if ( quadrant[i] != VTK_MIDDLE && dir[i] != 0.0 )
      {
      maxT[i] = (candidatePlane[i]-origin[i]) / dir[i];
      }
    else
      {
      maxT[i] = -1.0;
      }
    }

  //  Find the largest parametric value of intersection
  //
  for (i=0; i<3; i++)
    {
    if ( maxT[whichPlane] < maxT[i] )
      {
      whichPlane = i;
      }
    }

  //  Check for valid intersection along line
  //
  if ( maxT[whichPlane] > 1.0 || maxT[whichPlane] < 0.0 )
    {
    return 0;
    }
  else
    {
    t = maxT[whichPlane];
    }

  //  Intersection point along line is okay.  Check bbox.
  //
  for (i=0; i<3; i++)
    {
    if (whichPlane != i)
      {
      coord[i] = origin[i] + maxT[whichPlane]*dir[i];
      if ( coord[i] < bounds[2*i] || coord[i] > bounds[2*i+1] )
        {
        return 0;
        }
      }
    else
      {
      coord[i] = candidatePlane[i];
      }
    }

    return 1;
}
#undef VTK_RIGHT
#undef VTK_LEFT
#undef VTK_MIDDLE

void vtkBox::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "XMin: (" << this->XMin[0] << ", "
               << this->XMin[1] << ", " << this->XMin[2] << ")\n";
  os << indent << "XMax: (" << this->XMax[0] << ", "
               << this->XMax[1] << ", " << this->XMax[2] << ")\n";
}
<|endoftext|>


<commit_before>// Copyright 2009, Squish Tech, LLC.
#include "libxmljs.h"
#include "xml_syntax_error.h"
#include "xml_document.h"
#include "xml_node.h"
#include "xml_parser.h"
#include "html_parser.h"

namespace libxmljs {

    v8::Persistent<v8::FunctionTemplate> memory_usage;

namespace {

void on_libxml_destruct(xmlNode* node) {
}

}  // namespace

LibXMLJS::LibXMLJS() {
  xmlInitParser();  // Not always necessary, but necessary for thread safety.
  // xmlRegisterNodeDefault(on_libxml_construct);
  xmlDeregisterNodeDefault(on_libxml_destruct);
  // xmlThrDefRegisterNodeDefault(on_libxml_construct);
  xmlThrDefDeregisterNodeDefault(on_libxml_destruct);
}

LibXMLJS::~LibXMLJS() {
  xmlCleanupParser();  // As per xmlInitParser(), or memory leak will happen.
}

LibXMLJS LibXMLJS::init_;

static void
OnFatalError(const char* location,
             const char* message) {
#define FATAL_ERROR "\033[1;31mV8 FATAL ERROR.\033[m"
  if (location)
    fprintf(stderr, FATAL_ERROR " %s %s\n", location, message);
  else
    fprintf(stderr, FATAL_ERROR " %s\n", message);

  exit(1);
}

// Extracts a C str from a V8 Utf8Value.
// TODO: Fix this error state, maybe throw exception?
const char *
ToCString(const v8::String::Utf8Value& value) {
  return *value ? *value : "<str conversion failed>";
}

static void
ReportException(v8::TryCatch* try_catch) {
  v8::Handle<v8::Message> message = try_catch->Message();
  if (message.IsEmpty()) {
    fprintf(stderr, "Error: (no message)\n");
    fflush(stderr);
    return;
  }
  v8::Handle<v8::Value> error = try_catch->Exception();
  v8::Handle<v8::String> stack;
  if (error->IsObject()) {
    v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(error);
    v8::Handle<v8::Value> raw_stack = obj->Get(v8::String::New("stack"));
    if (raw_stack->IsString()) stack = v8::Handle<v8::String>::Cast(raw_stack);
  }
  if (stack.IsEmpty()) {
    v8::String::Utf8Value exception(error);

    // Print (filename):(line number): (message).
    v8::String::Utf8Value filename(message->GetScriptResourceName());
    const char* filename_string = ToCString(filename);
    int linenum = message->GetLineNumber();
    fprintf(stderr, "%s:%i: %s\n", filename_string, linenum, *exception);
    // Print line of source code.
    v8::String::Utf8Value sourceline(message->GetSourceLine());
    const char* sourceline_string = ToCString(sourceline);
    fprintf(stderr, "%s\n", sourceline_string);
    // Print wavy underline (GetUnderline is deprecated).
    int start = message->GetStartColumn();
    for (int i = 0; i < start; i++) {
      fprintf(stderr, " ");
    }
    int end = message->GetEndColumn();
    for (int i = start; i < end; i++) {
      fprintf(stderr, "^");
    }
    fprintf(stderr, "\n");

    message->PrintCurrentStackTrace(stderr);

  } else {
    v8::String::Utf8Value trace(stack);
    fprintf(stderr, "%s\n", *trace);
  }
  fflush(stderr);
}

// Executes a str within the current v8 context.
v8::Handle<v8::Value>
ExecuteString(v8::Handle<v8::String> source,
              v8::Handle<v8::Value> filename) {
  v8::HandleScope scope;
  v8::TryCatch try_catch;

  v8::Handle<v8::Script> script = v8::Script::Compile(source, filename);
  if (script.IsEmpty()) {
    ReportException(&try_catch);
    exit(1);
  }

  v8::Handle<v8::Value> result = script->Run();
  if (result.IsEmpty()) {
    ReportException(&try_catch);
    exit(1);
  }

  return scope.Close(result);
}

static void
ExecuteNativeJS(const char* filename,
                const char* data) {
  v8::HandleScope scope;
  v8::TryCatch try_catch;
  ExecuteString(v8::String::New(data), v8::String::New(filename));
  if (try_catch.HasCaught())  {
    puts("There is an error in Node's built-in javascript");
    puts("This should be reported as a bug!");
    ReportException(&try_catch);
    exit(1);
  }
}

void
UpdateV8Memory() {
    v8::V8::AdjustAmountOfExternalAllocatedMemory(-current_xml_memory);
    current_xml_memory = xmlMemUsed();
    v8::V8::AdjustAmountOfExternalAllocatedMemory(current_xml_memory);
}

v8::Handle<v8::Value>
MemoryUsage(const v8::Arguments& args) {
    v8::HandleScope scope;
    v8::Local<v8::Object> obj = v8::Object::New();
    long c = xmlMemUsed();

    obj->Set(v8::String::New("libxml"), v8::Integer::New(c));
    obj->Set(v8::String::New("v8"), v8::Integer::New(current_xml_memory));

    return scope.Close(obj);
}

void
InitializeLibXMLJS(v8::Handle<v8::Object> target) {
  v8::HandleScope scope;

  xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
  xmlInitMemory();

  XmlSyntaxError::Initialize(target);
  XmlDocument::Initialize(target);
  XmlParser::Initialize(target);
  HtmlParser::Initialize(target);

  target->Set(v8::String::NewSymbol("version"),
              v8::String::New(LIBXMLJS_VERSION));

  target->Set(v8::String::NewSymbol("libxml_version"),
              v8::String::New(LIBXML_DOTTED_VERSION));

  target->Set(v8::String::NewSymbol("libxml_parser_version"),
              v8::String::New(xmlParserVersion));

  target->Set(v8::String::NewSymbol("libxml_debug_enabled"),
              v8::Boolean::New(debugging));

  v8::Local<v8::FunctionTemplate> func = v8::FunctionTemplate::New(MemoryUsage);
  memory_usage = v8::Persistent<v8::FunctionTemplate>::New(func);
  memory_usage->InstanceTemplate()->SetInternalFieldCount(1);

  target->Set(v8::String::NewSymbol("memoryUsage"),
              memory_usage->GetFunction());

  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
  v8::Handle<v8::Context> context = v8::Context::New(NULL, global);

  v8::Context::Scope context_scope(context);
  context->Global()->Set(v8::String::NewSymbol("libxml"), target);

  ExecuteNativeJS("xml_sax_parser.js", native_xml_sax_parser);
  ExecuteNativeJS("xml_document.js", native_xml_document);
  ExecuteNativeJS("xml_element.js", native_xml_element);
}

// used by node.js to initialize libraries
extern "C" void
init(v8::Handle<v8::Object> target) {
  v8::HandleScope scope;
  InitializeLibXMLJS(target);
}

int
main(int argc,
     char* argv[]) {
  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  v8::V8::Initialize();
  v8::V8::SetFatalErrorHandler(OnFatalError);

  // Create a stack-allocated handle scope.
  v8::HandleScope handle_scope;
  // Create a new context.
  v8::Handle<v8::Context> context = v8::Context::New();
  // Enter the created context for compiling and
  // running the hello world script.
  v8::Context::Scope context_scope(context);

  v8::Local<v8::Object> global_obj = v8::Context::GetCurrent()->Global();
  v8::Local<v8::Object> libxml_obj = v8::Object::New();

  InitializeLibXMLJS(libxml_obj);

  global_obj->Set(v8::String::NewSymbol("libxml"), libxml_obj);

  // for (int i = 1; i < argc; i++) {
  //   // Create a string containing the JavaScript source code.
  //   Handle<String> source = ReadFile(argv[i]);
  //   // Compile the source code.
  //   Handle<Script> script = Script::Compile(source);
  //   // Run the script to get the result.
  //   Handle<Value> result = script->Run();
  // }

  v8::V8::Dispose();

  return 0;
}
}  // namespace libxmljs
<commit_msg>Call xmlMemSetup in static constructor to track memory from xmlInitParser<commit_after>// Copyright 2009, Squish Tech, LLC.
#include "libxmljs.h"
#include "xml_syntax_error.h"
#include "xml_document.h"
#include "xml_node.h"
#include "xml_parser.h"
#include "html_parser.h"

namespace libxmljs {

    v8::Persistent<v8::FunctionTemplate> memory_usage;

namespace {

void on_libxml_destruct(xmlNode* node) {
}

}  // namespace

LibXMLJS::LibXMLJS() {
  xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);

  xmlInitParser();  // Not always necessary, but necessary for thread safety.
  // xmlRegisterNodeDefault(on_libxml_construct);
  xmlDeregisterNodeDefault(on_libxml_destruct);
  // xmlThrDefRegisterNodeDefault(on_libxml_construct);
  xmlThrDefDeregisterNodeDefault(on_libxml_destruct);
}

LibXMLJS::~LibXMLJS() {
  xmlCleanupParser();  // As per xmlInitParser(), or memory leak will happen.
}

LibXMLJS LibXMLJS::init_;

static void
OnFatalError(const char* location,
             const char* message) {
#define FATAL_ERROR "\033[1;31mV8 FATAL ERROR.\033[m"
  if (location)
    fprintf(stderr, FATAL_ERROR " %s %s\n", location, message);
  else
    fprintf(stderr, FATAL_ERROR " %s\n", message);

  exit(1);
}

// Extracts a C str from a V8 Utf8Value.
// TODO: Fix this error state, maybe throw exception?
const char *
ToCString(const v8::String::Utf8Value& value) {
  return *value ? *value : "<str conversion failed>";
}

static void
ReportException(v8::TryCatch* try_catch) {
  v8::Handle<v8::Message> message = try_catch->Message();
  if (message.IsEmpty()) {
    fprintf(stderr, "Error: (no message)\n");
    fflush(stderr);
    return;
  }
  v8::Handle<v8::Value> error = try_catch->Exception();
  v8::Handle<v8::String> stack;
  if (error->IsObject()) {
    v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(error);
    v8::Handle<v8::Value> raw_stack = obj->Get(v8::String::New("stack"));
    if (raw_stack->IsString()) stack = v8::Handle<v8::String>::Cast(raw_stack);
  }
  if (stack.IsEmpty()) {
    v8::String::Utf8Value exception(error);

    // Print (filename):(line number): (message).
    v8::String::Utf8Value filename(message->GetScriptResourceName());
    const char* filename_string = ToCString(filename);
    int linenum = message->GetLineNumber();
    fprintf(stderr, "%s:%i: %s\n", filename_string, linenum, *exception);
    // Print line of source code.
    v8::String::Utf8Value sourceline(message->GetSourceLine());
    const char* sourceline_string = ToCString(sourceline);
    fprintf(stderr, "%s\n", sourceline_string);
    // Print wavy underline (GetUnderline is deprecated).
    int start = message->GetStartColumn();
    for (int i = 0; i < start; i++) {
      fprintf(stderr, " ");
    }
    int end = message->GetEndColumn();
    for (int i = start; i < end; i++) {
      fprintf(stderr, "^");
    }
    fprintf(stderr, "\n");

    message->PrintCurrentStackTrace(stderr);

  } else {
    v8::String::Utf8Value trace(stack);
    fprintf(stderr, "%s\n", *trace);
  }
  fflush(stderr);
}

// Executes a str within the current v8 context.
v8::Handle<v8::Value>
ExecuteString(v8::Handle<v8::String> source,
              v8::Handle<v8::Value> filename) {
  v8::HandleScope scope;
  v8::TryCatch try_catch;

  v8::Handle<v8::Script> script = v8::Script::Compile(source, filename);
  if (script.IsEmpty()) {
    ReportException(&try_catch);
    exit(1);
  }

  v8::Handle<v8::Value> result = script->Run();
  if (result.IsEmpty()) {
    ReportException(&try_catch);
    exit(1);
  }

  return scope.Close(result);
}

static void
ExecuteNativeJS(const char* filename,
                const char* data) {
  v8::HandleScope scope;
  v8::TryCatch try_catch;
  ExecuteString(v8::String::New(data), v8::String::New(filename));
  if (try_catch.HasCaught())  {
    puts("There is an error in Node's built-in javascript");
    puts("This should be reported as a bug!");
    ReportException(&try_catch);
    exit(1);
  }
}

void
UpdateV8Memory() {
    v8::V8::AdjustAmountOfExternalAllocatedMemory(-current_xml_memory);
    current_xml_memory = xmlMemUsed();
    v8::V8::AdjustAmountOfExternalAllocatedMemory(current_xml_memory);
}

v8::Handle<v8::Value>
MemoryUsage(const v8::Arguments& args) {
    v8::HandleScope scope;
    v8::Local<v8::Object> obj = v8::Object::New();
    long c = xmlMemUsed();

    obj->Set(v8::String::New("libxml"), v8::Integer::New(c));
    obj->Set(v8::String::New("v8"), v8::Integer::New(current_xml_memory));

    return scope.Close(obj);
}

void
InitializeLibXMLJS(v8::Handle<v8::Object> target) {
  v8::HandleScope scope;

  XmlSyntaxError::Initialize(target);
  XmlDocument::Initialize(target);
  XmlParser::Initialize(target);
  HtmlParser::Initialize(target);

  target->Set(v8::String::NewSymbol("version"),
              v8::String::New(LIBXMLJS_VERSION));

  target->Set(v8::String::NewSymbol("libxml_version"),
              v8::String::New(LIBXML_DOTTED_VERSION));

  target->Set(v8::String::NewSymbol("libxml_parser_version"),
              v8::String::New(xmlParserVersion));

  target->Set(v8::String::NewSymbol("libxml_debug_enabled"),
              v8::Boolean::New(debugging));

  v8::Local<v8::FunctionTemplate> func = v8::FunctionTemplate::New(MemoryUsage);
  memory_usage = v8::Persistent<v8::FunctionTemplate>::New(func);
  memory_usage->InstanceTemplate()->SetInternalFieldCount(1);

  target->Set(v8::String::NewSymbol("memoryUsage"),
              memory_usage->GetFunction());

  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
  v8::Handle<v8::Context> context = v8::Context::New(NULL, global);

  v8::Context::Scope context_scope(context);
  context->Global()->Set(v8::String::NewSymbol("libxml"), target);

  ExecuteNativeJS("xml_sax_parser.js", native_xml_sax_parser);
  ExecuteNativeJS("xml_document.js", native_xml_document);
  ExecuteNativeJS("xml_element.js", native_xml_element);
}

// used by node.js to initialize libraries
extern "C" void
init(v8::Handle<v8::Object> target) {
  v8::HandleScope scope;
  InitializeLibXMLJS(target);
}

int
main(int argc,
     char* argv[]) {
  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  v8::V8::Initialize();
  v8::V8::SetFatalErrorHandler(OnFatalError);

  // Create a stack-allocated handle scope.
  v8::HandleScope handle_scope;
  // Create a new context.
  v8::Handle<v8::Context> context = v8::Context::New();
  // Enter the created context for compiling and
  // running the hello world script.
  v8::Context::Scope context_scope(context);

  v8::Local<v8::Object> global_obj = v8::Context::GetCurrent()->Global();
  v8::Local<v8::Object> libxml_obj = v8::Object::New();

  InitializeLibXMLJS(libxml_obj);

  global_obj->Set(v8::String::NewSymbol("libxml"), libxml_obj);

  // for (int i = 1; i < argc; i++) {
  //   // Create a string containing the JavaScript source code.
  //   Handle<String> source = ReadFile(argv[i]);
  //   // Compile the source code.
  //   Handle<Script> script = Script::Compile(source);
  //   // Run the script to get the result.
  //   Handle<Value> result = script->Run();
  // }

  v8::V8::Dispose();

  return 0;
}
}  // namespace libxmljs
<|endoftext|>


<commit_before>/// \file CryptKeyEntry.cpp
//-----------------------------------------------------------------------------

#include "stdafx.h"
#include "PasswordSafe.h"
#include "CryptKeyEntry.h"
#include "util.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//-----------------------------------------------------------------------------
CCryptKeyEntry::CCryptKeyEntry(CWnd* pParent)
   : CDialog(CCryptKeyEntry::IDD, pParent)
{
   m_cryptkey1 = "";
   m_cryptkey2 = "";
}

void CCryptKeyEntry::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   DDX_Text(pDX, IDC_CRYPTKEY1, m_cryptkey1.m_mystring);
   DDX_Text(pDX, IDC_CRYPTKEY2, m_cryptkey2.m_mystring);
}

BEGIN_MESSAGE_MAP(CCryptKeyEntry, CDialog)
   ON_BN_CLICKED(ID_HELP, OnHelp)
END_MESSAGE_MAP()

void
CCryptKeyEntry::OnCancel()
{
   app.m_pMainWnd = NULL;
   CDialog::OnCancel();
}

void
CCryptKeyEntry::OnOK()
{
   UpdateData(TRUE);

   if (m_cryptkey1 != m_cryptkey2)
   {
      AfxMessageBox("The two entries do not match.");
      ((CEdit*)GetDlgItem(IDC_CRYPTKEY2))->SetFocus();
      return;
   }
   if (m_cryptkey1 == "")
   {
      AfxMessageBox("Please enter the key and verify it.");
      ((CEdit*)GetDlgItem(IDC_CRYPTKEY1))->SetFocus();
      return;
   }

   app.m_pMainWnd = NULL;
   CDialog::OnOK();
}

void
CCryptKeyEntry::OnHelp()
{
   WinHelp(0x20084, HELP_CONTEXT);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
<commit_msg>ThisMfcApp header, HtmlHelp<commit_after>/// \file CryptKeyEntry.cpp
//-----------------------------------------------------------------------------

#include "stdafx.h"
#include "PasswordSafe.h"

#include "ThisMfcApp.h"
#include "resource.h"
#include "util.h"

#include "CryptKeyEntry.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//-----------------------------------------------------------------------------
CCryptKeyEntry::CCryptKeyEntry(CWnd* pParent)
   : CDialog(CCryptKeyEntry::IDD, pParent)
{
   m_cryptkey1 = "";
   m_cryptkey2 = "";
}

void CCryptKeyEntry::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   DDX_Text(pDX, IDC_CRYPTKEY1, m_cryptkey1.m_mystring);
   DDX_Text(pDX, IDC_CRYPTKEY2, m_cryptkey2.m_mystring);
}

BEGIN_MESSAGE_MAP(CCryptKeyEntry, CDialog)
   ON_BN_CLICKED(ID_HELP, OnHelp)
END_MESSAGE_MAP()

void
CCryptKeyEntry::OnCancel()
{
   app.m_pMainWnd = NULL;
   CDialog::OnCancel();
}

void
CCryptKeyEntry::OnOK()
{
   UpdateData(TRUE);

   if (m_cryptkey1 != m_cryptkey2)
   {
      AfxMessageBox("The two entries do not match.");
      ((CEdit*)GetDlgItem(IDC_CRYPTKEY2))->SetFocus();
      return;
   }
   if (m_cryptkey1 == "")
   {
      AfxMessageBox("Please enter the key and verify it.");
      ((CEdit*)GetDlgItem(IDC_CRYPTKEY1))->SetFocus();
      return;
   }

   app.m_pMainWnd = NULL;
   CDialog::OnOK();
}

void
CCryptKeyEntry::OnHelp()
{
   //WinHelp(0x20084, HELP_CONTEXT);
   ::HtmlHelp(NULL,
              "pwsafe.chm::/html/pws_combo_entry.htm",
              HH_DISPLAY_TOPIC, 0);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
<|endoftext|>


<commit_before>/**
 * @file logging.cpp
 * @brief Logging class
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 *
 * This file is also distributed under the terms of the GNU General
 * Public License, see http://www.gnu.org/copyleft/gpl.txt for details.
 */

#if defined(WINDOWS_PHONE) && !defined(__STDC_LIMIT_MACROS)
#define __STDC_LIMIT_MACROS
#endif

#include "mega/logging.h"

#include <ctime>

#if defined(WINDOWS_PHONE)
#include <stdint.h>
#endif

namespace mega {

Logger *SimpleLogger::logger = nullptr;

// by the default, display logs with level equal or less than logInfo
enum LogLevel SimpleLogger::logCurrentLevel = logInfo;
long long SimpleLogger::maxPayloadLogSize  = 10240;

#ifdef ENABLE_LOG_PERFORMANCE

#ifdef WIN32
thread_local std::array<char, LOGGER_CHUNKS_SIZE> SimpleLogger::mBuffer;
#else
__thread std::array<char, LOGGER_CHUNKS_SIZE> SimpleLogger::mBuffer;
#endif

#else
// static member initialization
std::mutex SimpleLogger::outputs_mutex;
OutputMap SimpleLogger::outputs;

std::string SimpleLogger::getTime()
{
    char ts[50];
    time_t t = std::time(NULL);

    if (!std::strftime(ts, sizeof(ts), "%H:%M:%S", std::gmtime(&t))) {
        ts[0] = '\0';
    }
    return ts;
}

void SimpleLogger::flush()
{
    for (auto& o : outputs)
    {
        OutputStreams::iterator iter;
        OutputStreams vec;

        {
            std::lock_guard<std::mutex> guard(outputs_mutex);
            vec = o;
        }

        for (iter = vec.begin(); iter != vec.end(); iter++)
        {
            std::ostream *os = *iter;
            os->flush();
        }
    }
}

OutputStreams SimpleLogger::getOutput(enum LogLevel ll)
{
    assert(unsigned(ll) < outputs.size());
    std::lock_guard<std::mutex> guard(outputs_mutex);
    return outputs[ll];
}

void SimpleLogger::addOutput(enum LogLevel ll, std::ostream *os)
{
    assert(unsigned(ll) < outputs.size());
    std::lock_guard<std::mutex> guard(outputs_mutex);
    outputs[ll].push_back(os);
}

void SimpleLogger::setAllOutputs(std::ostream *os)
{
    std::lock_guard<std::mutex> guard(outputs_mutex);
    for (auto& o : outputs)
    {
        o.push_back(os);
    }
}
#endif

} // namespace
<commit_msg>use gmtime_r and check return result<commit_after>/**
 * @file logging.cpp
 * @brief Logging class
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 *
 * This file is also distributed under the terms of the GNU General
 * Public License, see http://www.gnu.org/copyleft/gpl.txt for details.
 */

#if defined(WINDOWS_PHONE) && !defined(__STDC_LIMIT_MACROS)
#define __STDC_LIMIT_MACROS
#endif

#include "mega/logging.h"

#include <ctime>

#if defined(WINDOWS_PHONE)
#include <stdint.h>
#endif

namespace mega {

Logger *SimpleLogger::logger = nullptr;

// by the default, display logs with level equal or less than logInfo
enum LogLevel SimpleLogger::logCurrentLevel = logInfo;
long long SimpleLogger::maxPayloadLogSize  = 10240;

#ifdef ENABLE_LOG_PERFORMANCE

#ifdef WIN32
thread_local std::array<char, LOGGER_CHUNKS_SIZE> SimpleLogger::mBuffer;
#else
__thread std::array<char, LOGGER_CHUNKS_SIZE> SimpleLogger::mBuffer;
#endif

#else
// static member initialization
std::mutex SimpleLogger::outputs_mutex;
OutputMap SimpleLogger::outputs;

std::string SimpleLogger::getTime()
{
    char ts[50];
    time_t t = std::time(NULL);
    struct tm tp;

    if (gmtime_r(&t, &tp) && std::strftime(ts, sizeof(ts), "%H:%M:%S", &tp)) return ts;

    return {};
}

void SimpleLogger::flush()
{
    for (auto& o : outputs)
    {
        OutputStreams::iterator iter;
        OutputStreams vec;

        {
            std::lock_guard<std::mutex> guard(outputs_mutex);
            vec = o;
        }

        for (iter = vec.begin(); iter != vec.end(); iter++)
        {
            std::ostream *os = *iter;
            os->flush();
        }
    }
}

OutputStreams SimpleLogger::getOutput(enum LogLevel ll)
{
    assert(unsigned(ll) < outputs.size());
    std::lock_guard<std::mutex> guard(outputs_mutex);
    return outputs[ll];
}

void SimpleLogger::addOutput(enum LogLevel ll, std::ostream *os)
{
    assert(unsigned(ll) < outputs.size());
    std::lock_guard<std::mutex> guard(outputs_mutex);
    outputs[ll].push_back(os);
}

void SimpleLogger::setAllOutputs(std::ostream *os)
{
    std::lock_guard<std::mutex> guard(outputs_mutex);
    for (auto& o : outputs)
    {
        o.push_back(os);
    }
}
#endif

} // namespace
<|endoftext|>


<commit_before>#include <string.h>
#include <types.h>
#include <idt.h>
#include <terminal.h>
#include <log.h>
#include <x86.h>
struct idt_entry idt[256];
struct idt_ptr idtp;

void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
{
    idt[num].base_lo = (base & 0xFFFF);
    idt[num].base_hi = (base >> 16) & 0xFFFF;

    idt[num].sel = sel;
    idt[num].always0 = 0;
    idt[num].flags = flags;
}

int idt_setup()
{
    idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
    idtp.base = (unsigned int)&idt;

    memset(&idt, 0, sizeof(struct idt_entry) * 256);

    idt_load();

	klog(0,"CPU","IDT Setup\n");
    return 0;
}

<commit_msg>Made IDT not output at panic level<commit_after>#include <string.h>
#include <types.h>
#include <idt.h>
#include <terminal.h>
#include <log.h>
#include <x86.h>
struct idt_entry idt[256];
struct idt_ptr idtp;

void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
{
    idt[num].base_lo = (base & 0xFFFF);
    idt[num].base_hi = (base >> 16) & 0xFFFF;

    idt[num].sel = sel;
    idt[num].always0 = 0;
    idt[num].flags = flags;
}

int idt_setup()
{
    idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
    idtp.base = (unsigned int)&idt;

    memset(&idt, 0, sizeof(struct idt_entry) * 256);

    idt_load();

	klog(LOG_DEBUG,"CPU","IDT Setup\n");
    return 0;
}

<|endoftext|>