<commit_before>#include "interpreterCore/managers/saveConvertionManager.h"

using namespace interpreterCore;
using namespace qReal;

QString SaveConvertionManager::editor()
{
	return "RobotsMetamodel";
}

QList<ProjectConverter> SaveConvertionManager::converters()
{
	return { before300Alpha1Converter()
		, from300Alpha4to300Alpha5Converter()
		, from300Beta2to300rc1Converter()
		, from300to301Converter()
		, from301to302Converter()
		, from302to310Converter()
	};
}

ProjectConverter SaveConvertionManager::before300Alpha1Converter()
{
	return ProjectConverter(editor(), Version(), Version::fromString("3.0.0-a1")
			, [=](const GraphicalModelAssistInterface &graphicalApi, LogicalModelAssistInterface &logicalApi)
	{
		Q_UNUSED(graphicalApi)
		Q_UNUSED(logicalApi)
		return ProjectConverter::VersionTooOld;
	});
}

ProjectConverter SaveConvertionManager::from300Alpha4to300Alpha5Converter()
{
	return constructConverter("3.0.0-a4", "3.0.0-a5"
			, {
				replace({
						{"JA1", "A1"}
						, {"JA2", "A2"}
						, {"JA3", "A3"}
						, {"JA4", "A4"}
						, {"JA5", "A5"}
						, {"JA6", "A6"}

						, {"JD1", "D1"}
						, {"JD2", "D2"}

						, {"JF1", "F1"}

						, {"JM1", "M1"}
						, {"JM2", "M2"}
						, {"JM3", "M3"}
						, {"JM4", "M4"}

						, {"JB1", "B1"}
						, {"JB2", "B2"}
						, {"JB3", "B3"}
						, {"JB4", "B4"}

						, {"JE1", "E1"}
						, {"JE2", "E2"}
						, {"JE3", "E3"}
						, {"JE4", "E4"}

						, {"JC1", "C1"}
						, {"JC2", "C2"}
						, {"JC3", "C3"}

						, {"sensor1", "sensorA1"}
						, {"sensor2", "sensorA2"}
						, {"sensor3", "sensorA3"}
						, {"sensor4", "sensorA4"}
						, {"sensor5", "sensorA5"}
						, {"sensor6", "sensorA6"}

						, {"digitSensor1", "sensorD1"}
						, {"digitSensor2", "sensorD2"}
				})
			}
			, [] (const Id &block) { return block.element().startsWith("Trik"); }
			);

}

ProjectConverter SaveConvertionManager::from300Beta2to300rc1Converter()
{
	return constructConverter("3.0.0-b2", "3.0.0-rc1"
			, { quote("TrikSay", "Text"), quote("PrintText", "PrintText") }
			);
}

qReal::ProjectConverter SaveConvertionManager::from300to301Converter()
{
	return constructConverter("3.0.0", "3.0.1"
			, {
				replace({
						{"enterButton", "buttonEnter"}
						, {"escapeButton", "buttonEscape"}
						, {"leftButton", "buttonLeft"}
						, {"rightButton", "buttonRight"}
						, {"backButton", "buttonBack"}
						, {"downButton", "buttonDown"}
						, {"enterButton", "buttonEnter"}
						, {"upButton", "buttonUp"}
						, {"powerButton", "buttonEsc"}
				  })
				, [=] (const Id &block, LogicalModelAssistInterface &logicalApi) {
						if (block.element().startsWith("Trik")) {
							return replace({{"buttonEscape", "buttonEsc"}})(block, logicalApi);
						}

						return false;
					}
				, deleteBlocks({"Ev3WaitForUp"
						, "Ev3WaitForEnter"
						, "Ev3WaitForDown"
						, "Ev3WaitForRight"
						, "Ev3WaitForLeft"
						, "Ev3WaitForBack"

						, "NxtWaitForEnter"
						, "NxtWaitForEscape"
						, "NxtWaitForLeft"
						, "NxtWaitForRight"

						, "TrikWaitForEnter"
						, "TrikWaitForLeft"
						, "TrikWaitForRight"
						, "TrikWaitForDown"
						, "TrikWaitForUp"
						, "TrikWaitForPower"
						})
			}
			);
}

qReal::ProjectConverter SaveConvertionManager::from301to302Converter()
{
	return constructConverter("3.0.1", "3.0.2", { quote("TrikSystem", "Command") } );
}

ProjectConverter SaveConvertionManager::from302to310Converter()
{
	return constructConverter("3.0.2", "3.1.0", { replace( {
				{ "interpreterBase", "kitBase"}
				, { "commonTwoDModel", "twoDModel" }
				, { "nxtKitInterpreter", "nxt" }
				, { "ev3KitInterpreter", "ev3" }
				, { "trikKitInterpreter", "trik" }
				, { "NxtRealRobotModel", "NxtUsbRealRobotModel" }
				, { "nxtKitRobot", "nxtKitUsbRobot" }
				, { "TrikRealRobotModelV6", "TrikRealRobotModel" }
	})});
}

bool SaveConvertionManager::isRobotsDiagram(const Id &diagram)
{
	const QStringList robotsDiagrams = { "RobotsDiagram", "SubprogramDiagram" };
	return diagram.editor() == editor() && robotsDiagrams.contains(diagram.diagram());
}

IdList SaveConvertionManager::elementsOfRobotsDiagrams(const LogicalModelAssistInterface &logicalApi)
{
	IdList result;
	for (const Id &diagramId : logicalApi.children(Id::rootId())) {
		if (isRobotsDiagram(diagramId)) {
			result += diagramId;
			result += logicalApi.children(diagramId);
		}
	}

	return result;
}

qReal::ProjectConverter SaveConvertionManager::constructConverter(const QString &oldVersion
		, const QString &newVersion
		, const QList<std::function<bool(const Id &, LogicalModelAssistInterface &)>> &filters
		, const std::function<bool(const qReal::Id &)> &condition
		)
{
	return ProjectConverter(editor(), Version::fromString(oldVersion), Version::fromString(newVersion)
			, [=](const GraphicalModelAssistInterface &graphicalApi, LogicalModelAssistInterface &logicalApi)
	{
		Q_UNUSED(graphicalApi);

		bool modificationsMade = false;

		for (const Id &graphicalBlock : elementsOfRobotsDiagrams(logicalApi)) {
			const Id block = graphicalApi.logicalId(graphicalBlock);

			if (!condition(block)) {
				continue;
			}

			for (const auto &filter : filters) {
				modificationsMade |= filter(block, logicalApi);
			}
		}

		return modificationsMade ? ProjectConverter::Success : ProjectConverter::NoModificationsMade;
	});
}

std::function<bool(const qReal::Id &, qReal::LogicalModelAssistInterface &)> SaveConvertionManager::replace(
		const QMap<QString, QString> &replacementRules)
{
	return [=] (const Id &block, LogicalModelAssistInterface &logicalApi) {
		bool modificationsMade = false;
		QMapIterator<QString, QVariant> iterator = logicalApi.logicalRepoApi().propertiesIterator(block);
		while (iterator.hasNext()) {
			iterator.next();
			const QString name = iterator.key();
			QString value = iterator.value().toString();
			bool replacementOccured = false;
			for (const QString &toReplace : replacementRules.keys()) {
				if (value.contains(toReplace)) {
					replacementOccured = true;
					modificationsMade = true;

					value.replace(toReplace, replacementRules[toReplace]);
				}
			}

			if (replacementOccured) {
				logicalApi.setPropertyByRoleName(block, value, name);
			}
		}

		 return modificationsMade;
	};
}

std::function<bool(const qReal::Id &, qReal::LogicalModelAssistInterface &)>
		SaveConvertionManager::deleteBlocks(const QStringList &blocks)
{
	return [=] (const Id &block, LogicalModelAssistInterface &logicalApi) {
		if (blocks.contains(block.element())) {
			logicalApi.removeElement(block);
			return true;
		}

		return false;
	};
}

std::function<bool(const qReal::Id &, qReal::LogicalModelAssistInterface &)> SaveConvertionManager::quote(
		const QString &blockType, const QString &property)
{
	return [blockType, property] (const qReal::Id &block, qReal::LogicalModelAssistInterface &logicalApi) {
		if (block.element() == blockType) {
			const QString oldValue = logicalApi.logicalRepoApi().property(block, property).toString();
			if (!oldValue.startsWith("\"")) {
				logicalApi.mutableLogicalRepoApi().setProperty(block, property, "\"" + oldValue + "\"");
				return true;
			}
		}

		return false;
	};
}
<commit_msg>converter for line sensor variables<commit_after>#include "interpreterCore/managers/saveConvertionManager.h"

using namespace interpreterCore;
using namespace qReal;

QString SaveConvertionManager::editor()
{
	return "RobotsMetamodel";
}

QList<ProjectConverter> SaveConvertionManager::converters()
{
	return { before300Alpha1Converter()
		, from300Alpha4to300Alpha5Converter()
		, from300Beta2to300rc1Converter()
		, from300to301Converter()
		, from301to302Converter()
		, from302to310Converter()
	};
}

ProjectConverter SaveConvertionManager::before300Alpha1Converter()
{
	return ProjectConverter(editor(), Version(), Version::fromString("3.0.0-a1")
			, [=](const GraphicalModelAssistInterface &graphicalApi, LogicalModelAssistInterface &logicalApi)
	{
		Q_UNUSED(graphicalApi)
		Q_UNUSED(logicalApi)
		return ProjectConverter::VersionTooOld;
	});
}

ProjectConverter SaveConvertionManager::from300Alpha4to300Alpha5Converter()
{
	return constructConverter("3.0.0-a4", "3.0.0-a5"
			, {
				replace({
						{"JA1", "A1"}
						, {"JA2", "A2"}
						, {"JA3", "A3"}
						, {"JA4", "A4"}
						, {"JA5", "A5"}
						, {"JA6", "A6"}

						, {"JD1", "D1"}
						, {"JD2", "D2"}

						, {"JF1", "F1"}

						, {"JM1", "M1"}
						, {"JM2", "M2"}
						, {"JM3", "M3"}
						, {"JM4", "M4"}

						, {"JB1", "B1"}
						, {"JB2", "B2"}
						, {"JB3", "B3"}
						, {"JB4", "B4"}

						, {"JE1", "E1"}
						, {"JE2", "E2"}
						, {"JE3", "E3"}
						, {"JE4", "E4"}

						, {"JC1", "C1"}
						, {"JC2", "C2"}
						, {"JC3", "C3"}

						, {"sensor1", "sensorA1"}
						, {"sensor2", "sensorA2"}
						, {"sensor3", "sensorA3"}
						, {"sensor4", "sensorA4"}
						, {"sensor5", "sensorA5"}
						, {"sensor6", "sensorA6"}

						, {"digitSensor1", "sensorD1"}
						, {"digitSensor2", "sensorD2"}
				})
			}
			, [] (const Id &block) { return block.element().startsWith("Trik"); }
			);

}

ProjectConverter SaveConvertionManager::from300Beta2to300rc1Converter()
{
	return constructConverter("3.0.0-b2", "3.0.0-rc1"
			, { quote("TrikSay", "Text"), quote("PrintText", "PrintText") }
			);
}

