<commit_before>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2014 ETH Zurich
 ** All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 ** following conditions are met:
 **
 **    * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 **      following disclaimer.
 **    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 **      following disclaimer in the documentation and/or other materials provided with the distribution.
 **    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
 **      derived from this software without specific prior written permission.
 **
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/
#include "ZoomLabelOverlay.h"
#include "shapes/Shape.h"
#include "../declarative/DeclarativeItemDef.h"
#include "VisualizationBase/src/icons/Icon.h"
#include "VisualizationBase/src/icons/IconStyle.h"
#include "VisualizationBase/src/items/StaticStyle.h"
#include "VisualizationBase/src/items/Text.h"
#include "VisualizationBase/src/items/Static.h"
#include "VisualizationBase/src/items/TextStyle.h"
#include "VisualizationBase/src/items/RootItem.h"
#include "VisualizationBase/src/overlays/OverlayAccessor.h"

namespace Visualization {

ITEM_COMMON_DEFINITIONS(ZoomLabelOverlay, "item")

QHash<Item*, ZoomLabelOverlay*>& ZoomLabelOverlay::itemToOverlay()
{
	static QHash<Item*, ZoomLabelOverlay*> map;
	return map;
}

ZoomLabelOverlay::ZoomLabelOverlay(Item* itemWithLabel, const StyleType* style) : Super{{itemWithLabel}, style}
{
	Q_ASSERT(itemWithLabel->node());
	Q_ASSERT(itemWithLabel->node()->definesSymbol());
	iconStyle_ = associatedItemIconStyle();
	itemToOverlay().insert(itemWithLabel, this);
}

void ZoomLabelOverlay::determineChildren()
{
	Super::determineChildren();
	text_->setText(associatedItemText());
}

void ZoomLabelOverlay::updateGeometry(int availableWidth, int availableHeight)
{
	Super::updateGeometry(availableWidth, availableHeight);

	setPos(associatedItem()->scenePos());

	auto maxScale = 1/mainViewScalingFactor();
	auto widthScale = associatedItem()->widthInScene() / (double) widthInLocal();
	auto heightScale = associatedItem()->heightInScene() / (double) heightInLocal();
	auto scaleToUse = maxScale;
	if (widthScale < scaleToUse) scaleToUse = widthScale;
	if (heightScale < scaleToUse) scaleToUse = heightScale;

	setScale(scaleToUse);
}

bool ZoomLabelOverlay::isSensitiveToScale() const
{
	return true;
}

int ZoomLabelOverlay::determineForm()
{
	return iconStyle_ ? 1 : 0;
}

void ZoomLabelOverlay::initializeForms()
{
	addForm(item<Text>(&I::text_, [](I* v){return v->associatedItemTextStyle();}));

	addForm(grid({{item<Static>(&I::icon_, [](I* v){ return v->iconStyle_;}),
		item<Text>(&I::text_, [](I* v){return v->associatedItemTextStyle();})}})
			  ->setVerticalAlignment(LayoutStyle::Alignment::Center));
}

const StaticStyle* ZoomLabelOverlay::associatedItemIconStyle() const
{
	const StaticStyle* iconStyle{};
	for (auto child : associatedItem()->childItems())
	{
		if ( auto childStaticStyle = dynamic_cast<const StaticStyle*>(child->style()) )
			if (dynamic_cast<const IconStyle*> (&childStaticStyle->itemStyle()))
		{
			if (!iconStyle) iconStyle = childStaticStyle;
			else return nullptr; // We found at least 2 icons => ambiguous
		}

	}

	return iconStyle; // Could be nullptr to indicate no icon;
}

const QString& ZoomLabelOverlay::associatedItemText() const
{
	return associatedItem()->node()->symbolName();
}

const TextStyle* ZoomLabelOverlay::associatedItemTextStyle() const
{
	const TextStyle* textStyle{};
	for (auto child : associatedItem()->childItems())
		if ( auto textChild = DCast<TextRenderer>(child) )
		{
			if (textChild->text() == associatedItemText())
			{
				if (!textStyle) textStyle = textChild->style();
				else
				{
					//we have found more than one text item representing the same string, ambiguous
					textStyle = nullptr;
					break;
				}
			}
		}

	return textStyle ? textStyle : Text::itemStyles().get();
}

QList<Item*> ZoomLabelOverlay::itemsThatShouldHaveZoomLabel(Scene* scene)
{
	QList<Item*> result;

	const double OVERLAY_SCALE_TRESHOLD = 0.5;
	auto scalingFactor = scene->mainViewScalingFactor();

	if (scalingFactor >= OVERLAY_SCALE_TRESHOLD)
	{
		itemToOverlay().clear();
		return result;
	}

	QList<Item*> stack = scene->topLevelItems();
	while (!stack.isEmpty())
	{
		auto item = stack.takeLast();

			if (item->widthInParent() * scalingFactor < OVERLAY_MIN_WIDTH
					|| item->heightInParent() * scalingFactor < OVERLAY_MIN_HEIGHT)
				continue;

		auto definesSymbol = !DCast<RootItem>(item) && item->node() && item->node()->definesSymbol();

		if (definesSymbol) result.append(item);
		stack.append(item->childItems());
	}

	return result;
}

void ZoomLabelOverlay::setItemPositionsAndHideOverlapped(OverlayGroup& group)
{
	static int postUpdateRevision{};
	++postUpdateRevision;

	for (auto accessor : group.overlays())
		static_cast<ZoomLabelOverlay*>(accessor->overlayItem())->postUpdate(postUpdateRevision);
}

void ZoomLabelOverlay::postUpdate(int revision)
{
	// If already updated, do nothing
	if (postUpdateRevision_ == revision) return;
	postUpdateRevision_ = revision;

	// Make sure all overlays above this one are updated
	auto item = associatedItem()->parent();
	while (item)
	{
		auto overlayIt = itemToOverlay().find(item);
		if (overlayIt != itemToOverlay().end())
		{
			overlayIt.value()->postUpdate(revision);
			break;
		}

		item = item->parent();
	}

	// Finally adjust the position of this overlay so that it does not overlap or if that's impossible, hide it.
	adjustPositionOrHide();
}

inline void ZoomLabelOverlay::reduceRect(QRect& rectToReduce, const QRect& rectToExclude)
{
	QRect intersected = rectToReduce.intersected(rectToExclude);
	if (intersected.isEmpty()) return; // No intersection

	// Now we will grow the intersected rect until it has at least three sides equal to the sides of rectToReduce
	// Then we'll just take what's left

	// Make sure only one of top/bottom is in the middle
	int distanceToTop = intersected.top() - rectToReduce.top();
	int distanceToBottom = rectToReduce.bottom() - intersected.bottom();
	if (distanceToTop > distanceToBottom) intersected.setBottom(rectToReduce.bottom());
	else intersected.setTop(rectToReduce.top());

	Q_ASSERT(rectToReduce.top() == intersected.top() || rectToReduce.bottom() == intersected.bottom());

	// Make sure only one of left/right is in the middle
	int distanceToLeft = intersected.left() - rectToReduce.left();
	int distanceToRight = rectToReduce.right() - intersected.right();
	if (distanceToLeft > distanceToRight) intersected.setRight(rectToReduce.right());
	else intersected.setLeft(rectToReduce.left());

	Q_ASSERT(rectToReduce.left() == intersected.left() || rectToReduce.right() == intersected.right());

	// At this point we might still have an intersecting rect in a corner. In that case take away the chunk that has
	// the smaller area.
	int horizontalArea = intersected.height()* rectToReduce.width();
	int verticalArea = intersected.width()* rectToReduce.height();
	if (horizontalArea < verticalArea)
	{
		intersected.setLeft( rectToReduce.left() );
		intersected.setRight( rectToReduce.right() );
	}
	else
	{
		intersected.setTop( rectToReduce.top() );
		intersected.setBottom( rectToReduce.bottom() );
	}

	Q_ASSERT( (rectToReduce.top() == intersected.top() && rectToReduce.bottom() == intersected.bottom()) ||
				 (rectToReduce.left() == intersected.left() && rectToReduce.right() == intersected.right()));

	// At this point we can just do rectToReduce = rectToReduce - intersected
	if (rectToReduce.top() != intersected.top()) rectToReduce.setBottom(intersected.top());
	else if (rectToReduce.bottom() != intersected.bottom()) rectToReduce.setTop(intersected.bottom()+1);
	else if (rectToReduce.left() != intersected.left()) rectToReduce.setRight(intersected.left());
	else if (rectToReduce.right() != intersected.right()) rectToReduce.setLeft(intersected.right()+1);
	else // complete overlap
	{
		rectToReduce.setWidth(0);
		rectToReduce.setHeight(0);
	}
}

void ZoomLabelOverlay::adjustPositionOrHide()
{
	auto availableRect = associatedItem()->sceneBoundingRect().toRect();

	auto item = associatedItem()->parent();
	while (item)
	{
		auto overlayIt = itemToOverlay().find(item);
		if (overlayIt != itemToOverlay().end() && overlayIt.value()->isVisible())
			reduceRect(availableRect, overlayIt.value()->sceneBoundingRect().toRect());

		item = item->parent();
	}

	// At this point we know in what amount of space we're supposed to fit.

	// If the space is too small don't bother trying to compute a scale
	bool visible = true;
	auto scalingFactor = scene()->mainViewScalingFactor();
	if (availableRect.width() * scalingFactor < OVERLAY_MIN_WIDTH
			|| availableRect.height() * scalingFactor < OVERLAY_MIN_HEIGHT) visible = false;

	// If there might be enough space, then try to fit in
	if (visible)
	{
		setPos(availableRect.topLeft());

		auto maxScale = 1/scalingFactor;
		auto widthScale = availableRect.width() / (double) widthInLocal();
		auto heightScale = availableRect.height() / (double) heightInLocal();
		auto scaleToUse = maxScale;
		if (widthScale < scaleToUse) scaleToUse = widthScale;
		if (heightScale < scaleToUse) scaleToUse = heightScale;

		setScale(scaleToUse);
	}

	if (visible != isVisible()) setVisible(visible);
}

} /* namespace Visualization */
<commit_msg>Only show zoom labels of items visible in the main view<commit_after>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2014 ETH Zurich
 ** All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 ** following conditions are met:
 **
 **    * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 **      following disclaimer.
 **    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 **      following disclaimer in the documentation and/or other materials provided with the distribution.
 **    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
 **      derived from this software without specific prior written permission.
 **
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/
#include "ZoomLabelOverlay.h"
#include "shapes/Shape.h"
#include "../declarative/DeclarativeItemDef.h"
#include "VisualizationBase/src/icons/Icon.h"
#include "VisualizationBase/src/icons/IconStyle.h"
#include "VisualizationBase/src/items/StaticStyle.h"
#include "VisualizationBase/src/items/Text.h"
#include "VisualizationBase/src/items/Static.h"
#include "VisualizationBase/src/items/TextStyle.h"
#include "VisualizationBase/src/items/RootItem.h"
#include "VisualizationBase/src/overlays/OverlayAccessor.h"
#include "VisualizationBase/src/views/MainView.h"