qReal::ProjectConverter SaveConvertionManager::from300to301Converter()
{
	return constructConverter("3.0.0", "3.0.1"
			, {
				replace({
						{"enterButton", "buttonEnter"}
						, {"escapeButton", "buttonEscape"}
						, {"leftButton", "buttonLeft"}
						, {"rightButton", "buttonRight"}
						, {"backButton", "buttonBack"}
						, {"downButton", "buttonDown"}
						, {"enterButton", "buttonEnter"}
						, {"upButton", "buttonUp"}
						, {"powerButton", "buttonEsc"}
				  })
				, [=] (const Id &block, LogicalModelAssistInterface &logicalApi) {
						if (block.element().startsWith("Trik")) {
							return replace({{"buttonEscape", "buttonEsc"}})(block, logicalApi);
						}

						return false;
					}
				, deleteBlocks({"Ev3WaitForUp"
						, "Ev3WaitForEnter"
						, "Ev3WaitForDown"
						, "Ev3WaitForRight"
						, "Ev3WaitForLeft"
						, "Ev3WaitForBack"

						, "NxtWaitForEnter"
						, "NxtWaitForEscape"
						, "NxtWaitForLeft"
						, "NxtWaitForRight"

						, "TrikWaitForEnter"
						, "TrikWaitForLeft"
						, "TrikWaitForRight"
						, "TrikWaitForDown"
						, "TrikWaitForUp"
						, "TrikWaitForPower"
						})
			}
			);
}

qReal::ProjectConverter SaveConvertionManager::from301to302Converter()
{
	return constructConverter("3.0.1", "3.0.2", { quote("TrikSystem", "Command") } );
}

ProjectConverter SaveConvertionManager::from302to310Converter()
{
	return constructConverter("3.0.2", "3.1.0"
			, {
				replace({
						{ "interpreterBase", "kitBase"}
						, { "commonTwoDModel", "twoDModel" }
						, { "nxtKitInterpreter", "nxt" }
						, { "ev3KitInterpreter", "ev3" }
						, { "trikKitInterpreter", "trik" }
						, { "NxtRealRobotModel", "NxtUsbRealRobotModel" }
						, { "nxtKitRobot", "nxtKitUsbRobot" }
						, { "TrikRealRobotModelV6", "TrikRealRobotModel" }
				})
				, replace({
						{ "lineSensorX", "lineSensor[0]"}
						, { "lineSensorSize", "lineSensor[1]" }
						, { "lineSensorCross", "lineSensor[2]" }
				})
			}
	);
}

bool SaveConvertionManager::isRobotsDiagram(const Id &diagram)
{
	const QStringList robotsDiagrams = { "RobotsDiagram", "SubprogramDiagram" };
	return diagram.editor() == editor() && robotsDiagrams.contains(diagram.diagram());
}

IdList SaveConvertionManager::elementsOfRobotsDiagrams(const LogicalModelAssistInterface &logicalApi)
{
	IdList result;
	for (const Id &diagramId : logicalApi.children(Id::rootId())) {
		if (isRobotsDiagram(diagramId)) {
			result += diagramId;
			result += logicalApi.children(diagramId);
		}
	}

	return result;
}

qReal::ProjectConverter SaveConvertionManager::constructConverter(const QString &oldVersion
		, const QString &newVersion
		, const QList<std::function<bool(const Id &, LogicalModelAssistInterface &)>> &filters
		, const std::function<bool(const qReal::Id &)> &condition
		)
{
	return ProjectConverter(editor(), Version::fromString(oldVersion), Version::fromString(newVersion)
			, [=](const GraphicalModelAssistInterface &graphicalApi, LogicalModelAssistInterface &logicalApi)
	{
		Q_UNUSED(graphicalApi);

		bool modificationsMade = false;

		for (const Id &graphicalBlock : elementsOfRobotsDiagrams(logicalApi)) {
			const Id block = graphicalApi.logicalId(graphicalBlock);

			if (!condition(block)) {
				continue;
			}

			for (const auto &filter : filters) {
				modificationsMade |= filter(block, logicalApi);
			}
		}

		return modificationsMade ? ProjectConverter::Success : ProjectConverter::NoModificationsMade;
	});
}

std::function<bool(const qReal::Id &, qReal::LogicalModelAssistInterface &)> SaveConvertionManager::replace(
		const QMap<QString, QString> &replacementRules)
{
	return [=] (const Id &block, LogicalModelAssistInterface &logicalApi) {
		bool modificationsMade = false;
		QMapIterator<QString, QVariant> iterator = logicalApi.logicalRepoApi().propertiesIterator(block);
		while (iterator.hasNext()) {
			iterator.next();
			const QString name = iterator.key();
			QString value = iterator.value().toString();
			bool replacementOccured = false;
			for (const QString &toReplace : replacementRules.keys()) {
				if (value.contains(toReplace)) {
					replacementOccured = true;
					modificationsMade = true;

					value.replace(toReplace, replacementRules[toReplace]);
				}
			}

			if (replacementOccured) {
				logicalApi.setPropertyByRoleName(block, value, name);
			}
		}

		 return modificationsMade;
	};
}

std::function<bool(const qReal::Id &, qReal::LogicalModelAssistInterface &)>
		SaveConvertionManager::deleteBlocks(const QStringList &blocks)
{
	return [=] (const Id &block, LogicalModelAssistInterface &logicalApi) {
		if (blocks.contains(block.element())) {
			logicalApi.removeElement(block);
			return true;
		}

		return false;
	};
}

std::function<bool(const qReal::Id &, qReal::LogicalModelAssistInterface &)> SaveConvertionManager::quote(
		const QString &blockType, const QString &property)
{
	return [blockType, property] (const qReal::Id &block, qReal::LogicalModelAssistInterface &logicalApi) {
		if (block.element() == blockType) {
			const QString oldValue = logicalApi.logicalRepoApi().property(block, property).toString();
			if (!oldValue.startsWith("\"")) {
				logicalApi.mutableLogicalRepoApi().setProperty(block, property, "\"" + oldValue + "\"");
				return true;
			}
		}

		return false;
	};
}
<|endoftext|>


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

#include "chrome/browser/worker_host/message_port_dispatcher.h"

#include "base/callback.h"
#include "base/singleton.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/renderer_host/resource_message_filter.h"
#include "chrome/browser/worker_host/worker_process_host.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/worker_messages.h"

struct MessagePortDispatcher::MessagePort {
  // sender and route_id are what we need to send messages to the port.
  IPC::Message::Sender* sender;
  int route_id;
  // A function pointer to generate a new route id for the sender above.
  // Owned by "sender" above, so don't delete.
  CallbackWithReturnValue<int>::Type* next_routing_id;
  // A globally unique id for this message port.
  int message_port_id;
  // The globally unique id of the entangled message port.
  int entangled_message_port_id;
  // If true, all messages to this message port are queued and not delivered.
  bool queue_messages;
  QueuedMessages queued_messages;
};

MessagePortDispatcher* MessagePortDispatcher::GetInstance() {
  return Singleton<MessagePortDispatcher>::get();
}

MessagePortDispatcher::MessagePortDispatcher()
    : next_message_port_id_(0),
      sender_(NULL),
      next_routing_id_(NULL) {
  // Receive a notification if a message filter or WorkerProcessHost is deleted.
  registrar_.Add(this, NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN,
                 NotificationService::AllSources());

  registrar_.Add(this, NotificationType::WORKER_PROCESS_HOST_SHUTDOWN,
                 NotificationService::AllSources());
}

MessagePortDispatcher::~MessagePortDispatcher() {
}

bool MessagePortDispatcher::OnMessageReceived(
    const IPC::Message& message,
    IPC::Message::Sender* sender,
    CallbackWithReturnValue<int>::Type* next_routing_id,
    bool* message_was_ok) {
  sender_ = sender;
  next_routing_id_ = next_routing_id;

  bool handled = true;
  *message_was_ok = true;

  IPC_BEGIN_MESSAGE_MAP_EX(MessagePortDispatcher, message, *message_was_ok)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_CreateMessagePort, OnCreate)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_DestroyMessagePort, OnDestroy)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_Entangle, OnEntangle)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_PostMessage, OnPostMessage)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_QueueMessages, OnQueueMessages)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_SendQueuedMessages,
                        OnSendQueuedMessages)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP_EX()

  sender_ = NULL;
  next_routing_id_ = NULL;

  return handled;
}

void MessagePortDispatcher::UpdateMessagePort(
    int message_port_id,
    IPC::Message::Sender* sender,
    int routing_id,
    CallbackWithReturnValue<int>::Type* next_routing_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  MessagePort& port = message_ports_[message_port_id];
  port.sender = sender;
  port.route_id = routing_id;
  port.next_routing_id = next_routing_id;
}

bool MessagePortDispatcher::Send(IPC::Message* message) {
  return sender_->Send(message);
}

void MessagePortDispatcher::OnCreate(int *route_id,
                                     int* message_port_id) {
  *message_port_id = ++next_message_port_id_;
  *route_id = next_routing_id_->Run();

  MessagePort port;
  port.sender = sender_;
  port.route_id = *route_id;
  port.next_routing_id = next_routing_id_;
  port.message_port_id = *message_port_id;
  port.entangled_message_port_id = MSG_ROUTING_NONE;
  port.queue_messages = false;
  message_ports_[*message_port_id] = port;
}

void MessagePortDispatcher::OnDestroy(int message_port_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  DCHECK(message_ports_[message_port_id].queued_messages.empty());
  Erase(message_port_id);
}

void MessagePortDispatcher::OnEntangle(int local_message_port_id,
                                       int remote_message_port_id) {
  if (!message_ports_.count(local_message_port_id) ||
      !message_ports_.count(remote_message_port_id)) {
    NOTREACHED();
    return;
  }

  DCHECK(message_ports_[remote_message_port_id].entangled_message_port_id ==
      MSG_ROUTING_NONE);
  message_ports_[remote_message_port_id].entangled_message_port_id =
      local_message_port_id;
}

void MessagePortDispatcher::OnPostMessage(
    int sender_message_port_id,
    const string16& message,
    const std::vector<int>& sent_message_port_ids) {
  if (!message_ports_.count(sender_message_port_id)) {
    NOTREACHED();
    return;
  }

  int entangled_message_port_id =
      message_ports_[sender_message_port_id].entangled_message_port_id;
  if (entangled_message_port_id == MSG_ROUTING_NONE)
    return;  // Process could have crashed.

  if (!message_ports_.count(entangled_message_port_id)) {
    NOTREACHED();
    return;
  }

  PostMessageTo(entangled_message_port_id, message, sent_message_port_ids);
}

void MessagePortDispatcher::PostMessageTo(
    int message_port_id,
    const string16& message,
    const std::vector<int>& sent_message_port_ids) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }
  for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
    if (!message_ports_.count(sent_message_port_ids[i])) {
      NOTREACHED();
      return;
    }
  }

  MessagePort& entangled_port = message_ports_[message_port_id];

  std::vector<MessagePort*> sent_ports(sent_message_port_ids.size());
  for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
    sent_ports[i] = &message_ports_[sent_message_port_ids[i]];
    sent_ports[i]->queue_messages = true;
  }

  if (entangled_port.queue_messages) {
    entangled_port.queued_messages.push_back(
        std::make_pair(message, sent_message_port_ids));
  } else {
    // If a message port was sent around, the new location will need a routing
    // id.  Instead of having the created port send us a sync message to get it,
    // send along with the message.
    std::vector<int> new_routing_ids(sent_message_port_ids.size());
    for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
      new_routing_ids[i] = entangled_port.next_routing_id->Run();
      sent_ports[i]->sender = entangled_port.sender;

      // Update the entry for the sent port as it can be in a different process.
      sent_ports[i]->route_id = new_routing_ids[i];
    }

    // Now send the message to the entangled port.
    IPC::Message* ipc_msg = new WorkerProcessMsg_Message(
        entangled_port.route_id, message, sent_message_port_ids,
        new_routing_ids);
    entangled_port.sender->Send(ipc_msg);
  }
}

void MessagePortDispatcher::OnQueueMessages(int message_port_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  MessagePort& port = message_ports_[message_port_id];
  port.sender->Send(new WorkerProcessMsg_MessagesQueued(port.route_id));
  port.queue_messages = true;
  port.sender = NULL;
}

void MessagePortDispatcher::OnSendQueuedMessages(
    int message_port_id,
    const QueuedMessages& queued_messages) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  // Send the queued messages to the port again.  This time they'll reach the
  // new location.
  MessagePort& port = message_ports_[message_port_id];
  port.queue_messages = false;
  port.queued_messages.insert(port.queued_messages.begin(),
                              queued_messages.begin(),
                              queued_messages.end());
  SendQueuedMessagesIfPossible(message_port_id);
}

void MessagePortDispatcher::SendQueuedMessagesIfPossible(int message_port_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  MessagePort& port = message_ports_[message_port_id];
  if (port.queue_messages || !port.sender)
    return;

  for (QueuedMessages::iterator iter = port.queued_messages.begin();
       iter != port.queued_messages.end(); ++iter) {
    PostMessageTo(message_port_id, iter->first, iter->second);
  }
  port.queued_messages.clear();
}

void MessagePortDispatcher::Observe(NotificationType type,
                                    const NotificationSource& source,
                                    const NotificationDetails& details) {
  IPC::Message::Sender* sender = NULL;
  if (type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN) {
    sender = Source<ResourceMessageFilter>(source).ptr();
  } else if (type.value == NotificationType::WORKER_PROCESS_HOST_SHUTDOWN) {
    sender = Source<WorkerProcessHost>(source).ptr();
  } else {
    NOTREACHED();
  }

  // Check if the (possibly) crashed process had any message ports.
  for (MessagePorts::iterator iter = message_ports_.begin();
       iter != message_ports_.end();) {
    MessagePorts::iterator cur_item = iter++;
    if (cur_item->second.sender == sender) {
      Erase(cur_item->first);
    }
  }
}

void MessagePortDispatcher::Erase(int message_port_id) {
  MessagePorts::iterator erase_item = message_ports_.find(message_port_id);
  DCHECK(erase_item != message_ports_.end());

  int entangled_id = erase_item->second.entangled_message_port_id;
  if (entangled_id != MSG_ROUTING_NONE) {
    // Do the disentanglement (and be paranoid about the other side existing
    // just in case something unusual happened during entanglement).
    if (message_ports_.count(entangled_id)) {
      message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE;
    }
  }
  message_ports_.erase(erase_item);
}
<commit_msg>Fix crash in web workers when entangled port sender is null.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/worker_host/message_port_dispatcher.h"

#include "base/callback.h"
#include "base/singleton.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/renderer_host/resource_message_filter.h"
#include "chrome/browser/worker_host/worker_process_host.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/worker_messages.h"

struct MessagePortDispatcher::MessagePort {
  // sender and route_id are what we need to send messages to the port.
  IPC::Message::Sender* sender;
  int route_id;
  // A function pointer to generate a new route id for the sender above.
  // Owned by "sender" above, so don't delete.
  CallbackWithReturnValue<int>::Type* next_routing_id;
  // A globally unique id for this message port.
  int message_port_id;
  // The globally unique id of the entangled message port.
  int entangled_message_port_id;
  // If true, all messages to this message port are queued and not delivered.
  bool queue_messages;
  QueuedMessages queued_messages;
};

MessagePortDispatcher* MessagePortDispatcher::GetInstance() {
  return Singleton<MessagePortDispatcher>::get();
}

MessagePortDispatcher::MessagePortDispatcher()
    : next_message_port_id_(0),
      sender_(NULL),
      next_routing_id_(NULL) {
  // Receive a notification if a message filter or WorkerProcessHost is deleted.
  registrar_.Add(this, NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN,
                 NotificationService::AllSources());

  registrar_.Add(this, NotificationType::WORKER_PROCESS_HOST_SHUTDOWN,
                 NotificationService::AllSources());
}

MessagePortDispatcher::~MessagePortDispatcher() {
}

bool MessagePortDispatcher::OnMessageReceived(
    const IPC::Message& message,
    IPC::Message::Sender* sender,
    CallbackWithReturnValue<int>::Type* next_routing_id,
    bool* message_was_ok) {
  sender_ = sender;
  next_routing_id_ = next_routing_id;

  bool handled = true;
  *message_was_ok = true;

  IPC_BEGIN_MESSAGE_MAP_EX(MessagePortDispatcher, message, *message_was_ok)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_CreateMessagePort, OnCreate)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_DestroyMessagePort, OnDestroy)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_Entangle, OnEntangle)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_PostMessage, OnPostMessage)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_QueueMessages, OnQueueMessages)
    IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_SendQueuedMessages,
                        OnSendQueuedMessages)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP_EX()

  sender_ = NULL;
  next_routing_id_ = NULL;

  return handled;
}

void MessagePortDispatcher::UpdateMessagePort(
    int message_port_id,
    IPC::Message::Sender* sender,
    int routing_id,
    CallbackWithReturnValue<int>::Type* next_routing_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  MessagePort& port = message_ports_[message_port_id];
  port.sender = sender;
  port.route_id = routing_id;
  port.next_routing_id = next_routing_id;
}

bool MessagePortDispatcher::Send(IPC::Message* message) {
  return sender_->Send(message);
}

void MessagePortDispatcher::OnCreate(int *route_id,
                                     int* message_port_id) {
  *message_port_id = ++next_message_port_id_;
  *route_id = next_routing_id_->Run();

  MessagePort port;
  port.sender = sender_;
  port.route_id = *route_id;
  port.next_routing_id = next_routing_id_;
  port.message_port_id = *message_port_id;
  port.entangled_message_port_id = MSG_ROUTING_NONE;
  port.queue_messages = false;
  message_ports_[*message_port_id] = port;
}

void MessagePortDispatcher::OnDestroy(int message_port_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  DCHECK(message_ports_[message_port_id].queued_messages.empty());
  Erase(message_port_id);
}

void MessagePortDispatcher::OnEntangle(int local_message_port_id,
                                       int remote_message_port_id) {
  if (!message_ports_.count(local_message_port_id) ||
      !message_ports_.count(remote_message_port_id)) {
    NOTREACHED();
    return;
  }

  DCHECK(message_ports_[remote_message_port_id].entangled_message_port_id ==
      MSG_ROUTING_NONE);
  message_ports_[remote_message_port_id].entangled_message_port_id =
      local_message_port_id;
}

void MessagePortDispatcher::OnPostMessage(
    int sender_message_port_id,
    const string16& message,
    const std::vector<int>& sent_message_port_ids) {
  if (!message_ports_.count(sender_message_port_id)) {
    NOTREACHED();
    return;
  }

  int entangled_message_port_id =
      message_ports_[sender_message_port_id].entangled_message_port_id;
  if (entangled_message_port_id == MSG_ROUTING_NONE)
    return;  // Process could have crashed.

  if (!message_ports_.count(entangled_message_port_id)) {
    NOTREACHED();
    return;
  }

  PostMessageTo(entangled_message_port_id, message, sent_message_port_ids);
}

void MessagePortDispatcher::PostMessageTo(
    int message_port_id,
    const string16& message,
    const std::vector<int>& sent_message_port_ids) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }
  for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
    if (!message_ports_.count(sent_message_port_ids[i])) {
      NOTREACHED();
      return;
    }
  }

  MessagePort& entangled_port = message_ports_[message_port_id];

  std::vector<MessagePort*> sent_ports(sent_message_port_ids.size());
  for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
    sent_ports[i] = &message_ports_[sent_message_port_ids[i]];
    sent_ports[i]->queue_messages = true;
  }

  if (entangled_port.queue_messages) {
    entangled_port.queued_messages.push_back(
        std::make_pair(message, sent_message_port_ids));
  } else {
    // If a message port was sent around, the new location will need a routing
    // id.  Instead of having the created port send us a sync message to get it,
    // send along with the message.
    std::vector<int> new_routing_ids(sent_message_port_ids.size());
    for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
      new_routing_ids[i] = entangled_port.next_routing_id->Run();
      sent_ports[i]->sender = entangled_port.sender;

      // Update the entry for the sent port as it can be in a different process.
      sent_ports[i]->route_id = new_routing_ids[i];
    }

    if (entangled_port.sender) {
      // Now send the message to the entangled port.
      IPC::Message* ipc_msg = new WorkerProcessMsg_Message(
          entangled_port.route_id, message, sent_message_port_ids,
          new_routing_ids);
      entangled_port.sender->Send(ipc_msg);
    }
  }
}

void MessagePortDispatcher::OnQueueMessages(int message_port_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  MessagePort& port = message_ports_[message_port_id];
  if (port.sender) {
    port.sender->Send(new WorkerProcessMsg_MessagesQueued(port.route_id));
    port.queue_messages = true;
    port.sender = NULL;
  }
}

void MessagePortDispatcher::OnSendQueuedMessages(
    int message_port_id,
    const QueuedMessages& queued_messages) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  // Send the queued messages to the port again.  This time they'll reach the
  // new location.
  MessagePort& port = message_ports_[message_port_id];
  port.queue_messages = false;
  port.queued_messages.insert(port.queued_messages.begin(),
                              queued_messages.begin(),
                              queued_messages.end());
  SendQueuedMessagesIfPossible(message_port_id);
}

void MessagePortDispatcher::SendQueuedMessagesIfPossible(int message_port_id) {
  if (!message_ports_.count(message_port_id)) {
    NOTREACHED();
    return;
  }

  MessagePort& port = message_ports_[message_port_id];
  if (port.queue_messages || !port.sender)
    return;

  for (QueuedMessages::iterator iter = port.queued_messages.begin();
       iter != port.queued_messages.end(); ++iter) {
    PostMessageTo(message_port_id, iter->first, iter->second);
  }
  port.queued_messages.clear();
}

void MessagePortDispatcher::Observe(NotificationType type,
                                    const NotificationSource& source,
                                    const NotificationDetails& details) {
  IPC::Message::Sender* sender = NULL;
  if (type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN) {
    sender = Source<ResourceMessageFilter>(source).ptr();
  } else if (type.value == NotificationType::WORKER_PROCESS_HOST_SHUTDOWN) {
    sender = Source<WorkerProcessHost>(source).ptr();
  } else {
    NOTREACHED();
  }

  // Check if the (possibly) crashed process had any message ports.
  for (MessagePorts::iterator iter = message_ports_.begin();
       iter != message_ports_.end();) {
    MessagePorts::iterator cur_item = iter++;
    if (cur_item->second.sender == sender) {
      Erase(cur_item->first);
    }
  }
}