namespace Visualization {

ITEM_COMMON_DEFINITIONS(ZoomLabelOverlay, "item")

QHash<Item*, ZoomLabelOverlay*>& ZoomLabelOverlay::itemToOverlay()
{
	static QHash<Item*, ZoomLabelOverlay*> map;
	return map;
}

ZoomLabelOverlay::ZoomLabelOverlay(Item* itemWithLabel, const StyleType* style) : Super{{itemWithLabel}, style}
{
	Q_ASSERT(itemWithLabel->node());
	Q_ASSERT(itemWithLabel->node()->definesSymbol());
	iconStyle_ = associatedItemIconStyle();
	itemToOverlay().insert(itemWithLabel, this);
}

void ZoomLabelOverlay::determineChildren()
{
	Super::determineChildren();
	text_->setText(associatedItemText());
}

void ZoomLabelOverlay::updateGeometry(int availableWidth, int availableHeight)
{
	Super::updateGeometry(availableWidth, availableHeight);

	setPos(associatedItem()->scenePos());

	auto maxScale = 1/mainViewScalingFactor();
	auto widthScale = associatedItem()->widthInScene() / (double) widthInLocal();
	auto heightScale = associatedItem()->heightInScene() / (double) heightInLocal();
	auto scaleToUse = maxScale;
	if (widthScale < scaleToUse) scaleToUse = widthScale;
	if (heightScale < scaleToUse) scaleToUse = heightScale;

	setScale(scaleToUse);
}

bool ZoomLabelOverlay::isSensitiveToScale() const
{
	return true;
}

int ZoomLabelOverlay::determineForm()
{
	return iconStyle_ ? 1 : 0;
}

void ZoomLabelOverlay::initializeForms()
{
	addForm(item<Text>(&I::text_, [](I* v){return v->associatedItemTextStyle();}));

	addForm(grid({{item<Static>(&I::icon_, [](I* v){ return v->iconStyle_;}),
		item<Text>(&I::text_, [](I* v){return v->associatedItemTextStyle();})}})
			  ->setVerticalAlignment(LayoutStyle::Alignment::Center));
}

const StaticStyle* ZoomLabelOverlay::associatedItemIconStyle() const
{
	const StaticStyle* iconStyle{};
	for (auto child : associatedItem()->childItems())
	{
		if ( auto childStaticStyle = dynamic_cast<const StaticStyle*>(child->style()) )
			if (dynamic_cast<const IconStyle*> (&childStaticStyle->itemStyle()))
		{
			if (!iconStyle) iconStyle = childStaticStyle;
			else return nullptr; // We found at least 2 icons => ambiguous
		}

	}

	return iconStyle; // Could be nullptr to indicate no icon;
}

const QString& ZoomLabelOverlay::associatedItemText() const
{
	return associatedItem()->node()->symbolName();
}

const TextStyle* ZoomLabelOverlay::associatedItemTextStyle() const
{
	const TextStyle* textStyle{};
	for (auto child : associatedItem()->childItems())
		if ( auto textChild = DCast<TextRenderer>(child) )
		{
			if (textChild->text() == associatedItemText())
			{
				if (!textStyle) textStyle = textChild->style();
				else
				{
					//we have found more than one text item representing the same string, ambiguous
					textStyle = nullptr;
					break;
				}
			}
		}

	return textStyle ? textStyle : Text::itemStyles().get();
}

QList<Item*> ZoomLabelOverlay::itemsThatShouldHaveZoomLabel(Scene* scene)
{
	QList<Item*> result;

	const double OVERLAY_SCALE_TRESHOLD = 0.5;
	auto scalingFactor = scene->mainViewScalingFactor();

	if (scalingFactor >= OVERLAY_SCALE_TRESHOLD)
	{
		itemToOverlay().clear();
		return result;
	}

	View* mainView{};
	for (auto view : scene->views())
		if (auto mv = dynamic_cast<MainView*>(view))
		{
			mainView = mv;
			break;
		}

	QList<Item*> stack = scene->topLevelItems();
	while (!stack.isEmpty())
	{
		auto item = stack.takeLast();

		auto scaledWidth = item->widthInParent() * scalingFactor;
		auto scaledHeight = item->heightInParent() * scalingFactor;
		if (scaledWidth < OVERLAY_MIN_WIDTH || scaledHeight < OVERLAY_MIN_HEIGHT) continue; // Do not explore children
		if (!mainView->visibleRect().intersects(item->sceneBoundingRect())) continue; // Do not explore children

		stack.append(item->childItems());

		bool definesSymbol = !DCast<RootItem>(item) && item->node() && item->node()->definesSymbol();
		if (definesSymbol) result.append(item);
	}

	return result;
}

void ZoomLabelOverlay::setItemPositionsAndHideOverlapped(OverlayGroup& group)
{
	static int postUpdateRevision{};
	++postUpdateRevision;

	for (auto accessor : group.overlays())
		static_cast<ZoomLabelOverlay*>(accessor->overlayItem())->postUpdate(postUpdateRevision);
}

void ZoomLabelOverlay::postUpdate(int revision)
{
	// If already updated, do nothing
	if (postUpdateRevision_ == revision) return;
	postUpdateRevision_ = revision;

	// Make sure all overlays above this one are updated
	auto item = associatedItem()->parent();
	while (item)
	{
		auto overlayIt = itemToOverlay().find(item);
		if (overlayIt != itemToOverlay().end())
		{
			overlayIt.value()->postUpdate(revision);
			break;
		}

		item = item->parent();
	}

	// Finally adjust the position of this overlay so that it does not overlap or if that's impossible, hide it.
	adjustPositionOrHide();
}

inline void ZoomLabelOverlay::reduceRect(QRect& rectToReduce, const QRect& rectToExclude)
{
	QRect intersected = rectToReduce.intersected(rectToExclude);
	if (intersected.isEmpty()) return; // No intersection

	// Now we will grow the intersected rect until it has at least three sides equal to the sides of rectToReduce
	// Then we'll just take what's left

	// Make sure only one of top/bottom is in the middle
	int distanceToTop = intersected.top() - rectToReduce.top();
	int distanceToBottom = rectToReduce.bottom() - intersected.bottom();
	if (distanceToTop > distanceToBottom) intersected.setBottom(rectToReduce.bottom());
	else intersected.setTop(rectToReduce.top());

	Q_ASSERT(rectToReduce.top() == intersected.top() || rectToReduce.bottom() == intersected.bottom());

	// Make sure only one of left/right is in the middle
	int distanceToLeft = intersected.left() - rectToReduce.left();
	int distanceToRight = rectToReduce.right() - intersected.right();
	if (distanceToLeft > distanceToRight) intersected.setRight(rectToReduce.right());
	else intersected.setLeft(rectToReduce.left());

	Q_ASSERT(rectToReduce.left() == intersected.left() || rectToReduce.right() == intersected.right());

	// At this point we might still have an intersecting rect in a corner. In that case take away the chunk that has
	// the smaller area.
	int horizontalArea = intersected.height()* rectToReduce.width();
	int verticalArea = intersected.width()* rectToReduce.height();
	if (horizontalArea < verticalArea)
	{
		intersected.setLeft( rectToReduce.left() );
		intersected.setRight( rectToReduce.right() );
	}
	else
	{
		intersected.setTop( rectToReduce.top() );
		intersected.setBottom( rectToReduce.bottom() );
	}

	Q_ASSERT( (rectToReduce.top() == intersected.top() && rectToReduce.bottom() == intersected.bottom()) ||
				 (rectToReduce.left() == intersected.left() && rectToReduce.right() == intersected.right()));

	// At this point we can just do rectToReduce = rectToReduce - intersected
	if (rectToReduce.top() != intersected.top()) rectToReduce.setBottom(intersected.top());
	else if (rectToReduce.bottom() != intersected.bottom()) rectToReduce.setTop(intersected.bottom()+1);
	else if (rectToReduce.left() != intersected.left()) rectToReduce.setRight(intersected.left());
	else if (rectToReduce.right() != intersected.right()) rectToReduce.setLeft(intersected.right()+1);
	else // complete overlap
	{
		rectToReduce.setWidth(0);
		rectToReduce.setHeight(0);
	}
}

void ZoomLabelOverlay::adjustPositionOrHide()
{
	auto availableRect = associatedItem()->sceneBoundingRect().toRect();

	auto item = associatedItem()->parent();
	while (item)
	{
		auto overlayIt = itemToOverlay().find(item);
		if (overlayIt != itemToOverlay().end() && overlayIt.value()->isVisible())
			reduceRect(availableRect, overlayIt.value()->sceneBoundingRect().toRect());

		item = item->parent();
	}

	// At this point we know in what amount of space we're supposed to fit.

	// If the space is too small don't bother trying to compute a scale
	bool visible = true;
	auto scalingFactor = scene()->mainViewScalingFactor();
	if (availableRect.width() * scalingFactor < OVERLAY_MIN_WIDTH
			|| availableRect.height() * scalingFactor < OVERLAY_MIN_HEIGHT) visible = false;

	// If there might be enough space, then try to fit in
	if (visible)
	{
		setPos(availableRect.topLeft());

		auto maxScale = 1/scalingFactor;
		auto widthScale = availableRect.width() / (double) widthInLocal();
		auto heightScale = availableRect.height() / (double) heightInLocal();
		auto scaleToUse = maxScale;
		if (widthScale < scaleToUse) scaleToUse = widthScale;
		if (heightScale < scaleToUse) scaleToUse = heightScale;

		setScale(scaleToUse);
	}

	if (visible != isVisible()) setVisible(visible);
}

} /* namespace Visualization */
<|endoftext|>