void MessagePortDispatcher::Erase(int message_port_id) {
  MessagePorts::iterator erase_item = message_ports_.find(message_port_id);
  DCHECK(erase_item != message_ports_.end());

  int entangled_id = erase_item->second.entangled_message_port_id;
  if (entangled_id != MSG_ROUTING_NONE) {
    // Do the disentanglement (and be paranoid about the other side existing
    // just in case something unusual happened during entanglement).
    if (message_ports_.count(entangled_id)) {
      message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE;
    }
  }
  message_ports_.erase(erase_item);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <string>
// #include <cctype>
#include <locale>
#include <vector>
#include <algorithm>
#include <boost/lexical_cast.hpp>
// #include <boost/algorithm/string/classification.hpp>
// #include <locale>  //not being used currently - will be later

using boost::lexical_cast;
using namespace std;
using namespace boost;

const unsigned long int GiB = 1073741824;
const unsigned long int MiB = 1048576;
const unsigned long int KiB = 1024;

int main(int ac, char* av[]) {
		locale loc;

        if (ac > 1) {
                std::vector<std::string> args(av, av+ac);
                int i;
                for (i = 1; i < ac; i++) {
                 	args[i].erase(std::remove_if(args[i].begin(), args[i].end(), !is_digit()), args[i].end());
                        double r = lexical_cast<double>(args[i]) / (double)GiB;
                        std::cout << i << ": " << setiosflags(ios::fixed) << setprecision(2) << r << "GiB" << std::endl;
                } //for
        } //if
        else
                std::cout << "Usage: " << av[0] << " <NUMBER..>" << std::endl;

} //main
<commit_msg>removed possibly unused locale.<commit_after>#include <iostream>
#include <iomanip>
#include <string>
// #include <cctype>
#include <locale>
#include <vector>
#include <algorithm>
#include <boost/lexical_cast.hpp>
// #include <boost/algorithm/string/classification.hpp>
// #include <locale>  //not being used currently - will be later

using boost::lexical_cast;
using namespace std;
using namespace boost;

const unsigned long int GiB = 1073741824;
const unsigned long int MiB = 1048576;
const unsigned long int KiB = 1024;

int main(int ac, char* av[]) {
	//	locale loc;

        if (ac > 1) {
                std::vector<std::string> args(av, av+ac);
                int i;
                for (i = 1; i < ac; i++) {
                 	args[i].erase(std::remove_if(args[i].begin(), args[i].end(), !is_digit()), args[i].end());
                        double r = lexical_cast<double>(args[i]) / (double)GiB;
                        std::cout << i << ": " << setiosflags(ios::fixed) << setprecision(2) << r << "GiB" << std::endl;
                } //for
        } //if
        else
                std::cout << "Usage: " << av[0] << " <NUMBER..>" << std::endl;

} //main
<|endoftext|>


<commit_before>//===-- asan_dll_thunk.cc -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// This file defines a family of thunks that should be statically linked into
// the DLLs that have ASan instrumentation in order to delegate the calls to the
// shared runtime that lives in the main binary.
// See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the
// details.
//===----------------------------------------------------------------------===//

// Only compile this code when buidling asan_dll_thunk.lib
// Using #ifdef rather than relying on Makefiles etc.
// simplifies the build procedure.
#ifdef ASAN_DLL_THUNK

// ----------------- Helper functions and macros --------------------- {{{1
extern "C" {
void *__stdcall GetModuleHandleA(const char *module_name);
void *__stdcall GetProcAddress(void *module, const char *proc_name);
void abort();
}

static void *getRealProcAddressOrDie(const char *name) {
  void *ret = GetProcAddress(GetModuleHandleA(0), name);
  if (!ret)
    abort();
  return ret;
}

#define WRAP_V_V(name)                                                         \
  extern "C" void name() {                                                     \
    typedef void (*fntype)();                                                  \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn();                                                                      \
  }

#define WRAP_V_W(name)                                                         \
  extern "C" void name(void *arg) {                                            \
    typedef void (*fntype)(void *arg);                                         \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn(arg);                                                                   \
  }

#define WRAP_V_WW(name)                                                        \
  extern "C" void name(void *arg1, void *arg2) {                               \
    typedef void (*fntype)(void *, void *);                                    \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn(arg1, arg2);                                                            \
  }

#define WRAP_V_WWW(name)                                                       \
  extern "C" void name(void *arg1, void *arg2, void *arg3) {                   \
    typedef void *(*fntype)(void *, void *, void *);                           \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn(arg1, arg2, arg3);                                                      \
  }

#define WRAP_W_V(name)                                                         \
  extern "C" void *name() {                                                    \
    typedef void *(*fntype)();                                                 \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn();                                                               \
  }

#define WRAP_W_W(name)                                                         \
  extern "C" void *name(void *arg) {                                           \
    typedef void *(*fntype)(void *arg);                                        \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg);                                                            \
  }

#define WRAP_W_WW(name)                                                        \
  extern "C" void *name(void *arg1, void *arg2) {                              \
    typedef void *(*fntype)(void *, void *);                                   \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2);                                                     \
  }

#define WRAP_W_WWW(name)                                                       \
  extern "C" void *name(void *arg1, void *arg2, void *arg3) {                  \
    typedef void *(*fntype)(void *, void *, void *);                           \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3);                                               \
  }

#define WRAP_W_WWWW(name)                                                      \
  extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) {      \
    typedef void *(*fntype)(void *, void *, void *, void *);                   \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3, arg4);                                         \
  }

#define WRAP_W_WWWWW(name)                                                     \
  extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
                        void *arg5) {                                          \
    typedef void *(*fntype)(void *, void *, void *, void *, void *);           \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3, arg4, arg5);                                   \
  }

#define WRAP_W_WWWWWW(name)                                                    \
  extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
                        void *arg5, void *arg6) {                              \
    typedef void *(*fntype)(void *, void *, void *, void *, void *, void *);   \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3, arg4, arg5, arg6);                             \
  }
// }}}

// ----------------- ASan own interface functions --------------------
WRAP_W_V(__asan_should_detect_stack_use_after_return)

extern "C" {
  int __asan_option_detect_stack_use_after_return;

  // Manually wrap __asan_init as we need to initialize
  // __asan_option_detect_stack_use_after_return afterwards.
  void __asan_init_v3() {
    typedef void (*fntype)();
    static fntype fn = (fntype)getRealProcAddressOrDie("__asan_init_v3");
    fn();
    __asan_option_detect_stack_use_after_return =
        (__asan_should_detect_stack_use_after_return() != 0);
  }
}

WRAP_V_V(__asan_handle_no_return)

WRAP_V_W(__asan_report_store1)
WRAP_V_W(__asan_report_store2)
WRAP_V_W(__asan_report_store4)
WRAP_V_W(__asan_report_store8)
WRAP_V_W(__asan_report_store16)
WRAP_V_WW(__asan_report_store_n)

WRAP_V_W(__asan_report_load1)
WRAP_V_W(__asan_report_load2)
WRAP_V_W(__asan_report_load4)
WRAP_V_W(__asan_report_load8)
WRAP_V_W(__asan_report_load16)
WRAP_V_WW(__asan_report_load_n)

WRAP_W_WWW(__asan_memcpy);
WRAP_W_WWW(__asan_memset);
WRAP_W_WWW(__asan_memmove);

WRAP_V_WW(__asan_register_globals)
WRAP_V_WW(__asan_unregister_globals)

WRAP_V_W(__asan_before_dynamic_init)
WRAP_V_V(__asan_after_dynamic_init)

WRAP_V_WW(__asan_poison_stack_memory)
WRAP_V_WW(__asan_unpoison_stack_memory)

WRAP_V_WW(__asan_poison_memory_region)
WRAP_V_WW(__asan_unpoison_memory_region)

WRAP_W_WW(__asan_stack_malloc_0)
WRAP_W_WW(__asan_stack_malloc_1)
WRAP_W_WW(__asan_stack_malloc_2)
WRAP_W_WW(__asan_stack_malloc_3)
WRAP_W_WW(__asan_stack_malloc_4)
WRAP_W_WW(__asan_stack_malloc_5)
WRAP_W_WW(__asan_stack_malloc_6)
WRAP_W_WW(__asan_stack_malloc_7)
WRAP_W_WW(__asan_stack_malloc_8)
WRAP_W_WW(__asan_stack_malloc_9)
WRAP_W_WW(__asan_stack_malloc_10)

WRAP_V_WWW(__asan_stack_free_0)
WRAP_V_WWW(__asan_stack_free_1)
WRAP_V_WWW(__asan_stack_free_2)
WRAP_V_WWW(__asan_stack_free_4)
WRAP_V_WWW(__asan_stack_free_5)
WRAP_V_WWW(__asan_stack_free_6)
WRAP_V_WWW(__asan_stack_free_7)
WRAP_V_WWW(__asan_stack_free_8)
WRAP_V_WWW(__asan_stack_free_9)
WRAP_V_WWW(__asan_stack_free_10)

// TODO(timurrrr): Add more interface functions on the as-needed basis.

// ----------------- Memory allocation functions ---------------------
WRAP_V_W(free)
WRAP_V_WW(_free_dbg)

WRAP_W_W(malloc)
WRAP_W_WWWW(_malloc_dbg)

WRAP_W_WW(calloc)
WRAP_W_WWWWW(_calloc_dbg)
WRAP_W_WWW(_calloc_impl)

WRAP_W_WW(realloc)
WRAP_W_WWW(_realloc_dbg)
WRAP_W_WWW(_recalloc)

WRAP_W_W(_msize)
WRAP_W_W(_expand)
WRAP_W_W(_expand_dbg)

// TODO(timurrrr): Might want to add support for _aligned_* allocation
// functions to detect a bit more bugs.  Those functions seem to wrap malloc().

// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).

#endif // ASAN_DLL_THUNK
<commit_msg>[ASan/Win] Add DLL thunks for the fake stack interface<commit_after>//===-- asan_dll_thunk.cc -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// This file defines a family of thunks that should be statically linked into
// the DLLs that have ASan instrumentation in order to delegate the calls to the
// shared runtime that lives in the main binary.
// See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the
// details.
//===----------------------------------------------------------------------===//

// Only compile this code when buidling asan_dll_thunk.lib
// Using #ifdef rather than relying on Makefiles etc.
// simplifies the build procedure.
#ifdef ASAN_DLL_THUNK

// ----------------- Helper functions and macros --------------------- {{{1
extern "C" {
void *__stdcall GetModuleHandleA(const char *module_name);
void *__stdcall GetProcAddress(void *module, const char *proc_name);
void abort();
}

static void *getRealProcAddressOrDie(const char *name) {
  void *ret = GetProcAddress(GetModuleHandleA(0), name);
  if (!ret)
    abort();
  return ret;
}

#define WRAP_V_V(name)                                                         \
  extern "C" void name() {                                                     \
    typedef void (*fntype)();                                                  \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn();                                                                      \
  }

#define WRAP_V_W(name)                                                         \
  extern "C" void name(void *arg) {                                            \
    typedef void (*fntype)(void *arg);                                         \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn(arg);                                                                   \
  }

#define WRAP_V_WW(name)                                                        \
  extern "C" void name(void *arg1, void *arg2) {                               \
    typedef void (*fntype)(void *, void *);                                    \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn(arg1, arg2);                                                            \
  }