<commit_before><commit_msg>Added PBRMaterial defines<commit_after><|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id */

// Macro for loading libraries needed for dealing with calibration data containers
// Laurent Aphecetche

void loadlibcalib ()
{
  gSystem->Load("libVMC");
  gSystem->Load("libMinuit");
  gSystem->Load("libTree");

  gSystem->Load("libESD");
  gSystem->Load("libSTEER");

  gSystem->Load("libPhysics");

  gSystem->Load("libMUONmapping");
  gSystem->Load("libMUONcalib");

}
<commit_msg>Changed libraries from Root to more basic ones<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id */

// Macro for loading libraries needed for dealing with calibration data containers
// Laurent Aphecetche

void loadlibcalib ()
{
  gSystem->Load("libMatrix");
  gSystem->Load("libTree");
  gSystem->Load("libGeom");
  gSystem->Load("libESD");

  gSystem->Load("libGui");
  gSystem->Load("libPhysics");
  gSystem->Load("libMUONmapping");
  gSystem->Load("libMUONcalib");
}
<|endoftext|>


<commit_before>#include "building_configure.hpp"
#include <silicium/file_operations.hpp>
#include <silicium/cmake.hpp>
#include <fstream>

namespace cdm
{
	void build_configure_command_line(
		Si::absolute_path const &application_source,
		Si::absolute_path const &temporary,
		Si::absolute_path const &resulting_executable,
		Si::Sink<char, Si::success>::interface &output)
	{
		Si::absolute_path const cdm = Si::parent(
			Si::parent(*Si::absolute_path::create(__FILE__)).or_throw(
				[]{ throw std::runtime_error("Could not find parent directory of this file: " __FILE__); }
			)
		).or_throw(
			[]{ throw std::runtime_error("Could not find the cdm directory"); }
		);
		Si::absolute_path const original_main_cpp = cdm / Si::relative_path("configure_cmdline/main.cpp");
		Si::absolute_path const source = temporary / Si::relative_path("source");
		Si::recreate_directories(source, Si::throw_);
		Si::absolute_path const copied_main_cpp = source / Si::relative_path("main.cpp");
		Si::copy(original_main_cpp, copied_main_cpp, Si::throw_);
		{
			Si::absolute_path const cmakeLists = source / Si::relative_path("CMakeLists.txt");
			std::ofstream cmakeListsFile(cmakeLists.c_str());
			cmakeListsFile << "cmake_minimum_required(VERSION 2.8)\n";
			cmakeListsFile << "project(configure_cmdline_generated)\n";
			cmakeListsFile << "if(UNIX)\n";
			cmakeListsFile << "	add_definitions(-std=c++1y)\n";
			cmakeListsFile << "endif()\n";
			cmakeListsFile << "find_package(Boost REQUIRED filesystem coroutine program_options system)\n";
			cmakeListsFile << "include_directories(${SILICIUM_INCLUDE_DIR} ${BOOST_INCLUDE_DIR} ${CDM_CONFIGURE_INCLUDE_DIRS})\n";
			cmakeListsFile << "add_executable(configure main.cpp)\n";
			cmakeListsFile << "target_link_libraries(configure ${Boost_LIBRARIES})\n";
			if (!cmakeListsFile)
			{
				throw std::runtime_error(("Could not generate " + Si::to_utf8_string(cmakeLists)).c_str());
			}
		}
		Si::absolute_path const build = temporary / Si::relative_path("build");
		Si::recreate_directories(build, Si::throw_);
		{
			std::vector<Si::os_string> arguments;
			{
				Si::absolute_path const silicium = Si::parent(cdm).or_throw([] { throw std::runtime_error("Could not find the silicium directory"); });
				arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-DSILICIUM_INCLUDE_DIR=") + Si::to_os_string(silicium));
			}
			Si::absolute_path const modules = cdm / Si::relative_path("modules");
			arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-DCDM_CONFIGURE_INCLUDE_DIRS=") + Si::to_os_string(application_source) + SILICIUM_SYSTEM_LITERAL(";") + Si::to_os_string(modules));
			arguments.emplace_back(Si::to_os_string(source));
			if (Si::run_process(Si::cmake_exe, arguments, build, output).get() != 0)
			{
				throw std::runtime_error("Could not CMake-configure the cdm configure executable");
			}
		}
		{
			std::vector<Si::os_string> arguments;
			arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("--build"));
			arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("."));
			if (Si::run_process(Si::cmake_exe, arguments, build, output).get() != 0)
			{
				throw std::runtime_error("Could not CMake --build the cdm configure executable");
			}
		}
		Si::absolute_path const built_executable = build / Si::relative_path("configure");
		Si::copy(built_executable, resulting_executable, Si::throw_);
	}

	void run_configure_command_line(
		Si::absolute_path const &configure_executable,
		Si::absolute_path const &module_permanent,
		Si::absolute_path const &application_source,
		Si::absolute_path const &application_build_dir,
		Si::Sink<char, Si::success>::interface &output)
	{
		std::vector<Si::os_string> arguments;
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-m"));
		arguments.emplace_back(Si::to_os_string(module_permanent));
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-a"));
		arguments.emplace_back(Si::to_os_string(application_source));
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-b"));
		arguments.emplace_back(Si::to_os_string(application_build_dir));
		int const rc = Si::run_process(configure_executable, arguments, application_build_dir, output).get();
		if (rc != 0)
		{
			throw std::runtime_error("Could not configure the application: " + boost::lexical_cast<std::string>(rc));
		}
	}
}
<commit_msg>link against Boost.Context, too<commit_after>#include "building_configure.hpp"
#include <silicium/file_operations.hpp>
#include <silicium/cmake.hpp>
#include <fstream>

namespace cdm
{
	void build_configure_command_line(
		Si::absolute_path const &application_source,
		Si::absolute_path const &temporary,
		Si::absolute_path const &resulting_executable,
		Si::Sink<char, Si::success>::interface &output)
	{
		Si::absolute_path const cdm = Si::parent(
			Si::parent(*Si::absolute_path::create(__FILE__)).or_throw(
				[]{ throw std::runtime_error("Could not find parent directory of this file: " __FILE__); }
			)
		).or_throw(
			[]{ throw std::runtime_error("Could not find the cdm directory"); }
		);
		Si::absolute_path const original_main_cpp = cdm / Si::relative_path("configure_cmdline/main.cpp");
		Si::absolute_path const source = temporary / Si::relative_path("source");
		Si::recreate_directories(source, Si::throw_);
		Si::absolute_path const copied_main_cpp = source / Si::relative_path("main.cpp");
		Si::copy(original_main_cpp, copied_main_cpp, Si::throw_);
		{
			Si::absolute_path const cmakeLists = source / Si::relative_path("CMakeLists.txt");
			std::ofstream cmakeListsFile(cmakeLists.c_str());
			cmakeListsFile << "cmake_minimum_required(VERSION 2.8)\n";
			cmakeListsFile << "project(configure_cmdline_generated)\n";
			cmakeListsFile << "if(UNIX)\n";
			cmakeListsFile << "	add_definitions(-std=c++1y)\n";
			cmakeListsFile << "endif()\n";
			cmakeListsFile << "find_package(Boost REQUIRED filesystem coroutine program_options context system)\n";
			cmakeListsFile << "include_directories(${SILICIUM_INCLUDE_DIR} ${BOOST_INCLUDE_DIR} ${CDM_CONFIGURE_INCLUDE_DIRS})\n";
			cmakeListsFile << "add_executable(configure main.cpp)\n";
			cmakeListsFile << "target_link_libraries(configure ${Boost_LIBRARIES})\n";
			if (!cmakeListsFile)
			{
				throw std::runtime_error(("Could not generate " + Si::to_utf8_string(cmakeLists)).c_str());
			}
		}
		Si::absolute_path const build = temporary / Si::relative_path("build");
		Si::recreate_directories(build, Si::throw_);
		{
			std::vector<Si::os_string> arguments;
			{
				Si::absolute_path const silicium = Si::parent(cdm).or_throw([] { throw std::runtime_error("Could not find the silicium directory"); });
				arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-DSILICIUM_INCLUDE_DIR=") + Si::to_os_string(silicium));
			}
			Si::absolute_path const modules = cdm / Si::relative_path("modules");
			arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-DCDM_CONFIGURE_INCLUDE_DIRS=") + Si::to_os_string(application_source) + SILICIUM_SYSTEM_LITERAL(";") + Si::to_os_string(modules));
			arguments.emplace_back(Si::to_os_string(source));
			if (Si::run_process(Si::cmake_exe, arguments, build, output).get() != 0)
			{
				throw std::runtime_error("Could not CMake-configure the cdm configure executable");
			}
		}
		{
			std::vector<Si::os_string> arguments;
			arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("--build"));
			arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("."));
			if (Si::run_process(Si::cmake_exe, arguments, build, output).get() != 0)
			{
				throw std::runtime_error("Could not CMake --build the cdm configure executable");
			}
		}
		Si::absolute_path const built_executable = build / Si::relative_path("configure");
		Si::copy(built_executable, resulting_executable, Si::throw_);
	}

	void run_configure_command_line(
		Si::absolute_path const &configure_executable,
		Si::absolute_path const &module_permanent,
		Si::absolute_path const &application_source,
		Si::absolute_path const &application_build_dir,
		Si::Sink<char, Si::success>::interface &output)
	{
		std::vector<Si::os_string> arguments;
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-m"));
		arguments.emplace_back(Si::to_os_string(module_permanent));
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-a"));
		arguments.emplace_back(Si::to_os_string(application_source));
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-b"));
		arguments.emplace_back(Si::to_os_string(application_build_dir));
		int const rc = Si::run_process(configure_executable, arguments, application_build_dir, output).get();
		if (rc != 0)
		{
			throw std::runtime_error("Could not configure the application: " + boost::lexical_cast<std::string>(rc));
		}
	}
}
<|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/chromeos/usb_mount_observer.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/dom_ui/filebrowse_ui.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"