#define WRAP_V_WWW(name)                                                       \
  extern "C" void name(void *arg1, void *arg2, void *arg3) {                   \
    typedef void *(*fntype)(void *, void *, void *);                           \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    fn(arg1, arg2, arg3);                                                      \
  }

#define WRAP_W_V(name)                                                         \
  extern "C" void *name() {                                                    \
    typedef void *(*fntype)();                                                 \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn();                                                               \
  }

#define WRAP_W_W(name)                                                         \
  extern "C" void *name(void *arg) {                                           \
    typedef void *(*fntype)(void *arg);                                        \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg);                                                            \
  }

#define WRAP_W_WW(name)                                                        \
  extern "C" void *name(void *arg1, void *arg2) {                              \
    typedef void *(*fntype)(void *, void *);                                   \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2);                                                     \
  }

#define WRAP_W_WWW(name)                                                       \
  extern "C" void *name(void *arg1, void *arg2, void *arg3) {                  \
    typedef void *(*fntype)(void *, void *, void *);                           \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3);                                               \
  }

#define WRAP_W_WWWW(name)                                                      \
  extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) {      \
    typedef void *(*fntype)(void *, void *, void *, void *);                   \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3, arg4);                                         \
  }

#define WRAP_W_WWWWW(name)                                                     \
  extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
                        void *arg5) {                                          \
    typedef void *(*fntype)(void *, void *, void *, void *, void *);           \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3, arg4, arg5);                                   \
  }

#define WRAP_W_WWWWWW(name)                                                    \
  extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
                        void *arg5, void *arg6) {                              \
    typedef void *(*fntype)(void *, void *, void *, void *, void *, void *);   \
    static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
    return fn(arg1, arg2, arg3, arg4, arg5, arg6);                             \
  }
// }}}

// ----------------- ASan own interface functions --------------------
WRAP_W_V(__asan_should_detect_stack_use_after_return)

extern "C" {
  int __asan_option_detect_stack_use_after_return;

  // Manually wrap __asan_init as we need to initialize
  // __asan_option_detect_stack_use_after_return afterwards.
  void __asan_init_v3() {
    typedef void (*fntype)();
    static fntype fn = (fntype)getRealProcAddressOrDie("__asan_init_v3");
    fn();
    __asan_option_detect_stack_use_after_return =
        (__asan_should_detect_stack_use_after_return() != 0);
  }
}

WRAP_V_V(__asan_handle_no_return)

WRAP_V_W(__asan_report_store1)
WRAP_V_W(__asan_report_store2)
WRAP_V_W(__asan_report_store4)
WRAP_V_W(__asan_report_store8)
WRAP_V_W(__asan_report_store16)
WRAP_V_WW(__asan_report_store_n)

WRAP_V_W(__asan_report_load1)
WRAP_V_W(__asan_report_load2)
WRAP_V_W(__asan_report_load4)
WRAP_V_W(__asan_report_load8)
WRAP_V_W(__asan_report_load16)
WRAP_V_WW(__asan_report_load_n)

WRAP_W_WWW(__asan_memcpy);
WRAP_W_WWW(__asan_memset);
WRAP_W_WWW(__asan_memmove);

WRAP_V_WW(__asan_register_globals)
WRAP_V_WW(__asan_unregister_globals)

WRAP_V_W(__asan_before_dynamic_init)
WRAP_V_V(__asan_after_dynamic_init)

WRAP_V_WW(__asan_poison_stack_memory)
WRAP_V_WW(__asan_unpoison_stack_memory)

WRAP_V_WW(__asan_poison_memory_region)
WRAP_V_WW(__asan_unpoison_memory_region)

WRAP_W_V(__asan_get_current_fake_stack)
WRAP_W_WWWW(__asan_addr_is_in_fake_stack)

WRAP_W_WW(__asan_stack_malloc_0)
WRAP_W_WW(__asan_stack_malloc_1)
WRAP_W_WW(__asan_stack_malloc_2)
WRAP_W_WW(__asan_stack_malloc_3)
WRAP_W_WW(__asan_stack_malloc_4)
WRAP_W_WW(__asan_stack_malloc_5)
WRAP_W_WW(__asan_stack_malloc_6)
WRAP_W_WW(__asan_stack_malloc_7)
WRAP_W_WW(__asan_stack_malloc_8)
WRAP_W_WW(__asan_stack_malloc_9)
WRAP_W_WW(__asan_stack_malloc_10)

WRAP_V_WWW(__asan_stack_free_0)
WRAP_V_WWW(__asan_stack_free_1)
WRAP_V_WWW(__asan_stack_free_2)
WRAP_V_WWW(__asan_stack_free_4)
WRAP_V_WWW(__asan_stack_free_5)
WRAP_V_WWW(__asan_stack_free_6)
WRAP_V_WWW(__asan_stack_free_7)
WRAP_V_WWW(__asan_stack_free_8)
WRAP_V_WWW(__asan_stack_free_9)
WRAP_V_WWW(__asan_stack_free_10)

// TODO(timurrrr): Add more interface functions on the as-needed basis.

// ----------------- Memory allocation functions ---------------------
WRAP_V_W(free)
WRAP_V_WW(_free_dbg)

WRAP_W_W(malloc)
WRAP_W_WWWW(_malloc_dbg)

WRAP_W_WW(calloc)
WRAP_W_WWWWW(_calloc_dbg)
WRAP_W_WWW(_calloc_impl)

WRAP_W_WW(realloc)
WRAP_W_WWW(_realloc_dbg)
WRAP_W_WWW(_recalloc)

WRAP_W_W(_msize)
WRAP_W_W(_expand)
WRAP_W_W(_expand_dbg)

// TODO(timurrrr): Might want to add support for _aligned_* allocation
// functions to detect a bit more bugs.  Those functions seem to wrap malloc().

// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).

#endif // ASAN_DLL_THUNK
<|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 "views/controls/native/native_view_host_gtk.h"

#include <gtk/gtk.h>
#include <algorithm>

#include "base/logging.h"
#include "views/controls/native/native_view_host.h"
#include "views/focus/focus_manager.h"
#include "views/widget/widget_gtk.h"

namespace views {

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostGtk, public:

NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host)
    : host_(host),
      installed_clip_(false),
      destroy_signal_id_(0),
      focus_signal_id_(0),
      fixed_(NULL) {
  CreateFixed(false);
}

NativeViewHostGtk::~NativeViewHostGtk() {
  if (fixed_)
    gtk_widget_destroy(fixed_);
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostGtk, NativeViewHostWrapper implementation:

void NativeViewHostGtk::NativeViewAttached() {
  DCHECK(host_->native_view());
  if (gtk_widget_get_parent(host_->native_view()))
    gtk_widget_reparent(host_->native_view(), fixed_);
  else
    gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());

  if (!destroy_signal_id_) {
    destroy_signal_id_ = g_signal_connect(G_OBJECT(host_->native_view()),
                                          "destroy", G_CALLBACK(CallDestroy),
                                          this);
  }

  if (!focus_signal_id_) {
    focus_signal_id_ = g_signal_connect(G_OBJECT(host_->native_view()),
                                        "focus-in-event",
                                        G_CALLBACK(CallFocusIn), this);
  }

  // Always layout though.
  host_->Layout();

  // We own the native view as long as it's attached, so that we can safely
  // reparent it in multiple passes.
  gtk_widget_ref(host_->native_view());

  // TODO(port): figure out focus.
}

void NativeViewHostGtk::NativeViewDetaching(bool destroyed) {
  DCHECK(host_->native_view());

  g_signal_handler_disconnect(G_OBJECT(host_->native_view()),
                              destroy_signal_id_);
  destroy_signal_id_ = 0;

  g_signal_handler_disconnect(G_OBJECT(host_->native_view()),
                              focus_signal_id_);
  focus_signal_id_ = 0;

  installed_clip_ = false;

  if (fixed_ && !destroyed) {
    DCHECK_NE(static_cast<gfx::NativeView>(NULL),
              gtk_widget_get_parent(host_->native_view()));
    gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view());
    DCHECK_EQ(
        0U, g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
  }

  g_object_unref(G_OBJECT(host_->native_view()));
}

void NativeViewHostGtk::AddedToWidget() {
  if (!fixed_)
    CreateFixed(false);
  if (gtk_widget_get_parent(fixed_))
    GetHostWidget()->ReparentChild(fixed_);
  else
    GetHostWidget()->AddChild(fixed_);

  if (!host_->native_view())
    return;

  if (gtk_widget_get_parent(host_->native_view()))
    gtk_widget_reparent(host_->native_view(), fixed_);
  else
    gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());

  if (host_->IsVisibleInRootView())
    gtk_widget_show(fixed_);
  else
    gtk_widget_hide(fixed_);
  host_->Layout();
}

void NativeViewHostGtk::RemovedFromWidget() {
  if (!host_->native_view())
    return;

  DestroyFixed();
}

void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) {
  DCHECK(w > 0 && h > 0);
  installed_clip_bounds_.SetRect(x, y, w, h);
  installed_clip_ = true;

  // We only re-create the fixed with a window when a cliprect is installed.
  // Because the presence of a X Window will prevent transparency from working
  // properly, we only want it to be active for the duration of a clip
  // (typically during animations and scrolling.)
  CreateFixed(true);
}

bool NativeViewHostGtk::HasInstalledClip() {
  return installed_clip_;
}

void NativeViewHostGtk::UninstallClip() {
  installed_clip_ = false;
  // We now re-create the fixed without a X Window so transparency works again.
  CreateFixed(false);
}

void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) {
  // x and y are the desired position of host_ in WidgetGtk coordiantes.
  int fixed_x = x;
  int fixed_y = y;
  int fixed_w = w;
  int fixed_h = h;
  int child_x = 0;
  int child_y = 0;
  int child_w = w;
  int child_h = h;
  if (installed_clip_) {
    child_x = -installed_clip_bounds_.x();
    child_y = -installed_clip_bounds_.y();
    fixed_x += -child_x;
    fixed_y += -child_y;
    fixed_w = std::min(installed_clip_bounds_.width(), w);
    fixed_h = std::min(installed_clip_bounds_.height(), h);
  }

  // Size and place the fixed_.
  GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h);

  // Size and place the hosted NativeView.
  gtk_widget_set_size_request(host_->native_view(), child_w, child_h);
  gtk_fixed_move(GTK_FIXED(fixed_), host_->native_view(), child_x, child_y);

  gtk_widget_show(fixed_);
  gtk_widget_show(host_->native_view());
}

void NativeViewHostGtk::HideWidget() {
  gtk_widget_hide(fixed_);
}

void NativeViewHostGtk::SetFocus() {
  DCHECK(host_->native_view());
  gtk_widget_grab_focus(host_->native_view());
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostGtk, private:

void NativeViewHostGtk::CreateFixed(bool needs_window) {
  GtkWidget* focused_widget = GetFocusedDescendant();
  bool fixed_is_focused = (focused_widget == fixed_);

  if (focused_widget) {
    // A descendant of our fixed has focus. When we destroy the fixed focus is
    // automatically moved. Temporarily move focus to our host widget, then
    // restore focus after we create the new fixed_. This way focus hasn't
    // really moved.
    gtk_widget_grab_focus(GetHostWidget()->GetNativeView());
  }

  DestroyFixed();

  fixed_ = gtk_fixed_new();
  gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window);
  // Defeat refcounting. We need to own the fixed.
  gtk_widget_ref(fixed_);

  WidgetGtk* widget_gtk = GetHostWidget();
  if (widget_gtk)
    widget_gtk->AddChild(fixed_);

  if (host_->native_view())
    gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());

  if (widget_gtk && host_->native_view() && focused_widget) {
    if (fixed_is_focused)
      gtk_widget_grab_focus(fixed_);
    else
      gtk_widget_grab_focus(focused_widget);
  }
}

void NativeViewHostGtk::DestroyFixed() {
  if (!fixed_)
    return;

  gtk_widget_hide(fixed_);
  GetHostWidget()->RemoveChild(fixed_);

  if (host_->native_view()) {
    // We can safely remove the widget from its container since we own the
    // widget from the moment it is attached.
    gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view());
  }
  // fixed_ should not have any children this point.
  DCHECK_EQ(0U,
            g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
  gtk_widget_destroy(fixed_);
  fixed_ = NULL;
}

WidgetGtk* NativeViewHostGtk::GetHostWidget() const {
  return static_cast<WidgetGtk*>(host_->GetWidget());
}

GtkWidget* NativeViewHostGtk::GetFocusedDescendant() {
  if (!fixed_)
    return NULL;
  WidgetGtk* host = GetHostWidget();
  if (!host)
    return NULL;
  GtkWidget* top_level = gtk_widget_get_toplevel(host->GetNativeView());
  if (!top_level || !GTK_IS_WINDOW(top_level))
    return NULL;
  GtkWidget* focused = gtk_window_get_focus(GTK_WINDOW(top_level));
  if (!focused)
    return NULL;
  return (focused == fixed_ || gtk_widget_is_ancestor(focused, fixed_)) ?
      focused : NULL;
}

// static
void NativeViewHostGtk::CallDestroy(GtkObject* object,
                                    NativeViewHostGtk* host) {
  host->host_->NativeViewDestroyed();
}

// static
void NativeViewHostGtk::CallFocusIn(GtkWidget* widget,
                                    GdkEventFocus* event,
                                    NativeViewHostGtk* host) {
  FocusManager* focus_manager =
      FocusManager::GetFocusManagerForNativeView(widget);
  if (!focus_manager) {
    // TODO(jcampan): http://crbug.com/21378 Reenable this NOTREACHED() when the
    // options page is only based on views.
    // NOTREACHED();
    NOTIMPLEMENTED();
    return;
  }
  focus_manager->SetFocusedView(host->host_->focus_view());
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWrapper, public:

// static
NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
    NativeViewHost* host) {
  return new NativeViewHostGtk(host);
}

}  // namespace views
<commit_msg>Fixes bug that resulted in background tabs not getting sized correctly. When using fixed like we are we need to explicitly call allocate, otherwise the child won't get a size allocate and correctly update itself.<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 "views/controls/native/native_view_host_gtk.h"

#include <gtk/gtk.h>
#include <algorithm>

#include "base/logging.h"
#include "views/controls/native/native_view_host.h"
#include "views/focus/focus_manager.h"
#include "views/widget/widget_gtk.h"

namespace views {

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostGtk, public:

NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host)
    : host_(host),
      installed_clip_(false),
      destroy_signal_id_(0),
      focus_signal_id_(0),
      fixed_(NULL) {
  CreateFixed(false);
}

NativeViewHostGtk::~NativeViewHostGtk() {
  if (fixed_)
    gtk_widget_destroy(fixed_);
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostGtk, NativeViewHostWrapper implementation:

void NativeViewHostGtk::NativeViewAttached() {
  DCHECK(host_->native_view());
  if (gtk_widget_get_parent(host_->native_view()))
    gtk_widget_reparent(host_->native_view(), fixed_);
  else
    gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());

  if (!destroy_signal_id_) {
    destroy_signal_id_ = g_signal_connect(G_OBJECT(host_->native_view()),
                                          "destroy", G_CALLBACK(CallDestroy),
                                          this);
  }

  if (!focus_signal_id_) {
    focus_signal_id_ = g_signal_connect(G_OBJECT(host_->native_view()),
                                        "focus-in-event",
                                        G_CALLBACK(CallFocusIn), this);
  }

  // Always layout though.
  host_->Layout();

  // We own the native view as long as it's attached, so that we can safely
  // reparent it in multiple passes.
  gtk_widget_ref(host_->native_view());

  // TODO(port): figure out focus.
}

void NativeViewHostGtk::NativeViewDetaching(bool destroyed) {
  DCHECK(host_->native_view());

  g_signal_handler_disconnect(G_OBJECT(host_->native_view()),
                              destroy_signal_id_);
  destroy_signal_id_ = 0;

  g_signal_handler_disconnect(G_OBJECT(host_->native_view()),
                              focus_signal_id_);
  focus_signal_id_ = 0;

  installed_clip_ = false;

  if (fixed_ && !destroyed) {
    DCHECK_NE(static_cast<gfx::NativeView>(NULL),
              gtk_widget_get_parent(host_->native_view()));
    gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view());
    DCHECK_EQ(
        0U, g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
  }

  g_object_unref(G_OBJECT(host_->native_view()));
}

void NativeViewHostGtk::AddedToWidget() {
  if (!fixed_)
    CreateFixed(false);
  if (gtk_widget_get_parent(fixed_))
    GetHostWidget()->ReparentChild(fixed_);
  else
    GetHostWidget()->AddChild(fixed_);

  if (!host_->native_view())
    return;

  if (gtk_widget_get_parent(host_->native_view()))
    gtk_widget_reparent(host_->native_view(), fixed_);
  else
    gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());

  if (host_->IsVisibleInRootView())
    gtk_widget_show(fixed_);
  else
    gtk_widget_hide(fixed_);
  host_->Layout();
}

void NativeViewHostGtk::RemovedFromWidget() {
  if (!host_->native_view())
    return;

  DestroyFixed();
}

void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) {
  DCHECK(w > 0 && h > 0);
  installed_clip_bounds_.SetRect(x, y, w, h);
  installed_clip_ = true;

  // We only re-create the fixed with a window when a cliprect is installed.
  // Because the presence of a X Window will prevent transparency from working
  // properly, we only want it to be active for the duration of a clip
  // (typically during animations and scrolling.)
  CreateFixed(true);
}

bool NativeViewHostGtk::HasInstalledClip() {
  return installed_clip_;
}

void NativeViewHostGtk::UninstallClip() {
  installed_clip_ = false;
  // We now re-create the fixed without a X Window so transparency works again.
  CreateFixed(false);
}

void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) {
  // x and y are the desired position of host_ in WidgetGtk coordinates.
  int fixed_x = x;
  int fixed_y = y;
  int fixed_w = w;
  int fixed_h = h;
  int child_x = 0;
  int child_y = 0;
  int child_w = w;
  int child_h = h;
  if (installed_clip_) {
    child_x = -installed_clip_bounds_.x();
    child_y = -installed_clip_bounds_.y();
    fixed_x += -child_x;
    fixed_y += -child_y;
    fixed_w = std::min(installed_clip_bounds_.width(), w);
    fixed_h = std::min(installed_clip_bounds_.height(), h);
  }

  // Size and place the fixed_.
  GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h);

  // Size and place the hosted NativeView.
  gtk_widget_set_size_request(host_->native_view(), child_w, child_h);
  gtk_fixed_move(GTK_FIXED(fixed_), host_->native_view(), child_x, child_y);
  GtkAllocation alloc = { child_x, child_y, child_w, child_y};
  gtk_widget_size_allocate(host_->native_view(), &alloc);

  gtk_widget_show(fixed_);
  gtk_widget_show(host_->native_view());
}

void NativeViewHostGtk::HideWidget() {
  gtk_widget_hide(fixed_);
}

void NativeViewHostGtk::SetFocus() {
  DCHECK(host_->native_view());
  gtk_widget_grab_focus(host_->native_view());
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostGtk, private:

void NativeViewHostGtk::CreateFixed(bool needs_window) {
  GtkWidget* focused_widget = GetFocusedDescendant();
  bool fixed_is_focused = (focused_widget == fixed_);

  if (focused_widget) {
    // A descendant of our fixed has focus. When we destroy the fixed focus is
    // automatically moved. Temporarily move focus to our host widget, then
    // restore focus after we create the new fixed_. This way focus hasn't
    // really moved.
    gtk_widget_grab_focus(GetHostWidget()->GetNativeView());
  }

  DestroyFixed();

  fixed_ = gtk_fixed_new();
  gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window);
  // Defeat refcounting. We need to own the fixed.
  gtk_widget_ref(fixed_);

  WidgetGtk* widget_gtk = GetHostWidget();
  if (widget_gtk)
    widget_gtk->AddChild(fixed_);

  if (host_->native_view())
    gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());

  if (widget_gtk && host_->native_view() && focused_widget) {
    if (fixed_is_focused)
      gtk_widget_grab_focus(fixed_);
    else
      gtk_widget_grab_focus(focused_widget);
  }
}

void NativeViewHostGtk::DestroyFixed() {
  if (!fixed_)
    return;

  gtk_widget_hide(fixed_);
  GetHostWidget()->RemoveChild(fixed_);

  if (host_->native_view()) {
    // We can safely remove the widget from its container since we own the
    // widget from the moment it is attached.
    gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view());
  }
  // fixed_ should not have any children this point.
  DCHECK_EQ(0U,
            g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
  gtk_widget_destroy(fixed_);
  fixed_ = NULL;
}

WidgetGtk* NativeViewHostGtk::GetHostWidget() const {
  return static_cast<WidgetGtk*>(host_->GetWidget());
}

GtkWidget* NativeViewHostGtk::GetFocusedDescendant() {
  if (!fixed_)
    return NULL;
  WidgetGtk* host = GetHostWidget();
  if (!host)
    return NULL;
  GtkWidget* top_level = gtk_widget_get_toplevel(host->GetNativeView());
  if (!top_level || !GTK_IS_WINDOW(top_level))
    return NULL;
  GtkWidget* focused = gtk_window_get_focus(GTK_WINDOW(top_level));
  if (!focused)
    return NULL;
  return (focused == fixed_ || gtk_widget_is_ancestor(focused, fixed_)) ?
      focused : NULL;
}

// static
void NativeViewHostGtk::CallDestroy(GtkObject* object,
                                    NativeViewHostGtk* host) {
  host->host_->NativeViewDestroyed();
}

// static
void NativeViewHostGtk::CallFocusIn(GtkWidget* widget,
                                    GdkEventFocus* event,
                                    NativeViewHostGtk* host) {
  FocusManager* focus_manager =
      FocusManager::GetFocusManagerForNativeView(widget);
  if (!focus_manager) {
    // TODO(jcampan): http://crbug.com/21378 Reenable this NOTREACHED() when the
    // options page is only based on views.
    // NOTREACHED();
    NOTIMPLEMENTED();
    return;
  }
  focus_manager->SetFocusedView(host->host_->focus_view());
}

////////////////////////////////////////////////////////////////////////////////
// NativeViewHostWrapper, public:

// static
NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
    NativeViewHost* host) {
  return new NativeViewHostGtk(host);
}

}  // namespace views
<|endoftext|>


<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 "content/browser/renderer_host/web_input_event_aura.h"