namespace chromeos {

const char* kFilebrowseURLHash = "chrome://filebrowse#";
const char* kFilebrowseScanning = "scanningdevice";
const int kPopupLeft = 0;
const int kPopupTop = 0;
const int kPopupWidth = 250;
const int kPopupHeight = 300;

void USBMountObserver::Observe(NotificationType type,
                               const NotificationSource& source,
                               const NotificationDetails& details) {
  DCHECK(type == NotificationType::BROWSER_CLOSED);
  for (BrowserIterator i = browsers_.begin(); i != browsers_.end();
       ++i) {
    if (Source<Browser>(source).ptr() == i->browser) {
      i->browser = NULL;
      registrar_.Remove(this,
                        NotificationType::BROWSER_CLOSED,
                        source);
      return;
    }
  }
}

void USBMountObserver::OpenFileBrowse(const std::string& url,
                                      const std::string& device_path,
                                      bool small) {
  Browser* browser;
  Profile* profile;
  profile = BrowserList::GetLastActive()->profile();
  if (small) {
    browser = FileBrowseUI::OpenPopup(profile,
                                      url,
                                      FileBrowseUI::kSmallPopupWidth,
                                      FileBrowseUI::kSmallPopupHeight);
  } else {
    browser = FileBrowseUI::OpenPopup(profile,
                                      url,
                                      FileBrowseUI::kPopupWidth,
                                      FileBrowseUI::kPopupHeight);
  }
  registrar_.Add(this,
                 NotificationType::BROWSER_CLOSED,
                 Source<Browser>(browser));
  BrowserIterator iter = FindBrowserForPath(device_path);
  if (iter == browsers_.end()) {
    BrowserWithPath new_browser;
    new_browser.browser = browser;
    new_browser.device_path = device_path;
    browsers_.push_back(new_browser);
  } else {
    iter->browser = browser;
  }
}

void USBMountObserver::MountChanged(chromeos::MountLibrary* obj,
                                    chromeos::MountEventType evt,
                                    const std::string& path) {
  if (evt == chromeos::DISK_ADDED) {
    const chromeos::MountLibrary::DiskVector& disks = obj->disks();
    for (size_t i = 0; i < disks.size(); ++i) {
      chromeos::MountLibrary::Disk disk = disks[i];
      if (disk.device_path == path) {
        if (disk.is_parent) {
          if (!disk.has_media) {
            RemoveBrowserFromVector(disk.system_path);
          }
        } else if (!obj->MountPath(path.c_str())) {
          RemoveBrowserFromVector(disk.system_path);
        }
      }
    }
    LOG(INFO) << "Got added mount:" << path;
  } else if (evt == chromeos::DISK_REMOVED ||
             evt == chromeos::DEVICE_REMOVED) {
    RemoveBrowserFromVector(path);
  } else if (evt == chromeos::DISK_CHANGED) {
    BrowserIterator iter = FindBrowserForPath(path);
    LOG(INFO) << "Got changed mount:" << path;
    if (iter == browsers_.end() && iter->browser) {
      // We don't currently have this one, so it must have been
      // mounted
      const chromeos::MountLibrary::DiskVector& disks = obj->disks();
      for (size_t i = 0; i < disks.size(); ++i) {
        if (disks[i].device_path == path) {
          if (!disks[i].mount_path.empty()) {
            // Doing second search to see if the current disk has already
            // been popped up due to its parent device being plugged in.
            iter = FindBrowserForPath(disks[i].system_path);
            if (iter != browsers_.end() && iter->browser) {
              std::string url = kFilebrowseURLHash;
              url += disks[i].mount_path;
              TabContents* tab = iter->browser->GetSelectedTabContents();
              iter->browser->window()->SetBounds(gfx::Rect(
                  0, 0, FileBrowseUI::kPopupWidth, FileBrowseUI::kPopupHeight));
              tab->OpenURL(GURL(url), GURL(), CURRENT_TAB,
                  PageTransition::LINK);
              tab->NavigateToPendingEntry(NavigationController::RELOAD);
              iter->device_path = path;
            } else {
              OpenFileBrowse(disks[i].mount_path, disks[i].device_path, false);
            }
          }
          return;
        }
      }
    }
  } else if (evt == chromeos::DEVICE_ADDED) {
    LOG(INFO) << "Got device added" << path;
    OpenFileBrowse(kFilebrowseScanning, path, true);
  } else if (evt == chromeos::DEVICE_SCANNED) {
    LOG(INFO) << "Got device scanned:" << path;
  }
}

USBMountObserver::BrowserIterator USBMountObserver::FindBrowserForPath(
    const std::string& path) {
  for (BrowserIterator i = browsers_.begin();i != browsers_.end();
       ++i) {
    // Doing a substring match so that we find if this new one is a subdevice
    // of another already inserted device.
    if (path.find(i->device_path) != std::string::npos) {
      return i;
    }
  }
  return browsers_.end();
}

void USBMountObserver::RemoveBrowserFromVector(const std::string& path) {
  BrowserIterator i = FindBrowserForPath(path);
  std::string mount_path;
  if (i != browsers_.end()) {
    registrar_.Remove(this,
                      NotificationType::BROWSER_CLOSED,
                      Source<Browser>(i->browser));
    mount_path = i->mount_path;
    browsers_.erase(i);
  }
  std::vector<Browser*> close_these;
  for (BrowserList::const_iterator it = BrowserList::begin();
       it != BrowserList::end(); ++it) {
    if ((*it)->type() == Browser::TYPE_POPUP) {
      if (*it && (*it)->GetTabContentsAt((*it)->selected_index())) {
        const GURL& url =
            (*it)->GetTabContentsAt((*it)->selected_index())->GetURL();
        if (url.SchemeIs(chrome::kChromeUIScheme) &&
            url.host() == chrome::kChromeUIFileBrowseHost &&
            url.ref().find(mount_path) != std::string::npos) {
          close_these.push_back(*it);
        }
      }
    }
  }
  for (size_t x = 0; x < close_these.size(); x++) {
    if (close_these[x]->window()) {
      close_these[x]->window()->Close();
    }
  }
}

} // namespace chromeos
<commit_msg>Fixing mounting case.<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/chromeos/usb_mount_observer.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/dom_ui/filebrowse_ui.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"