#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"

#if defined(USE_OZONE)
#include "ui/events/keycodes/keyboard_code_conversion.h"
#endif

namespace content {

#if defined(OS_WIN)
blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
    const base::NativeEvent& native_event);
blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
    const base::NativeEvent& native_event);
blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
    const base::NativeEvent& native_event);
blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
    const base::NativeEvent& native_event);
#endif
#if defined(USE_X11) || defined(USE_OZONE)
blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
    ui::KeyEvent* event) {
  blink::WebKeyboardEvent webkit_event;

  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());

  switch (event->type()) {
    case ui::ET_KEY_PRESSED:
      webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
          blink::WebInputEvent::RawKeyDown;
      break;
    case ui::ET_KEY_RELEASED:
      webkit_event.type = blink::WebInputEvent::KeyUp;
      break;
    default:
      NOTREACHED();
  }

  if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
    webkit_event.isSystemKey = true;

  webkit_event.windowsKeyCode = event->GetLocatedWindowsKeyboardCode();
  webkit_event.nativeKeyCode = event->platform_keycode();
  webkit_event.unmodifiedText[0] = event->GetUnmodifiedText();
  webkit_event.text[0] = event->GetText();

  webkit_event.setKeyIdentifierFromWindowsKeyCode();

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    ui::ScrollEvent* event) {
  blink::WebMouseWheelEvent webkit_event;

  webkit_event.type = blink::WebInputEvent::MouseWheel;
  webkit_event.button = blink::WebMouseEvent::ButtonNone;
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
  webkit_event.hasPreciseScrollingDeltas = true;

  float offset_ordinal_x = 0.f;
  float offset_ordinal_y = 0.f;
  if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 && event->x_offset() == 0) {
    webkit_event.deltaX = event->y_offset();
    webkit_event.deltaY = 0;
    offset_ordinal_x = event->y_offset_ordinal();
    offset_ordinal_y = event->x_offset_ordinal();
  } else {
    webkit_event.deltaX = event->x_offset();
    webkit_event.deltaY = event->y_offset();
    offset_ordinal_x = event->x_offset_ordinal();
    offset_ordinal_y = event->y_offset_ordinal();
  }

  if (offset_ordinal_x != 0.f && webkit_event.deltaX != 0.f)
    webkit_event.accelerationRatioX = offset_ordinal_x / webkit_event.deltaX;
  webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
  webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
  if (offset_ordinal_y != 0.f && webkit_event.deltaY != 0.f)
    webkit_event.accelerationRatioY = offset_ordinal_y / webkit_event.deltaY;
  return webkit_event;
}

blink::WebGestureEvent MakeWebGestureEventFromAuraEvent(
    ui::ScrollEvent* event) {
  blink::WebGestureEvent webkit_event;

  switch (event->type()) {
    case ui::ET_SCROLL_FLING_START:
      webkit_event.type = blink::WebInputEvent::GestureFlingStart;
      webkit_event.data.flingStart.velocityX = event->x_offset();
      webkit_event.data.flingStart.velocityY = event->y_offset();
      break;
    case ui::ET_SCROLL_FLING_CANCEL:
      webkit_event.type = blink::WebInputEvent::GestureFlingCancel;
      break;
    case ui::ET_SCROLL:
      NOTREACHED() << "Invalid gesture type: " << event->type();
      break;
    default:
      NOTREACHED() << "Unknown gesture type: " << event->type();
  }

  webkit_event.sourceDevice = blink::WebGestureDeviceTouchpad;
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
  return webkit_event;
}

#endif

blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(
    ui::MouseEvent* event);
blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    ui::MouseWheelEvent* event);

// General approach:
//
// ui::Event only carries a subset of possible event data provided to Aura by
// the host platform. WebKit utilizes a larger subset of that information than
// Aura itself. WebKit includes some built in cracking functionality that we
// rely on to obtain this information cleanly and consistently.
//
// The only place where an ui::Event's data differs from what the underlying
// base::NativeEvent would provide is position data, since we would like to
// provide coordinates relative to the aura::Window that is hosting the
// renderer, not the top level platform window.
//
// The approach is to fully construct a blink::WebInputEvent from the
// ui::Event's base::NativeEvent, and then replace the coordinate fields with
// the translated values from the ui::Event.
//
// The exception is mouse events on linux. The ui::MouseEvent contains enough
// necessary information to construct a WebMouseEvent. So instead of extracting
// the information from the XEvent, which can be tricky when supporting both
// XInput2 and XInput, the WebMouseEvent is constructed from the
// ui::MouseEvent. This will not be necessary once only XInput2 is supported.
//

blink::WebMouseEvent MakeWebMouseEvent(ui::MouseEvent* event) {
  // Construct an untranslated event from the platform event data.
  blink::WebMouseEvent webkit_event =
#if defined(OS_WIN)
  // On Windows we have WM_ events comming from desktop and pure aura
  // events comming from metro mode.
  event->native_event().message ?
      MakeUntranslatedWebMouseEventFromNativeEvent(event->native_event()) :
      MakeWebMouseEventFromAuraEvent(event);
#else
  MakeWebMouseEventFromAuraEvent(event);
#endif
  // Replace the event's coordinate fields with translated position data from
  // |event|.
  webkit_event.windowX = webkit_event.x = event->x();
  webkit_event.windowY = webkit_event.y = event->y();

#if defined(OS_WIN)
  if (event->native_event().message)
    return webkit_event;
#endif
  const gfx::Point root_point = event->root_location();
  webkit_event.globalX = root_point.x();
  webkit_event.globalY = root_point.y();

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::MouseWheelEvent* event) {
#if defined(OS_WIN)
  // Construct an untranslated event from the platform event data.
  blink::WebMouseWheelEvent webkit_event = event->native_event().message ?
      MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event()) :
      MakeWebMouseWheelEventFromAuraEvent(event);
#else
  blink::WebMouseWheelEvent webkit_event =
      MakeWebMouseWheelEventFromAuraEvent(event);
#endif

  // Replace the event's coordinate fields with translated position data from
  // |event|.
  webkit_event.windowX = webkit_event.x = event->x();
  webkit_event.windowY = webkit_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  webkit_event.globalX = root_point.x();
  webkit_event.globalY = root_point.y();

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
#if defined(OS_WIN)
  // Construct an untranslated event from the platform event data.
  blink::WebMouseWheelEvent webkit_event =
      MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event());
#else
  blink::WebMouseWheelEvent webkit_event =
      MakeWebMouseWheelEventFromAuraEvent(event);
#endif

  // Replace the event's coordinate fields with translated position data from
  // |event|.
  webkit_event.windowX = webkit_event.x = event->x();
  webkit_event.windowY = webkit_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  webkit_event.globalX = root_point.x();
  webkit_event.globalY = root_point.y();

  return webkit_event;
}

blink::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
  // Windows can figure out whether or not to construct a RawKeyDown or a Char
  // WebInputEvent based on the type of message carried in
  // event->native_event(). X11 is not so fortunate, there is no separate
  // translated event type, so DesktopHostLinux sends an extra KeyEvent with
  // is_char() == true. We need to pass the ui::KeyEvent to the X11 function
  // to detect this case so the right event type can be constructed.
#if defined(OS_WIN)
  if (!event->HasNativeEvent())
    return blink::WebKeyboardEvent();

  // Key events require no translation by the aura system.
  return MakeWebKeyboardEventFromNativeEvent(event->native_event());
#else
  return MakeWebKeyboardEventFromAuraEvent(event);
#endif
}

blink::WebGestureEvent MakeWebGestureEvent(ui::GestureEvent* event) {
  blink::WebGestureEvent gesture_event;
#if defined(OS_WIN)
  if (event->HasNativeEvent())
    gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
  else
    gesture_event = MakeWebGestureEventFromUIEvent(*event);
#else
  gesture_event = MakeWebGestureEventFromUIEvent(*event);
#endif

  gesture_event.x = event->x();
  gesture_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  gesture_event.globalX = root_point.x();
  gesture_event.globalY = root_point.y();

  return gesture_event;
}

blink::WebGestureEvent MakeWebGestureEvent(ui::ScrollEvent* event) {
  blink::WebGestureEvent gesture_event;

#if defined(OS_WIN)
  gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
#else
  gesture_event = MakeWebGestureEventFromAuraEvent(event);
#endif

  gesture_event.x = event->x();
  gesture_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  gesture_event.globalX = root_point.x();
  gesture_event.globalY = root_point.y();

  return gesture_event;
}

blink::WebGestureEvent MakeWebGestureEventFlingCancel() {
  blink::WebGestureEvent gesture_event;

  // All other fields are ignored on a GestureFlingCancel event.
  gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
  gesture_event.sourceDevice = blink::WebGestureDeviceTouchpad;
  return gesture_event;
}

blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
  blink::WebMouseEvent webkit_event;

  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();

  webkit_event.button = blink::WebMouseEvent::ButtonNone;
  int button_flags = event->flags();
  if (event->type() == ui::ET_MOUSE_PRESSED ||
      event->type() == ui::ET_MOUSE_RELEASED) {
    // We want to use changed_button_flags() for mouse pressed & released.
    // These flags can be used only if they are set which is not always the case
    // (see e.g. GetChangedMouseButtonFlagsFromNative() in events_win.cc).
    if (event->changed_button_flags())
      button_flags = event->changed_button_flags();
  }
  if (button_flags & ui::EF_LEFT_MOUSE_BUTTON)
    webkit_event.button = blink::WebMouseEvent::ButtonLeft;
  if (button_flags & ui::EF_MIDDLE_MOUSE_BUTTON)
    webkit_event.button = blink::WebMouseEvent::ButtonMiddle;
  if (button_flags & ui::EF_RIGHT_MOUSE_BUTTON)
    webkit_event.button = blink::WebMouseEvent::ButtonRight;

  switch (event->type()) {
    case ui::ET_MOUSE_PRESSED:
      webkit_event.type = blink::WebInputEvent::MouseDown;
      webkit_event.clickCount = event->GetClickCount();
      break;
    case ui::ET_MOUSE_RELEASED:
      webkit_event.type = blink::WebInputEvent::MouseUp;
      webkit_event.clickCount = event->GetClickCount();
      break;
    case ui::ET_MOUSE_ENTERED:
    case ui::ET_MOUSE_EXITED:
    case ui::ET_MOUSE_MOVED:
    case ui::ET_MOUSE_DRAGGED:
      webkit_event.type = blink::WebInputEvent::MouseMove;
      break;
    default:
      NOTIMPLEMENTED() << "Received unexpected event: " << event->type();
      break;
  }

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    ui::MouseWheelEvent* event) {
  blink::WebMouseWheelEvent webkit_event;

  webkit_event.type = blink::WebInputEvent::MouseWheel;
  webkit_event.button = blink::WebMouseEvent::ButtonNone;
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();

  if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 && event->x_offset() == 0) {
    webkit_event.deltaX = event->y_offset();
    webkit_event.deltaY = 0;
  } else {
    webkit_event.deltaX = event->x_offset();
    webkit_event.deltaY = event->y_offset();
  }

  webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
  webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;

  return webkit_event;
}

}  // namespace content
<commit_msg>Fix native key code under X11.<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 "content/browser/renderer_host/web_input_event_aura.h"

#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"