namespace chromeos {

const char* kFilebrowseURLHash = "chrome://filebrowse#";
const char* kFilebrowseScanning = "scanningdevice";
const int kPopupLeft = 0;
const int kPopupTop = 0;
const int kPopupWidth = 250;
const int kPopupHeight = 300;

void USBMountObserver::Observe(NotificationType type,
                               const NotificationSource& source,
                               const NotificationDetails& details) {
  DCHECK(type == NotificationType::BROWSER_CLOSED);
  for (BrowserIterator i = browsers_.begin(); i != browsers_.end();
       ++i) {
    if (Source<Browser>(source).ptr() == i->browser) {
      i->browser = NULL;
      registrar_.Remove(this,
                        NotificationType::BROWSER_CLOSED,
                        source);
      return;
    }
  }
}

void USBMountObserver::OpenFileBrowse(const std::string& url,
                                      const std::string& device_path,
                                      bool small) {
  Browser* browser;
  Profile* profile;
  profile = BrowserList::GetLastActive()->profile();
  if (small) {
    browser = FileBrowseUI::OpenPopup(profile,
                                      url,
                                      FileBrowseUI::kSmallPopupWidth,
                                      FileBrowseUI::kSmallPopupHeight);
  } else {
    browser = FileBrowseUI::OpenPopup(profile,
                                      url,
                                      FileBrowseUI::kPopupWidth,
                                      FileBrowseUI::kPopupHeight);
  }
  registrar_.Add(this,
                 NotificationType::BROWSER_CLOSED,
                 Source<Browser>(browser));
  BrowserIterator iter = FindBrowserForPath(device_path);
  if (iter == browsers_.end()) {
    BrowserWithPath new_browser;
    new_browser.browser = browser;
    new_browser.device_path = device_path;
    browsers_.push_back(new_browser);
  } else {
    iter->browser = browser;
  }
}

void USBMountObserver::MountChanged(chromeos::MountLibrary* obj,
                                    chromeos::MountEventType evt,
                                    const std::string& path) {
  if (evt == chromeos::DISK_ADDED) {
    const chromeos::MountLibrary::DiskVector& disks = obj->disks();
    for (size_t i = 0; i < disks.size(); ++i) {
      chromeos::MountLibrary::Disk disk = disks[i];
      if (disk.device_path == path) {
        if (disk.is_parent) {
          if (!disk.has_media) {
            RemoveBrowserFromVector(disk.system_path);
          }
        } else if (!obj->MountPath(path.c_str())) {
          RemoveBrowserFromVector(disk.system_path);
        }
      }
    }
    LOG(INFO) << "Got added mount:" << path;
  } else if (evt == chromeos::DISK_REMOVED ||
             evt == chromeos::DEVICE_REMOVED) {
    RemoveBrowserFromVector(path);
  } else if (evt == chromeos::DISK_CHANGED) {
    BrowserIterator iter = FindBrowserForPath(path);
    LOG(INFO) << "Got changed mount:" << path;
    if (iter == browsers_.end()) {
      // We don't currently have this one, so it must have been
      // mounted
      const chromeos::MountLibrary::DiskVector& disks = obj->disks();
      for (size_t i = 0; i < disks.size(); ++i) {
        if (disks[i].device_path == path) {
          if (!disks[i].mount_path.empty()) {
            // Doing second search to see if the current disk has already
            // been popped up due to its parent device being plugged in.
            iter = FindBrowserForPath(disks[i].system_path);
            if (iter != browsers_.end() && iter->browser) {
              std::string url = kFilebrowseURLHash;
              url += disks[i].mount_path;
              TabContents* tab = iter->browser->GetSelectedTabContents();
              iter->browser->window()->SetBounds(gfx::Rect(
                  0, 0, FileBrowseUI::kPopupWidth, FileBrowseUI::kPopupHeight));
              tab->OpenURL(GURL(url), GURL(), CURRENT_TAB,
                  PageTransition::LINK);
              tab->NavigateToPendingEntry(NavigationController::RELOAD);
              iter->device_path = path;
            } else {
              OpenFileBrowse(disks[i].mount_path, disks[i].device_path, false);
            }
          }
          return;
        }
      }
    }
  } else if (evt == chromeos::DEVICE_ADDED) {
    LOG(INFO) << "Got device added" << path;
    OpenFileBrowse(kFilebrowseScanning, path, true);
  } else if (evt == chromeos::DEVICE_SCANNED) {
    LOG(INFO) << "Got device scanned:" << path;
  }
}

USBMountObserver::BrowserIterator USBMountObserver::FindBrowserForPath(
    const std::string& path) {
  for (BrowserIterator i = browsers_.begin();i != browsers_.end();
       ++i) {
    // Doing a substring match so that we find if this new one is a subdevice
    // of another already inserted device.
    if (path.find(i->device_path) != std::string::npos) {
      return i;
    }
  }
  return browsers_.end();
}

void USBMountObserver::RemoveBrowserFromVector(const std::string& path) {
  BrowserIterator i = FindBrowserForPath(path);
  std::string mount_path;
  if (i != browsers_.end()) {
    registrar_.Remove(this,
                      NotificationType::BROWSER_CLOSED,
                      Source<Browser>(i->browser));
    mount_path = i->mount_path;
    browsers_.erase(i);
  }
  std::vector<Browser*> close_these;
  for (BrowserList::const_iterator it = BrowserList::begin();
       it != BrowserList::end(); ++it) {
    if ((*it)->type() == Browser::TYPE_POPUP) {
      if (*it && (*it)->GetTabContentsAt((*it)->selected_index())) {
        const GURL& url =
            (*it)->GetTabContentsAt((*it)->selected_index())->GetURL();
        if (url.SchemeIs(chrome::kChromeUIScheme) &&
            url.host() == chrome::kChromeUIFileBrowseHost &&
            url.ref().find(mount_path) != std::string::npos) {
          close_these.push_back(*it);
        }
      }
    }
  }
  for (size_t x = 0; x < close_these.size(); x++) {
    if (close_these[x]->window()) {
      close_these[x]->window()->Close();
    }
  }
}

} // namespace chromeos
<|endoftext|>


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

#include <vector>

#include "base/message_loop.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "googleurl/src/gurl.h"

namespace {

// Note: WaitableEvent is not used for synchronization between the main thread
// and history backend thread because the history subsystem posts tasks back
// to the main thread. Had we tried to Signal an event in such a task
// and Wait for it on the main thread, the task would not run at all because
// the main thread would be blocked on the Wait call, resulting in a deadlock.

// A task to be scheduled on the history backend thread.
// Notifies the main thread after all history backend thread tasks have run.
class WaitForHistoryTask : public HistoryDBTask {
 public:
  WaitForHistoryTask() {
  }

  virtual bool RunOnDBThread(history::HistoryBackend* backend,
                             history::HistoryDatabase* db) {
    return true;
  }

  virtual void DoneRunOnMainThread() {
    MessageLoop::current()->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
};

// Enumerates all history contents on the backend thread.
class HistoryEnumerator : public HistoryService::URLEnumerator {
 public:
  explicit HistoryEnumerator(HistoryService* history) {
    EXPECT_TRUE(history);
    if (!history)
      return;

    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        NewRunnableMethod(history, &HistoryService::IterateURLs, this));
    ui_test_utils::RunMessageLoop();
  }

  virtual void OnURL(const GURL& url) {
    urls_.push_back(url);
  }

  virtual void OnComplete(bool success) {
    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        new MessageLoop::QuitTask());
  }

  std::vector<GURL>& urls() { return urls_; }

 private:
  std::vector<GURL> urls_;

  DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator);
};

class HistoryBrowserTest : public InProcessBrowserTest {
 protected:
  PrefService* GetPrefs() {
    return GetProfile()->GetPrefs();
  }

  Profile* GetProfile() {
    return browser()->GetProfile();
  }

  HistoryService* GetHistoryService() {
    return GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
  }

  std::vector<GURL> GetHistoryContents() {
    HistoryEnumerator enumerator(GetHistoryService());
    return enumerator.urls();
  }

  GURL GetTestUrl() {
    return ui_test_utils::GetTestUrl(
        FilePath(FilePath::kCurrentDirectory),
        FilePath(FILE_PATH_LITERAL("title2.html")));
  }

  void WaitForHistoryBackendToRun() {
    CancelableRequestConsumerTSimple<int> request_consumer;
    scoped_refptr<HistoryDBTask> task(new WaitForHistoryTask());
    HistoryService* history = GetHistoryService();
    BrowserThread::PostTask(BrowserThread::UI,
                            FROM_HERE,
                            NewRunnableMethod(history,
                                              &HistoryService::ScheduleDBTask,
                                              task,
                                              &request_consumer));
    ui_test_utils::RunMessageLoop();
  }

  void ExpectEmptyHistory() {
    std::vector<GURL> urls(GetHistoryContents());
    EXPECT_EQ(0U, urls.size());
  }
};

// Test that the browser history is saved (default setting).
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabled) {
  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Times out on Vista only.  http://crbug.com/57994
#if defined(OS_WIN)
#define MAYBE_SavingHistoryDisabled DISABLED_SavingHistoryDisabled
#else
#define MAYBE_SavingHistoryDisabled SavingHistoryDisabled
#endif

// Test that disabling saving browser history really works.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, MAYBE_SavingHistoryDisabled) {
  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_FALSE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();
  ExpectEmptyHistory();
}

// Times out on Vista only.  http://crbug.com/57994
#if defined(OS_WIN)
#define MAYBE_SavingHistoryEnabledThenDisabled \
    DISABLED_SavingHistoryEnabledThenDisabled
#else
#define MAYBE_SavingHistoryEnabledThenDisabled SavingHistoryEnabledThenDisabled
#endif

// Test that changing the pref takes effect immediately
// when the browser is running.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,
    MAYBE_SavingHistoryEnabledThenDisabled) {
  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  ui_test_utils::WaitForHistoryToLoad(browser());

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    // No additional entries should be present in the history.
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Test that changing the pref takes effect immediately
// when the browser is running.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabledThenEnabled) {
  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();
  ExpectEmptyHistory();

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, false);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

}  // namespace
<commit_msg>Re-enable HistoryBrowserTest.SavingHistoryDisabled and SavingHistoryDisabledThenEnabled<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "base/message_loop.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "googleurl/src/gurl.h"

namespace {

// Helper to debug intermittent test hangs/timeouts.
// TODO(phajdan.jr): remove when http://crbug.com/57994 is fixed.
void Checkpoint(const char* message, const base::TimeTicks& start_time) {
  LOG(INFO) << message << " : "
            << (base::TimeTicks::Now() - start_time).InMilliseconds()
            << " ms" << std::flush;
}

// Note: WaitableEvent is not used for synchronization between the main thread
// and history backend thread because the history subsystem posts tasks back
// to the main thread. Had we tried to Signal an event in such a task
// and Wait for it on the main thread, the task would not run at all because
// the main thread would be blocked on the Wait call, resulting in a deadlock.

// A task to be scheduled on the history backend thread.
// Notifies the main thread after all history backend thread tasks have run.
class WaitForHistoryTask : public HistoryDBTask {
 public:
  WaitForHistoryTask() {
  }

  virtual bool RunOnDBThread(history::HistoryBackend* backend,
                             history::HistoryDatabase* db) {
    return true;
  }

  virtual void DoneRunOnMainThread() {
    MessageLoop::current()->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
};

// Enumerates all history contents on the backend thread.
class HistoryEnumerator : public HistoryService::URLEnumerator {
 public:
  explicit HistoryEnumerator(HistoryService* history) {
    EXPECT_TRUE(history);
    if (!history)
      return;

    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        NewRunnableMethod(history, &HistoryService::IterateURLs, this));
    ui_test_utils::RunMessageLoop();
  }

  virtual void OnURL(const GURL& url) {
    urls_.push_back(url);
  }

  virtual void OnComplete(bool success) {
    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        new MessageLoop::QuitTask());
  }

  std::vector<GURL>& urls() { return urls_; }

 private:
  std::vector<GURL> urls_;

  DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator);
};

class HistoryBrowserTest : public InProcessBrowserTest {
 protected:
  PrefService* GetPrefs() {
    return GetProfile()->GetPrefs();
  }

  Profile* GetProfile() {
    return browser()->GetProfile();
  }

  HistoryService* GetHistoryService() {
    return GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
  }

  std::vector<GURL> GetHistoryContents() {
    HistoryEnumerator enumerator(GetHistoryService());
    return enumerator.urls();
  }

  GURL GetTestUrl() {
    return ui_test_utils::GetTestUrl(
        FilePath(FilePath::kCurrentDirectory),
        FilePath(FILE_PATH_LITERAL("title2.html")));
  }