#if defined(USE_X11) || defined(USE_OZONE)
#include "ui/events/keycodes/dom4/keycode_converter.h"
#endif

namespace content {

#if defined(OS_WIN)
blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
    const base::NativeEvent& native_event);
blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
    const base::NativeEvent& native_event);
blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
    const base::NativeEvent& native_event);
blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
    const base::NativeEvent& native_event);
#endif
#if defined(USE_X11) || defined(USE_OZONE)
blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
    ui::KeyEvent* event) {
  blink::WebKeyboardEvent webkit_event;

  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());

  switch (event->type()) {
    case ui::ET_KEY_PRESSED:
      webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
          blink::WebInputEvent::RawKeyDown;
      break;
    case ui::ET_KEY_RELEASED:
      webkit_event.type = blink::WebInputEvent::KeyUp;
      break;
    default:
      NOTREACHED();
  }

  if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
    webkit_event.isSystemKey = true;

  webkit_event.windowsKeyCode = event->GetLocatedWindowsKeyboardCode();
  webkit_event.nativeKeyCode =
    ui::KeycodeConverter::CodeToNativeKeycode(event->code().c_str());
  webkit_event.unmodifiedText[0] = event->GetUnmodifiedText();
  webkit_event.text[0] = event->GetText();

  webkit_event.setKeyIdentifierFromWindowsKeyCode();

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    ui::ScrollEvent* event) {
  blink::WebMouseWheelEvent webkit_event;

  webkit_event.type = blink::WebInputEvent::MouseWheel;
  webkit_event.button = blink::WebMouseEvent::ButtonNone;
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
  webkit_event.hasPreciseScrollingDeltas = true;

  float offset_ordinal_x = 0.f;
  float offset_ordinal_y = 0.f;
  if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 && event->x_offset() == 0) {
    webkit_event.deltaX = event->y_offset();
    webkit_event.deltaY = 0;
    offset_ordinal_x = event->y_offset_ordinal();
    offset_ordinal_y = event->x_offset_ordinal();
  } else {
    webkit_event.deltaX = event->x_offset();
    webkit_event.deltaY = event->y_offset();
    offset_ordinal_x = event->x_offset_ordinal();
    offset_ordinal_y = event->y_offset_ordinal();
  }

  if (offset_ordinal_x != 0.f && webkit_event.deltaX != 0.f)
    webkit_event.accelerationRatioX = offset_ordinal_x / webkit_event.deltaX;
  webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
  webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
  if (offset_ordinal_y != 0.f && webkit_event.deltaY != 0.f)
    webkit_event.accelerationRatioY = offset_ordinal_y / webkit_event.deltaY;
  return webkit_event;
}

blink::WebGestureEvent MakeWebGestureEventFromAuraEvent(
    ui::ScrollEvent* event) {
  blink::WebGestureEvent webkit_event;

  switch (event->type()) {
    case ui::ET_SCROLL_FLING_START:
      webkit_event.type = blink::WebInputEvent::GestureFlingStart;
      webkit_event.data.flingStart.velocityX = event->x_offset();
      webkit_event.data.flingStart.velocityY = event->y_offset();
      break;
    case ui::ET_SCROLL_FLING_CANCEL:
      webkit_event.type = blink::WebInputEvent::GestureFlingCancel;
      break;
    case ui::ET_SCROLL:
      NOTREACHED() << "Invalid gesture type: " << event->type();
      break;
    default:
      NOTREACHED() << "Unknown gesture type: " << event->type();
  }

  webkit_event.sourceDevice = blink::WebGestureDeviceTouchpad;
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
  return webkit_event;
}

#endif

blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(
    ui::MouseEvent* event);
blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    ui::MouseWheelEvent* event);

// General approach:
//
// ui::Event only carries a subset of possible event data provided to Aura by
// the host platform. WebKit utilizes a larger subset of that information than
// Aura itself. WebKit includes some built in cracking functionality that we
// rely on to obtain this information cleanly and consistently.
//
// The only place where an ui::Event's data differs from what the underlying
// base::NativeEvent would provide is position data, since we would like to
// provide coordinates relative to the aura::Window that is hosting the
// renderer, not the top level platform window.
//
// The approach is to fully construct a blink::WebInputEvent from the
// ui::Event's base::NativeEvent, and then replace the coordinate fields with
// the translated values from the ui::Event.
//
// The exception is mouse events on linux. The ui::MouseEvent contains enough
// necessary information to construct a WebMouseEvent. So instead of extracting
// the information from the XEvent, which can be tricky when supporting both
// XInput2 and XInput, the WebMouseEvent is constructed from the
// ui::MouseEvent. This will not be necessary once only XInput2 is supported.
//

blink::WebMouseEvent MakeWebMouseEvent(ui::MouseEvent* event) {
  // Construct an untranslated event from the platform event data.
  blink::WebMouseEvent webkit_event =
#if defined(OS_WIN)
  // On Windows we have WM_ events comming from desktop and pure aura
  // events comming from metro mode.
  event->native_event().message ?
      MakeUntranslatedWebMouseEventFromNativeEvent(event->native_event()) :
      MakeWebMouseEventFromAuraEvent(event);
#else
  MakeWebMouseEventFromAuraEvent(event);
#endif
  // Replace the event's coordinate fields with translated position data from
  // |event|.
  webkit_event.windowX = webkit_event.x = event->x();
  webkit_event.windowY = webkit_event.y = event->y();

#if defined(OS_WIN)
  if (event->native_event().message)
    return webkit_event;
#endif
  const gfx::Point root_point = event->root_location();
  webkit_event.globalX = root_point.x();
  webkit_event.globalY = root_point.y();

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::MouseWheelEvent* event) {
#if defined(OS_WIN)
  // Construct an untranslated event from the platform event data.
  blink::WebMouseWheelEvent webkit_event = event->native_event().message ?
      MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event()) :
      MakeWebMouseWheelEventFromAuraEvent(event);
#else
  blink::WebMouseWheelEvent webkit_event =
      MakeWebMouseWheelEventFromAuraEvent(event);
#endif

  // Replace the event's coordinate fields with translated position data from
  // |event|.
  webkit_event.windowX = webkit_event.x = event->x();
  webkit_event.windowY = webkit_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  webkit_event.globalX = root_point.x();
  webkit_event.globalY = root_point.y();

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
#if defined(OS_WIN)
  // Construct an untranslated event from the platform event data.
  blink::WebMouseWheelEvent webkit_event =
      MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event());
#else
  blink::WebMouseWheelEvent webkit_event =
      MakeWebMouseWheelEventFromAuraEvent(event);
#endif

  // Replace the event's coordinate fields with translated position data from
  // |event|.
  webkit_event.windowX = webkit_event.x = event->x();
  webkit_event.windowY = webkit_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  webkit_event.globalX = root_point.x();
  webkit_event.globalY = root_point.y();

  return webkit_event;
}

blink::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
  // Windows can figure out whether or not to construct a RawKeyDown or a Char
  // WebInputEvent based on the type of message carried in
  // event->native_event(). X11 is not so fortunate, there is no separate
  // translated event type, so DesktopHostLinux sends an extra KeyEvent with
  // is_char() == true. We need to pass the ui::KeyEvent to the X11 function
  // to detect this case so the right event type can be constructed.
#if defined(OS_WIN)
  if (!event->HasNativeEvent())
    return blink::WebKeyboardEvent();

  // Key events require no translation by the aura system.
  return MakeWebKeyboardEventFromNativeEvent(event->native_event());
#else
  return MakeWebKeyboardEventFromAuraEvent(event);
#endif
}

blink::WebGestureEvent MakeWebGestureEvent(ui::GestureEvent* event) {
  blink::WebGestureEvent gesture_event;
#if defined(OS_WIN)
  if (event->HasNativeEvent())
    gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
  else
    gesture_event = MakeWebGestureEventFromUIEvent(*event);
#else
  gesture_event = MakeWebGestureEventFromUIEvent(*event);
#endif

  gesture_event.x = event->x();
  gesture_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  gesture_event.globalX = root_point.x();
  gesture_event.globalY = root_point.y();

  return gesture_event;
}

blink::WebGestureEvent MakeWebGestureEvent(ui::ScrollEvent* event) {
  blink::WebGestureEvent gesture_event;

#if defined(OS_WIN)
  gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
#else
  gesture_event = MakeWebGestureEventFromAuraEvent(event);
#endif

  gesture_event.x = event->x();
  gesture_event.y = event->y();

  const gfx::Point root_point = event->root_location();
  gesture_event.globalX = root_point.x();
  gesture_event.globalY = root_point.y();

  return gesture_event;
}

blink::WebGestureEvent MakeWebGestureEventFlingCancel() {
  blink::WebGestureEvent gesture_event;

  // All other fields are ignored on a GestureFlingCancel event.
  gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
  gesture_event.sourceDevice = blink::WebGestureDeviceTouchpad;
  return gesture_event;
}

blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
  blink::WebMouseEvent webkit_event;

  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();

  webkit_event.button = blink::WebMouseEvent::ButtonNone;
  int button_flags = event->flags();
  if (event->type() == ui::ET_MOUSE_PRESSED ||
      event->type() == ui::ET_MOUSE_RELEASED) {
    // We want to use changed_button_flags() for mouse pressed & released.
    // These flags can be used only if they are set which is not always the case
    // (see e.g. GetChangedMouseButtonFlagsFromNative() in events_win.cc).
    if (event->changed_button_flags())
      button_flags = event->changed_button_flags();
  }
  if (button_flags & ui::EF_LEFT_MOUSE_BUTTON)
    webkit_event.button = blink::WebMouseEvent::ButtonLeft;
  if (button_flags & ui::EF_MIDDLE_MOUSE_BUTTON)
    webkit_event.button = blink::WebMouseEvent::ButtonMiddle;
  if (button_flags & ui::EF_RIGHT_MOUSE_BUTTON)
    webkit_event.button = blink::WebMouseEvent::ButtonRight;

  switch (event->type()) {
    case ui::ET_MOUSE_PRESSED:
      webkit_event.type = blink::WebInputEvent::MouseDown;
      webkit_event.clickCount = event->GetClickCount();
      break;
    case ui::ET_MOUSE_RELEASED:
      webkit_event.type = blink::WebInputEvent::MouseUp;
      webkit_event.clickCount = event->GetClickCount();
      break;
    case ui::ET_MOUSE_ENTERED:
    case ui::ET_MOUSE_EXITED:
    case ui::ET_MOUSE_MOVED:
    case ui::ET_MOUSE_DRAGGED:
      webkit_event.type = blink::WebInputEvent::MouseMove;
      break;
    default:
      NOTIMPLEMENTED() << "Received unexpected event: " << event->type();
      break;
  }

  return webkit_event;
}

blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    ui::MouseWheelEvent* event) {
  blink::WebMouseWheelEvent webkit_event;

  webkit_event.type = blink::WebInputEvent::MouseWheel;
  webkit_event.button = blink::WebMouseEvent::ButtonNone;
  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();

  if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 && event->x_offset() == 0) {
    webkit_event.deltaX = event->y_offset();
    webkit_event.deltaY = 0;
  } else {
    webkit_event.deltaX = event->x_offset();
    webkit_event.deltaY = event->y_offset();
  }

  webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
  webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;

  return webkit_event;
}

}  // namespace content
<|endoftext|>