  void WaitForHistoryBackendToRun() {
    CancelableRequestConsumerTSimple<int> request_consumer;
    scoped_refptr<HistoryDBTask> task(new WaitForHistoryTask());
    HistoryService* history = GetHistoryService();
    BrowserThread::PostTask(BrowserThread::UI,
                            FROM_HERE,
                            NewRunnableMethod(history,
                                              &HistoryService::ScheduleDBTask,
                                              task,
                                              &request_consumer));
    ui_test_utils::RunMessageLoop();
  }

  void ExpectEmptyHistory() {
    std::vector<GURL> urls(GetHistoryContents());
    EXPECT_EQ(0U, urls.size());
  }
};

// Test that the browser history is saved (default setting).
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabled) {
  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Test that disabling saving browser history really works.
// TODO(phajdan.jr): remove debug code when http://crbug.com/57994 is fixed.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabled) {
  base::TimeTicks start_time = base::TimeTicks::Now();

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_FALSE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  Checkpoint("Before waiting for history to load", start_time);
  ui_test_utils::WaitForHistoryToLoad(browser());
  Checkpoint("After waiting for history to load", start_time);
  ExpectEmptyHistory();
  Checkpoint("After checking history", start_time);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  Checkpoint("After NavigateToURL", start_time);
  WaitForHistoryBackendToRun();
  Checkpoint("After waiting for history backend to run", start_time);
  ExpectEmptyHistory();
  Checkpoint("After second check", start_time);
}

// Test that changing the pref takes effect immediately
// when the browser is running.
// TODO(phajdan.jr): remove debug code when http://crbug.com/57994 is fixed.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabledThenDisabled) {
  base::TimeTicks start_time = base::TimeTicks::Now();

  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  Checkpoint("Before waiting for history to load", start_time);
  ui_test_utils::WaitForHistoryToLoad(browser());
  Checkpoint("After waiting for history to load", start_time);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  Checkpoint("After first NavigateToURL", start_time);
  WaitForHistoryBackendToRun();
  Checkpoint("After waiting for history backend to run", start_time);

  {
    std::vector<GURL> urls(GetHistoryContents());
    Checkpoint("After first GetHistoryContents", start_time);
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  Checkpoint("After second NavigateToURL", start_time);
  WaitForHistoryBackendToRun();
  Checkpoint("After waiting for history backend to run (2nd time)", start_time);

  {
    // No additional entries should be present in the history.
    std::vector<GURL> urls(GetHistoryContents());
    Checkpoint("After second GetHistoryContents", start_time);
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Test that changing the pref takes effect immediately
// when the browser is running.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabledThenEnabled) {
  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();
  ExpectEmptyHistory();

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, false);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

}  // namespace
<|endoftext|>


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

#include "chrome/browser/policy/device_token_fetcher.h"

#include <algorithm>

#include "base/message_loop.h"
#include "chrome/browser/policy/cloud_policy_cache_base.h"
#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"

namespace {

// Retry after 5 minutes (with exponential backoff) after token fetch errors.
const int64 kTokenFetchErrorDelayMilliseconds = 5 * 60 * 1000;
// Retry after max 3 hours after token fetch errors.
const int64 kTokenFetchErrorMaxDelayMilliseconds = 3 * 60 * 60 * 1000;
// For unmanaged devices, check once per day whether they're still unmanaged.
const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000;

}  // namespace

namespace policy {

namespace em = enterprise_management;

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             kTokenFetchErrorDelayMilliseconds,
             kTokenFetchErrorMaxDelayMilliseconds,
             kUnmanagedDeviceRefreshRateMilliseconds);
}

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache,
    int64 token_fetch_error_delay_ms,
    int64 token_fetch_error_max_delay_ms,
    int64 unmanaged_device_refresh_rate_ms)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             token_fetch_error_delay_ms,
             token_fetch_error_max_delay_ms,
             unmanaged_device_refresh_rate_ms);
}

DeviceTokenFetcher::~DeviceTokenFetcher() {
  CancelRetryTask();
}

void DeviceTokenFetcher::FetchToken(
    const std::string& auth_token,
    const std::string& device_id,
    em::DeviceRegisterRequest_Type policy_type,
    const std::string& machine_id) {
  SetState(STATE_INACTIVE);
  auth_token_ = auth_token;
  device_id_ = device_id;
  policy_type_ = policy_type;
  machine_id_ = machine_id;
  FetchTokenInternal();
}

void DeviceTokenFetcher::FetchTokenInternal() {
  DCHECK(state_ != STATE_TOKEN_AVAILABLE);
  if (auth_token_.empty() || device_id_.empty()) {
    // Maybe this device is unmanaged, just exit. The CloudPolicyController
    // will call FetchToken() again if something changes.
    return;
  }
  // Construct a new backend, which will discard any previous requests.
  backend_.reset(service_->CreateBackend());
  em::DeviceRegisterRequest request;
  request.set_type(policy_type_);
  if (!machine_id_.empty())
    request.set_machine_id(machine_id_);
  request.set_machine_model(kRegisterRequestMachineModel);
  backend_->ProcessRegisterRequest(auth_token_, device_id_, request, this);
}

void DeviceTokenFetcher::SetUnmanagedState() {
  // The call to |cache_->SetUnmanaged()| has to happen first because it sets
  // the timestamp that |SetState()| needs to determine the correct refresh
  // time.
  cache_->SetUnmanaged();
  SetState(STATE_UNMANAGED);
}

const std::string& DeviceTokenFetcher::GetDeviceToken() {
  return device_token_;
}

void DeviceTokenFetcher::AddObserver(DeviceTokenFetcher::Observer* observer) {
  observer_list_.AddObserver(observer);
}

void DeviceTokenFetcher::RemoveObserver(
    DeviceTokenFetcher::Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void DeviceTokenFetcher::HandleRegisterResponse(
    const em::DeviceRegisterResponse& response) {
  if (response.has_device_management_token()) {
    device_token_ = response.device_management_token();
    SetState(STATE_TOKEN_AVAILABLE);
  } else {
    NOTREACHED();
    SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) {
  switch (code) {
    case DeviceManagementBackend::kErrorServiceManagementNotSupported:
      cache_->SetUnmanaged();
      SetState(STATE_UNMANAGED);
      break;
    case DeviceManagementBackend::kErrorRequestFailed:
    case DeviceManagementBackend::kErrorTemporaryUnavailable:
    case DeviceManagementBackend::kErrorServiceDeviceNotFound:
    case DeviceManagementBackend::kErrorServiceManagementTokenInvalid:
      SetState(STATE_TEMPORARY_ERROR);
      break;
    default:
      SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::Initialize(DeviceManagementService* service,
                                    CloudPolicyCacheBase* cache,
                                    int64 token_fetch_error_delay_ms,
                                    int64 token_fetch_error_max_delay_ms,
                                    int64 unmanaged_device_refresh_rate_ms) {
  service_ = service;
  cache_ = cache;
  token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  token_fetch_error_max_delay_ms_ = token_fetch_error_max_delay_ms;
  effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
  state_ = STATE_INACTIVE;
  retry_task_ = NULL;

  if (cache_->is_unmanaged())
    SetState(STATE_UNMANAGED);
}

void DeviceTokenFetcher::SetState(FetcherState state) {
  state_ = state;
  if (state_ != STATE_ERROR)
    effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_;

  base::Time delayed_work_at;
  switch (state_) {
    case STATE_INACTIVE:
      device_token_.clear();
      auth_token_.clear();
      device_id_.clear();
      break;
    case STATE_TOKEN_AVAILABLE:
      FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceTokenAvailable());
      break;
    case STATE_UNMANAGED:
      delayed_work_at = cache_->last_policy_refresh_time() +
          base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
      break;
    case STATE_TEMPORARY_ERROR:
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      effective_token_fetch_error_delay_ms_ =
          std::min(effective_token_fetch_error_delay_ms_ * 2,
                   token_fetch_error_max_delay_ms_);
      break;
    case STATE_ERROR:
      effective_token_fetch_error_delay_ms_ = token_fetch_error_max_delay_ms_;
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      break;
  }

  CancelRetryTask();
  if (!delayed_work_at.is_null()) {
    base::Time now(base::Time::Now());
    int64 delay = std::max<int64>((delayed_work_at - now).InMilliseconds(), 0);
    retry_task_ = method_factory_.NewRunnableMethod(
            &DeviceTokenFetcher::ExecuteRetryTask);
    MessageLoop::current()->PostDelayedTask(FROM_HERE, retry_task_,
                                            delay);
  }
}

void DeviceTokenFetcher::ExecuteRetryTask() {
  DCHECK(retry_task_);
  retry_task_ = NULL;

  switch (state_) {
    case STATE_INACTIVE:
    case STATE_TOKEN_AVAILABLE:
      break;
    case STATE_UNMANAGED:
    case STATE_ERROR:
    case STATE_TEMPORARY_ERROR:
      FetchTokenInternal();
      break;
  }
}

void DeviceTokenFetcher::CancelRetryTask() {
  if (retry_task_) {
    retry_task_->Cancel();
    retry_task_ = NULL;
  }
}

}  // namespace policy
<commit_msg>Changed the way we handle 401 error in the cloud policy token fetcher.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/policy/device_token_fetcher.h"

#include <algorithm>

#include "base/message_loop.h"
#include "chrome/browser/policy/cloud_policy_cache_base.h"
#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"

namespace {

// Retry after 5 minutes (with exponential backoff) after token fetch errors.
const int64 kTokenFetchErrorDelayMilliseconds = 5 * 60 * 1000;
// Retry after max 3 hours after token fetch errors.
const int64 kTokenFetchErrorMaxDelayMilliseconds = 3 * 60 * 60 * 1000;
// For unmanaged devices, check once per day whether they're still unmanaged.
const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000;

}  // namespace

namespace policy {

namespace em = enterprise_management;

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             kTokenFetchErrorDelayMilliseconds,
             kTokenFetchErrorMaxDelayMilliseconds,
             kUnmanagedDeviceRefreshRateMilliseconds);
}

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache,
    int64 token_fetch_error_delay_ms,
    int64 token_fetch_error_max_delay_ms,
    int64 unmanaged_device_refresh_rate_ms)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             token_fetch_error_delay_ms,
             token_fetch_error_max_delay_ms,
             unmanaged_device_refresh_rate_ms);
}

DeviceTokenFetcher::~DeviceTokenFetcher() {
  CancelRetryTask();
}

void DeviceTokenFetcher::FetchToken(
    const std::string& auth_token,
    const std::string& device_id,
    em::DeviceRegisterRequest_Type policy_type,
    const std::string& machine_id) {
  SetState(STATE_INACTIVE);
  auth_token_ = auth_token;
  device_id_ = device_id;
  policy_type_ = policy_type;
  machine_id_ = machine_id;
  FetchTokenInternal();
}

void DeviceTokenFetcher::FetchTokenInternal() {
  DCHECK(state_ != STATE_TOKEN_AVAILABLE);
  if (auth_token_.empty() || device_id_.empty()) {
    // Maybe this device is unmanaged, just exit. The CloudPolicyController
    // will call FetchToken() again if something changes.
    return;
  }
  // Construct a new backend, which will discard any previous requests.
  backend_.reset(service_->CreateBackend());
  em::DeviceRegisterRequest request;
  request.set_type(policy_type_);
  if (!machine_id_.empty())
    request.set_machine_id(machine_id_);
  request.set_machine_model(kRegisterRequestMachineModel);
  backend_->ProcessRegisterRequest(auth_token_, device_id_, request, this);
}

void DeviceTokenFetcher::SetUnmanagedState() {
  // The call to |cache_->SetUnmanaged()| has to happen first because it sets
  // the timestamp that |SetState()| needs to determine the correct refresh
  // time.
  cache_->SetUnmanaged();
  SetState(STATE_UNMANAGED);
}

const std::string& DeviceTokenFetcher::GetDeviceToken() {
  return device_token_;
}

void DeviceTokenFetcher::AddObserver(DeviceTokenFetcher::Observer* observer) {
  observer_list_.AddObserver(observer);
}

void DeviceTokenFetcher::RemoveObserver(
    DeviceTokenFetcher::Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void DeviceTokenFetcher::HandleRegisterResponse(
    const em::DeviceRegisterResponse& response) {
  if (response.has_device_management_token()) {
    device_token_ = response.device_management_token();
    SetState(STATE_TOKEN_AVAILABLE);
  } else {
    NOTREACHED();
    SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) {
  switch (code) {
    case DeviceManagementBackend::kErrorServiceManagementNotSupported:
      cache_->SetUnmanaged();
      SetState(STATE_UNMANAGED);
      break;
    case DeviceManagementBackend::kErrorRequestFailed:
    case DeviceManagementBackend::kErrorTemporaryUnavailable:
    case DeviceManagementBackend::kErrorServiceDeviceNotFound:
      SetState(STATE_TEMPORARY_ERROR);
      break;
    case DeviceManagementBackend::kErrorServiceManagementTokenInvalid:
      // Most probably the GAIA auth cookie has expired. We can not do anything
      // until the user logs-in again.
      SetState(STATE_INACTIVE);
      break;
    default:
      SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::Initialize(DeviceManagementService* service,
                                    CloudPolicyCacheBase* cache,
                                    int64 token_fetch_error_delay_ms,
                                    int64 token_fetch_error_max_delay_ms,
                                    int64 unmanaged_device_refresh_rate_ms) {
  service_ = service;
  cache_ = cache;
  token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  token_fetch_error_max_delay_ms_ = token_fetch_error_max_delay_ms;
  effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
  state_ = STATE_INACTIVE;
  retry_task_ = NULL;

  if (cache_->is_unmanaged())
    SetState(STATE_UNMANAGED);
}

void DeviceTokenFetcher::SetState(FetcherState state) {
  state_ = state;
  if (state_ != STATE_ERROR)
    effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_;

  base::Time delayed_work_at;
  switch (state_) {
    case STATE_INACTIVE:
      device_token_.clear();
      auth_token_.clear();
      device_id_.clear();
      break;
    case STATE_TOKEN_AVAILABLE:
      FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceTokenAvailable());
      break;
    case STATE_UNMANAGED:
      delayed_work_at = cache_->last_policy_refresh_time() +
          base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
      break;
    case STATE_TEMPORARY_ERROR:
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      effective_token_fetch_error_delay_ms_ =
          std::min(effective_token_fetch_error_delay_ms_ * 2,
                   token_fetch_error_max_delay_ms_);
      break;
    case STATE_ERROR:
      effective_token_fetch_error_delay_ms_ = token_fetch_error_max_delay_ms_;
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      break;
  }

  CancelRetryTask();
  if (!delayed_work_at.is_null()) {
    base::Time now(base::Time::Now());
    int64 delay = std::max<int64>((delayed_work_at - now).InMilliseconds(), 0);
    retry_task_ = method_factory_.NewRunnableMethod(
            &DeviceTokenFetcher::ExecuteRetryTask);
    MessageLoop::current()->PostDelayedTask(FROM_HERE, retry_task_,
                                            delay);
  }
}

void DeviceTokenFetcher::ExecuteRetryTask() {
  DCHECK(retry_task_);
  retry_task_ = NULL;

  switch (state_) {
    case STATE_INACTIVE:
    case STATE_TOKEN_AVAILABLE:
      break;
    case STATE_UNMANAGED:
    case STATE_ERROR:
    case STATE_TEMPORARY_ERROR:
      FetchTokenInternal();
      break;
  }
}

void DeviceTokenFetcher::CancelRetryTask() {
  if (retry_task_) {
    retry_task_->Cancel();
    retry_task_ = NULL;
  }
}

}  // namespace policy
<|endoftext|>


<commit_before>// Copyright (c) 2010 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/translate/translate_manager.h"

#include "base/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/translation_service.h"
#include "chrome/browser/tab_contents/language_state.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/translate/translate_infobars_delegates.h"
#include "chrome/browser/translate/translate_prefs.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"

TranslateManager::~TranslateManager() {
}

void TranslateManager::Observe(NotificationType type,
                               const NotificationSource& source,
                               const NotificationDetails& details) {
  switch (type.value) {
    case NotificationType::TAB_LANGUAGE_DETERMINED: {
      TabContents* tab = Source<TabContents>(source).ptr();
      std::string language = *(Details<std::string>(details).ptr());
      // We may get this notifications multiple times.  Make sure to translate
      // only once.
      if (!tab->language_state().translation_pending())
        InitiateTranslation(tab, language);
      break;
    }
    case NotificationType::PAGE_TRANSLATED: {
      // Only add translate infobar if it doesn't exist; if it already exists,
      // it would have received the same notification and acted accordingly.
      TabContents* tab = Source<TabContents>(source).ptr();
      int i;
      for (i = 0; i < tab->infobar_delegate_count(); ++i) {
        InfoBarDelegate* info_bar = tab->GetInfoBarDelegateAt(i);
        if (info_bar->AsTranslateInfoBarDelegate())
          break;
      }
      if (i == tab->infobar_delegate_count()) {
        NavigationEntry* entry = tab->controller().GetActiveEntry();
        if (entry) {
          std::pair<std::string, std::string>* language_pair =
              (Details<std::pair<std::string, std::string> >(details).ptr());
          PrefService* prefs = tab->profile()->GetPrefs();
          tab->AddInfoBar(new TranslateInfoBarDelegate(tab, prefs,
              TranslateInfoBarDelegate::kAfterTranslate, entry->url(),
              language_pair->first, language_pair->second));
        }
      }
      break;
    }
    case NotificationType::PROFILE_DESTROYED: {
      Profile* profile = Source<Profile>(source).ptr();
      notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
                                     source);
      size_t count = accept_languages_.erase(profile->GetPrefs());
      // We should know about this profile since we are listening for
      // notifications on it.
      DCHECK(count > 0);
      profile->GetPrefs()->RemovePrefObserver(prefs::kAcceptLanguages, this);
      break;
    }
    case NotificationType::PREF_CHANGED: {
      DCHECK(*Details<std::wstring>(details).ptr() == prefs::kAcceptLanguages);
      PrefService* prefs = Source<PrefService>(source).ptr();
      InitAcceptLanguages(prefs);
      break;
    }
    default:
      NOTREACHED();
  }
}

TranslateManager::TranslateManager() {
  if (!TestEnabled() && !TranslationService::IsTranslationEnabled())
    return;

  notification_registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
                              NotificationService::AllSources());
  notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
                              NotificationService::AllSources());
}

void TranslateManager::InitiateTranslation(TabContents* tab,
                                           const std::string& page_lang) {
  PrefService* prefs = tab->profile()->GetPrefs();
  NavigationEntry* entry = tab->controller().GetActiveEntry();
  if (!entry) {
    NOTREACHED();
    return;
  }

  if (!TranslationService::IsSupportedLanguage(page_lang))
    return;  // Nothing to do, we don't support that language.

  std::string ui_lang = TranslationService::GetLanguageCode(
      g_browser_process->GetApplicationLocale());

  // We don't want to translate:
  // - any Chrome specific page (New Tab Page, Download, History... pages).
  // - similar languages (ex: en-US to en).
  // - any user black-listed URLs or user selected language combination.
  // - any language the user configured as accepted languages.
  if (entry->url().SchemeIs("chrome") || page_lang == ui_lang ||
      !TranslatePrefs::CanTranslate(prefs, page_lang, entry->url()) ||
      IsAcceptLanguage(tab, page_lang)) {
    return;
  }

  if (TranslatePrefs::ShouldAutoTranslate(prefs, page_lang, ui_lang)) {
    // The user has previously select "always translate" for this language.
    tab->TranslatePage(page_lang, ui_lang);
    return;
  }

  std::string auto_translate_to = tab->language_state().AutoTranslateTo();
  if (!auto_translate_to.empty()) {
    // This page was navigated through a click from a translated page.
    tab->TranslatePage(page_lang, auto_translate_to);
    return;
  }

  // Prompts the user if he/she wants the page translated.
  tab->AddInfoBar(new TranslateInfoBarDelegate(tab, prefs,
      TranslateInfoBarDelegate::kBeforeTranslate, entry->url(),
      page_lang, ui_lang));
}

bool TranslateManager::IsAcceptLanguage(TabContents* tab,
                                        const std::string& language) {
  PrefService* pref_service = tab->profile()->GetPrefs();
  PrefServiceLanguagesMap::const_iterator iter =
      accept_languages_.find(pref_service);
  if (iter == accept_languages_.end()) {
    InitAcceptLanguages(pref_service);
    // Listen for this profile going away, in which case we would need to clear
    // the accepted languages for the profile.
    notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
                                Source<Profile>(tab->profile()));
    // Also start listening for changes in the accept languages.
    tab->profile()->GetPrefs()->AddPrefObserver(prefs::kAcceptLanguages, this);

    iter = accept_languages_.find(pref_service);
  }

  return iter->second.count(language) != 0;
}

void TranslateManager::InitAcceptLanguages(PrefService* prefs) {
  // We have been asked for this profile, build the languages.
  std::wstring accept_langs_str = prefs->GetString(prefs::kAcceptLanguages);
  std::vector<std::string> accept_langs_list;
  LanguageSet accept_langs_set;
  SplitString(WideToASCII(accept_langs_str), ',', &accept_langs_list);
  std::vector<std::string>::const_iterator iter;
  for (iter = accept_langs_list.begin();
       iter != accept_langs_list.end(); ++iter) {
    // Get rid of the locale extension if any (ex: en-US -> en), but for Chinese
    // for which the CLD reports zh-CN and zh-TW.
    std::string accept_lang(*iter);
    size_t index = iter->find("-");
    if (index != std::string::npos && *iter != "zh-CN" && *iter != "zh-TW")
      accept_lang = iter->substr(0, iter->length() - index - 1);
    accept_langs_set.insert(accept_lang);
  }
  accept_languages_[prefs] = accept_langs_set;
}
<commit_msg>Revert my previous fix for UI tests, it breaks the unit-tests.<commit_after>// Copyright (c) 2010 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/translate/translate_manager.h"

#include "base/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/translation_service.h"
#include "chrome/browser/tab_contents/language_state.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/translate/translate_infobars_delegates.h"
#include "chrome/browser/translate/translate_prefs.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"

TranslateManager::~TranslateManager() {
}

void TranslateManager::Observe(NotificationType type,
                               const NotificationSource& source,
                               const NotificationDetails& details) {
  switch (type.value) {
    case NotificationType::TAB_LANGUAGE_DETERMINED: {
      TabContents* tab = Source<TabContents>(source).ptr();
      std::string language = *(Details<std::string>(details).ptr());
      // We may get this notifications multiple times.  Make sure to translate
      // only once.
      if (!tab->language_state().translation_pending())
        InitiateTranslation(tab, language);
      break;
    }
    case NotificationType::PAGE_TRANSLATED: {
      // Only add translate infobar if it doesn't exist; if it already exists,
      // it would have received the same notification and acted accordingly.
      TabContents* tab = Source<TabContents>(source).ptr();
      int i;
      for (i = 0; i < tab->infobar_delegate_count(); ++i) {
        InfoBarDelegate* info_bar = tab->GetInfoBarDelegateAt(i);
        if (info_bar->AsTranslateInfoBarDelegate())
          break;
      }
      if (i == tab->infobar_delegate_count()) {
        NavigationEntry* entry = tab->controller().GetActiveEntry();
        if (entry) {
          std::pair<std::string, std::string>* language_pair =
              (Details<std::pair<std::string, std::string> >(details).ptr());
          PrefService* prefs = tab->profile()->GetPrefs();
          tab->AddInfoBar(new TranslateInfoBarDelegate(tab, prefs,
              TranslateInfoBarDelegate::kAfterTranslate, entry->url(),
              language_pair->first, language_pair->second));
        }
      }
      break;
    }
    case NotificationType::PROFILE_DESTROYED: {
      Profile* profile = Source<Profile>(source).ptr();
      notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
                                     source);
      size_t count = accept_languages_.erase(profile->GetPrefs());
      // We should know about this profile since we are listening for
      // notifications on it.
      DCHECK(count > 0);
      profile->GetPrefs()->RemovePrefObserver(prefs::kAcceptLanguages, this);
      break;
    }
    case NotificationType::PREF_CHANGED: {
      DCHECK(*Details<std::wstring>(details).ptr() == prefs::kAcceptLanguages);
      PrefService* prefs = Source<PrefService>(source).ptr();
      InitAcceptLanguages(prefs);
      break;
    }
    default:
      NOTREACHED();
  }
}

TranslateManager::TranslateManager() {
  if (TestEnabled() && !TranslationService::IsTranslationEnabled())
    return;

  notification_registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
                              NotificationService::AllSources());
  notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
                              NotificationService::AllSources());
}

void TranslateManager::InitiateTranslation(TabContents* tab,
                                           const std::string& page_lang) {
  PrefService* prefs = tab->profile()->GetPrefs();
  NavigationEntry* entry = tab->controller().GetActiveEntry();
  if (!entry) {
    NOTREACHED();
    return;
  }

  if (!TranslationService::IsSupportedLanguage(page_lang))
    return;  // Nothing to do, we don't support that language.

  std::string ui_lang = TranslationService::GetLanguageCode(
      g_browser_process->GetApplicationLocale());

  // We don't want to translate:
  // - any Chrome specific page (New Tab Page, Download, History... pages).
  // - similar languages (ex: en-US to en).
  // - any user black-listed URLs or user selected language combination.
  // - any language the user configured as accepted languages.
  if (entry->url().SchemeIs("chrome") || page_lang == ui_lang ||
      !TranslatePrefs::CanTranslate(prefs, page_lang, entry->url()) ||
      IsAcceptLanguage(tab, page_lang)) {
    return;
  }

  if (TranslatePrefs::ShouldAutoTranslate(prefs, page_lang, ui_lang)) {
    // The user has previously select "always translate" for this language.
    tab->TranslatePage(page_lang, ui_lang);
    return;
  }

  std::string auto_translate_to = tab->language_state().AutoTranslateTo();
  if (!auto_translate_to.empty()) {
    // This page was navigated through a click from a translated page.
    tab->TranslatePage(page_lang, auto_translate_to);
    return;
  }

  // Prompts the user if he/she wants the page translated.
  tab->AddInfoBar(new TranslateInfoBarDelegate(tab, prefs,
      TranslateInfoBarDelegate::kBeforeTranslate, entry->url(),
      page_lang, ui_lang));
}

bool TranslateManager::IsAcceptLanguage(TabContents* tab,
                                        const std::string& language) {
  PrefService* pref_service = tab->profile()->GetPrefs();
  PrefServiceLanguagesMap::const_iterator iter =
      accept_languages_.find(pref_service);
  if (iter == accept_languages_.end()) {
    InitAcceptLanguages(pref_service);
    // Listen for this profile going away, in which case we would need to clear
    // the accepted languages for the profile.
    notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
                                Source<Profile>(tab->profile()));
    // Also start listening for changes in the accept languages.
    tab->profile()->GetPrefs()->AddPrefObserver(prefs::kAcceptLanguages, this);

    iter = accept_languages_.find(pref_service);
  }

  return iter->second.count(language) != 0;
}

void TranslateManager::InitAcceptLanguages(PrefService* prefs) {
  // We have been asked for this profile, build the languages.
  std::wstring accept_langs_str = prefs->GetString(prefs::kAcceptLanguages);
  std::vector<std::string> accept_langs_list;
  LanguageSet accept_langs_set;
  SplitString(WideToASCII(accept_langs_str), ',', &accept_langs_list);
  std::vector<std::string>::const_iterator iter;
  for (iter = accept_langs_list.begin();
       iter != accept_langs_list.end(); ++iter) {
    // Get rid of the locale extension if any (ex: en-US -> en), but for Chinese
    // for which the CLD reports zh-CN and zh-TW.
    std::string accept_lang(*iter);
    size_t index = iter->find("-");
    if (index != std::string::npos && *iter != "zh-CN" && *iter != "zh-TW")
      accept_lang = iter->substr(0, iter->length() - index - 1);
    accept_langs_set.insert(accept_lang);
  }
  accept_languages_[prefs] = accept_langs_set;
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <fstream>
<<<<<<< HEAD
using namespace std;

void readFile(char filename[])
{
	int i=0;
	char file[1024];

	ifstream r;
	r.open (filename);

//	while (r != EOF)
//	{
//		r >> file[i];
//		i++;
//	}

	r.close();
=======
#include <assert.h>
using namespace std;

#define BUF_SIZE 1024

void readFile(char* filename, char str[1024])
{
	int i=0;

	ifstream fin (filename, ios_base::in | ios_base::binary);

	if (fin.is_open())
	{
		fin.read(str, 1024);
	}
	else
	{
		return;
	}

	fin.close();
>>>>>>> fd78047... file I/O
}

void writeFile(char* filename, char* str, int size)
{
<<<<<<< HEAD
	ofstream w;
	w.open (filename);

	w.close();
=======
	ofstream fout (filename, ios_base::out | ios_base::trunc | ios_base::binary);

	if(fout.is_open())
	{
		fout.write(str, size);
	}
	else
	{
		return;
	}

	fout.close();
>>>>>>> fd78047... file I/O
}
<commit_msg>modify file I/O<commit_after>#include <string>
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;

#define BUF_SIZE 1024

void readFile(char* filename, char str[1024])
{
	int i=0;

	ifstream fin (filename, ios_base::in | ios_base::binary);

	if (fin.is_open())
	{
		fin.read(str, 1024);
	}
	else
	{
		return;
	}

	fin.close();
}

void writeFile(char* filename, char* str, int size)
{
	ofstream fout (filename, ios_base::out | ios_base::trunc | ios_base::binary);

	if(fout.is_open())
	{
		fout.write(str, size);
	}
	else
	{
		return;
	}

	fout.close();
}
<|endoftext|>