<commit_before>//===--- RawSILInstLowering.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "raw-sil-inst-lowering"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/Statistic.h"

STATISTIC(numAssignRewritten, "Number of assigns rewritten");

using namespace swift;

/// Emit the sequence that an assign instruction lowers to once we know
/// if it is an initialization or an assignment.  If it is an assignment,
/// a live-in value can be provided to optimize out the reload.
static void lowerAssignInstruction(SILBuilderWithScope &b, AssignInst *inst) {
  LLVM_DEBUG(llvm::dbgs() << "  *** Lowering [isInit="
                          << unsigned(inst->getOwnershipQualifier())
                          << "]: " << *inst << "\n");

  ++numAssignRewritten;

  SILValue src = inst->getSrc();
  SILValue dest = inst->getDest();
  SILLocation loc = inst->getLoc();
  AssignOwnershipQualifier qualifier = inst->getOwnershipQualifier();

  // Unknown qualifier is considered unprocessed. Just lower it as [reassign],
  // but if the destination type is trivial, treat it as [init].
  //
  // Unknown should not be lowered because definite initialization should
  // always set an initialization kind for assign instructions, but there exists
  // some situations where SILGen doesn't generate a mark_uninitialized
  // instruction for a full mark_uninitialized. Thus definite initialization
  // doesn't set an initialization kind for some assign instructions.
  //
  // TODO: Fix SILGen so that this is an assert preventing the lowering of
  //       Unknown init kind.
  if (qualifier == AssignOwnershipQualifier::Unknown)
    qualifier = AssignOwnershipQualifier::Reassign;

  if (qualifier == AssignOwnershipQualifier::Init ||
      inst->getDest()->getType().isTrivial(*inst->getFunction())) {

    // If this is an initialization, or the storage type is trivial, we
    // can just replace the assignment with a store.
    assert(qualifier != AssignOwnershipQualifier::Reinit);
    b.createTrivialStoreOr(loc, src, dest, StoreOwnershipQualifier::Init);
    inst->eraseFromParent();
    return;
  }

  if (qualifier == AssignOwnershipQualifier::Reinit) {
    // We have a case where a convenience initializer on a class
    // delegates to a factory initializer from a protocol extension.
    // Factory initializers give us a whole new instance, so the existing
    // instance, which has not been initialized and never will be, must be
    // freed using dealloc_partial_ref.
    SILValue pointer = b.createLoad(loc, dest, LoadOwnershipQualifier::Take);
    b.createStore(loc, src, dest, StoreOwnershipQualifier::Init);

    auto metatypeTy = CanMetatypeType::get(
        dest->getType().getASTType(), MetatypeRepresentation::Thick);
    auto silMetatypeTy = SILType::getPrimitiveObjectType(metatypeTy);
    SILValue metatype = b.createValueMetatype(loc, silMetatypeTy, pointer);

    b.createDeallocPartialRef(loc, pointer, metatype);
    inst->eraseFromParent();
    return;
  }

  assert(qualifier == AssignOwnershipQualifier::Reassign);
  // Otherwise, we need to replace the assignment with a store [assign] which
  // lowers to the load/store/release dance. Note that the new value is already
  // considered to be retained (by the semantics of the storage type),
  // and we're transferring that ownership count into the destination.

  b.createStore(loc, src, dest, StoreOwnershipQualifier::Assign);
  inst->eraseFromParent();
}

/// Construct the argument list for the assign_by_wrapper initializer or setter.
///
/// Usually this is only a single value and a single argument, but in case of
/// a tuple, the initializer/setter expect the tuple elements as separate
/// arguments. The purpose of this function is to recursively visit tuple
/// elements and add them to the argument list \p arg.
static void getAssignByWrapperArgsRecursively(SmallVectorImpl<SILValue> &args,
    SILValue src, unsigned &argIdx, const SILFunctionConventions &convention,
    SILBuilder &forProjections, SILBuilder &forCleanup) {

  SILLocation loc = (*forProjections.getInsertionPoint()).getLoc();
  SILType srcTy = src->getType();
  if (auto tupleTy = srcTy.getAs<TupleType>()) {
    // In case the source is a tuple, we have to destructure the tuple and pass
    // the tuple elements separately.
    if (srcTy.isAddress()) {
      for (unsigned idx = 0, n = tupleTy->getNumElements(); idx < n; ++idx) {
        auto *TEA = forProjections.createTupleElementAddr(loc, src, idx);
        getAssignByWrapperArgsRecursively(args, TEA, argIdx, convention,
          forProjections, forCleanup);
      }
    } else {
      auto *DTI = forProjections.createDestructureTuple(loc, src);
      for (SILValue elmt : DTI->getAllResults()) {
        getAssignByWrapperArgsRecursively(args, elmt, argIdx, convention,
          forProjections, forCleanup);
      }
    }
    return;
  }
  assert(argIdx < convention.getNumSILArguments() &&
         "initializer or setter has too few arguments");

  SILArgumentConvention argConv = convention.getSILArgumentConvention(argIdx);
  if (srcTy.isAddress() && !argConv.isIndirectConvention()) {
    // In case of a tuple where one element is loadable, but the other is
    // address only, we get the whole tuple as address.
    // For the loadable element, the argument is passed directly, but the
    // tuple element is in memory. For this case we have to insert a load.
    src = forProjections.createTrivialLoadOr(loc, src,
                                             LoadOwnershipQualifier::Take);
  }
  switch (argConv) {
    case SILArgumentConvention::Indirect_In_Guaranteed:
      forCleanup.createDestroyAddr(loc, src);
      break;
    case SILArgumentConvention::Direct_Guaranteed:
      forCleanup.createDestroyValue(loc, src);
      break;
    case SILArgumentConvention::Direct_Unowned:
    case SILArgumentConvention::Indirect_In:
    case SILArgumentConvention::Indirect_In_Constant:
    case SILArgumentConvention::Direct_Owned:
      break;
    case SILArgumentConvention::Indirect_Inout:
    case SILArgumentConvention::Indirect_InoutAliasable:
    case SILArgumentConvention::Indirect_Out:
      llvm_unreachable("wrong convention for setter/initializer src argument");
  }
  args.push_back(src);
  ++argIdx;
}

static void getAssignByWrapperArgs(SmallVectorImpl<SILValue> &args,
            SILValue src, const SILFunctionConventions &convention,
            SILBuilder &forProjections, SILBuilder &forCleanup) {
  unsigned argIdx = convention.getSILArgIndexOfFirstParam();
  getAssignByWrapperArgsRecursively(args, src, argIdx, convention,
                              forProjections, forCleanup);
  assert(argIdx == convention.getNumSILArguments() &&
         "initializer or setter has too many arguments");
}

static void
lowerAssignByWrapperInstruction(SILBuilderWithScope &b,
                                AssignByWrapperInst *inst,
                                SmallSetVector<SILValue, 8> &toDelete) {
  LLVM_DEBUG(llvm::dbgs() << "  *** Lowering " << *inst << "\n");

  ++numAssignRewritten;

  SILValue src = inst->getSrc();
  SILValue dest = inst->getDest();
  SILLocation loc = inst->getLoc();
  SILBuilderWithScope forCleanup(std::next(inst->getIterator()));

  switch (inst->getMode()) {
    case AssignByWrapperInst::Unknown:
      assert(b.getModule().getASTContext().hadError() &&
             "assign_by_wrapper must have a valid mode");
      // In case DefiniteInitialization already gave up with an error, just
      // treat the assign_by_wrapper as an "init".
      LLVM_FALLTHROUGH;
    case AssignByWrapperInst::Initialization:
    case AssignByWrapperInst::Assign: {
      switch (inst->getOriginator()) {
      case AssignByWrapperInst::Originator::TypeWrapper: {
        if (inst->getMode() == AssignByWrapperInst::Initialization ||
            inst->getDest()->getType().isTrivial(*inst->getFunction())) {
          b.createTrivialStoreOr(loc, src, dest, StoreOwnershipQualifier::Init);
        } else {
          b.createStore(loc, src, dest, StoreOwnershipQualifier::Assign);
        }
        break;
      }

      case AssignByWrapperInst::Originator::PropertyWrapper: {
        SILValue initFn = inst->getInitializer();
        CanSILFunctionType fTy = initFn->getType().castTo<SILFunctionType>();
        SILFunctionConventions convention(fTy, inst->getModule());
        SmallVector<SILValue, 4> args;
        if (convention.hasIndirectSILResults()) {
          if (inst->getMode() == AssignByWrapperInst::Assign)
            b.createDestroyAddr(loc, dest);

          args.push_back(dest);
          getAssignByWrapperArgs(args, src, convention, b, forCleanup);
          b.createApply(loc, initFn, SubstitutionMap(), args);
        } else {
          getAssignByWrapperArgs(args, src, convention, b, forCleanup);
          SILValue wrappedSrc =
              b.createApply(loc, initFn, SubstitutionMap(), args);
          if (inst->getMode() == AssignByWrapperInst::Initialization ||
              inst->getDest()->getType().isTrivial(*inst->getFunction())) {
            b.createTrivialStoreOr(loc, wrappedSrc, dest,
                                   StoreOwnershipQualifier::Init);
          } else {
            b.createStore(loc, wrappedSrc, dest,
                          StoreOwnershipQualifier::Assign);
          }
        }
        break;
      }
      }

      // The unused partial_apply violates memory lifetime rules in case "self"
      // is an inout. Therefore we cannot keep it as a dead closure to be
      // cleaned up later. We have to delete it in this pass.
      toDelete.insert(inst->getSetter());

      // Also the argument of the closure (which usually is a "load") has to be
      // deleted to avoid memory lifetime violations.
      auto *setterPA = dyn_cast<PartialApplyInst>(inst->getSetter());
      if (setterPA && setterPA->getNumArguments() == 1)
        toDelete.insert(setterPA->getArgument(0));
      break;
    }
    case AssignByWrapperInst::AssignWrappedValue: {
      SILValue setterFn = inst->getSetter();
      CanSILFunctionType fTy = setterFn->getType().castTo<SILFunctionType>();
      SILFunctionConventions convention(fTy, inst->getModule());
      assert(!convention.hasIndirectSILResults());
      SmallVector<SILValue, 4> args;
      getAssignByWrapperArgs(args, src, convention, b, forCleanup);
      b.createApply(loc, setterFn, SubstitutionMap(), args);

      // The destination address is not used. Remove it if it is a dead access
      // marker. This is important, because also the setter function contains
      // access marker. In case those markers are dynamic it would cause a
      // nested access violation.
      if (isa<BeginAccessInst>(dest))
        toDelete.insert(dest);

      // Again, we have to delete the unused dead closure.
      toDelete.insert(inst->getInitializer());
      break;
    }
  }
  inst->eraseFromParent();
}

static void deleteDeadAccessMarker(BeginAccessInst *BA) {
  SmallVector<SILInstruction *, 4> Users;
  for (Operand *Op : BA->getUses()) {
    SILInstruction *User = Op->getUser();
    if (!isa<EndAccessInst>(User))
      return;

    Users.push_back(User);
  }
  for (SILInstruction *User: Users) {
    User->eraseFromParent();
  }
  BA->eraseFromParent();
}

/// Delete a dead load for a dead setter-closure.
static void deleteDeadClosureArg(LoadInst *load) {
  if (load->getOwnershipQualifier() != LoadOwnershipQualifier::Trivial &&
      load->getOwnershipQualifier() != LoadOwnershipQualifier::Copy)
    return;

  for (Operand *use : load->getUses()) {
    if (!isa<DestroyValueInst>(use->getUser()))
      return;
  }
  while (!load->use_empty()) {
    load->use_begin()->getUser()->eraseFromParent();
  }
  load->eraseFromParent();
}

/// lowerRawSILOperations - There are a variety of raw-sil instructions like
/// 'assign' that are only used by this pass.  Now that definite initialization
/// checking is done, remove them.
static bool lowerRawSILOperations(SILFunction &fn) {
  bool changed = false;

  for (auto &bb : fn) {
    SmallSetVector<SILValue, 8> toDelete;

    auto i = bb.begin(), e = bb.end();
    while (i != e) {
      SILInstruction *inst = &*i;
      ++i;

      // Lower 'assign' depending on initialization kind defined by definite
      // initialization.
      //
      // * Unknown is considered unprocessed and is treated as [reassign] or
      //   [init] if the destination type is trivial.
      // * Init becomes a store [init] or a store [trivial] if the destination's
      //   type is trivial.
      // * Reinit becomes a load [take], store [init], and a
      //   dealloc_partial_ref.
      // * Reassign becomes a store [assign].
      if (auto *ai = dyn_cast<AssignInst>(inst)) {
        SILBuilderWithScope b(ai);
        lowerAssignInstruction(b, ai);
        // Assign lowering may split the block. If it did,
        // reset our iteration range to the block after the insertion.
        if (b.getInsertionBB() != &bb)
          i = e;
        changed = true;
        continue;
      }

      if (auto *ai = dyn_cast<AssignByWrapperInst>(inst)) {
        SILBuilderWithScope b(ai);
        lowerAssignByWrapperInstruction(b, ai, toDelete);
        changed = true;
        continue;
      }

      // mark_uninitialized just becomes a noop, resolving to its operand.
      if (auto *mui = dyn_cast<MarkUninitializedInst>(inst)) {
        mui->replaceAllUsesWith(mui->getOperand());
        mui->eraseFromParent();
        changed = true;
        continue;
      }

      // mark_function_escape just gets zapped.
      if (isa<MarkFunctionEscapeInst>(inst)) {
        inst->eraseFromParent();
        changed = true;
        continue;
      }
    }
    for (SILValue deadVal : toDelete) {
      if (auto *beginAccess = dyn_cast<BeginAccessInst>(deadVal)) {
        deleteDeadAccessMarker(beginAccess);
      } else if (auto *load = dyn_cast<LoadInst>(deadVal)) {
        deleteDeadClosureArg(load);
      } else if (auto *svi = dyn_cast<SingleValueInstruction>(deadVal)) {
        tryDeleteDeadClosure(svi);
      }
    }
  }
  return changed;
}

//===----------------------------------------------------------------------===//
//                            Top Level Entrypoint
//===----------------------------------------------------------------------===//

namespace {

class RawSILInstLowering : public SILFunctionTransform {
  void run() override {
    // Do not try to relower raw instructions in canonical SIL. There won't be
    // any there.
    if (getFunction()->wasDeserializedCanonical()) {
      return;
    }

    // Lower raw-sil only instructions used by this pass, like "assign".
    if (lowerRawSILOperations(*getFunction()))
      invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
  }
};

} // end anonymous namespace

SILTransform *swift::createRawSILInstLowering() {
  return new RawSILInstLowering();
}
<commit_msg>[SILOptimizer] TypeWrappers: Lower assign_by_wrapper into copy_addr for address-only types<commit_after>//===--- RawSILInstLowering.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "raw-sil-inst-lowering"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/Statistic.h"

STATISTIC(numAssignRewritten, "Number of assigns rewritten");

using namespace swift;

/// Emit the sequence that an assign instruction lowers to once we know
/// if it is an initialization or an assignment.  If it is an assignment,
/// a live-in value can be provided to optimize out the reload.
static void lowerAssignInstruction(SILBuilderWithScope &b, AssignInst *inst) {
  LLVM_DEBUG(llvm::dbgs() << "  *** Lowering [isInit="
                          << unsigned(inst->getOwnershipQualifier())
                          << "]: " << *inst << "\n");

  ++numAssignRewritten;

  SILValue src = inst->getSrc();
  SILValue dest = inst->getDest();
  SILLocation loc = inst->getLoc();
  AssignOwnershipQualifier qualifier = inst->getOwnershipQualifier();

  // Unknown qualifier is considered unprocessed. Just lower it as [reassign],
  // but if the destination type is trivial, treat it as [init].
  //
  // Unknown should not be lowered because definite initialization should
  // always set an initialization kind for assign instructions, but there exists
  // some situations where SILGen doesn't generate a mark_uninitialized
  // instruction for a full mark_uninitialized. Thus definite initialization
  // doesn't set an initialization kind for some assign instructions.
  //
  // TODO: Fix SILGen so that this is an assert preventing the lowering of
  //       Unknown init kind.
  if (qualifier == AssignOwnershipQualifier::Unknown)
    qualifier = AssignOwnershipQualifier::Reassign;

  if (qualifier == AssignOwnershipQualifier::Init ||
      inst->getDest()->getType().isTrivial(*inst->getFunction())) {

    // If this is an initialization, or the storage type is trivial, we
    // can just replace the assignment with a store.
    assert(qualifier != AssignOwnershipQualifier::Reinit);
    b.createTrivialStoreOr(loc, src, dest, StoreOwnershipQualifier::Init);
    inst->eraseFromParent();
    return;
  }

  if (qualifier == AssignOwnershipQualifier::Reinit) {
    // We have a case where a convenience initializer on a class
    // delegates to a factory initializer from a protocol extension.
    // Factory initializers give us a whole new instance, so the existing
    // instance, which has not been initialized and never will be, must be
    // freed using dealloc_partial_ref.
    SILValue pointer = b.createLoad(loc, dest, LoadOwnershipQualifier::Take);
    b.createStore(loc, src, dest, StoreOwnershipQualifier::Init);

    auto metatypeTy = CanMetatypeType::get(
        dest->getType().getASTType(), MetatypeRepresentation::Thick);
    auto silMetatypeTy = SILType::getPrimitiveObjectType(metatypeTy);
    SILValue metatype = b.createValueMetatype(loc, silMetatypeTy, pointer);

    b.createDeallocPartialRef(loc, pointer, metatype);
    inst->eraseFromParent();
    return;
  }

  assert(qualifier == AssignOwnershipQualifier::Reassign);
  // Otherwise, we need to replace the assignment with a store [assign] which
  // lowers to the load/store/release dance. Note that the new value is already
  // considered to be retained (by the semantics of the storage type),
  // and we're transferring that ownership count into the destination.

  b.createStore(loc, src, dest, StoreOwnershipQualifier::Assign);
  inst->eraseFromParent();
}

/// Construct the argument list for the assign_by_wrapper initializer or setter.
///
/// Usually this is only a single value and a single argument, but in case of
/// a tuple, the initializer/setter expect the tuple elements as separate
/// arguments. The purpose of this function is to recursively visit tuple
/// elements and add them to the argument list \p arg.
static void getAssignByWrapperArgsRecursively(SmallVectorImpl<SILValue> &args,
    SILValue src, unsigned &argIdx, const SILFunctionConventions &convention,
    SILBuilder &forProjections, SILBuilder &forCleanup) {

  SILLocation loc = (*forProjections.getInsertionPoint()).getLoc();
  SILType srcTy = src->getType();
  if (auto tupleTy = srcTy.getAs<TupleType>()) {
    // In case the source is a tuple, we have to destructure the tuple and pass
    // the tuple elements separately.
    if (srcTy.isAddress()) {
      for (unsigned idx = 0, n = tupleTy->getNumElements(); idx < n; ++idx) {
        auto *TEA = forProjections.createTupleElementAddr(loc, src, idx);
        getAssignByWrapperArgsRecursively(args, TEA, argIdx, convention,
          forProjections, forCleanup);
      }
    } else {
      auto *DTI = forProjections.createDestructureTuple(loc, src);
      for (SILValue elmt : DTI->getAllResults()) {
        getAssignByWrapperArgsRecursively(args, elmt, argIdx, convention,
          forProjections, forCleanup);
      }
    }
    return;
  }
  assert(argIdx < convention.getNumSILArguments() &&
         "initializer or setter has too few arguments");

  SILArgumentConvention argConv = convention.getSILArgumentConvention(argIdx);
  if (srcTy.isAddress() && !argConv.isIndirectConvention()) {
    // In case of a tuple where one element is loadable, but the other is
    // address only, we get the whole tuple as address.
    // For the loadable element, the argument is passed directly, but the
    // tuple element is in memory. For this case we have to insert a load.
    src = forProjections.createTrivialLoadOr(loc, src,
                                             LoadOwnershipQualifier::Take);
  }
  switch (argConv) {
    case SILArgumentConvention::Indirect_In_Guaranteed:
      forCleanup.createDestroyAddr(loc, src);
      break;
    case SILArgumentConvention::Direct_Guaranteed:
      forCleanup.createDestroyValue(loc, src);
      break;
    case SILArgumentConvention::Direct_Unowned:
    case SILArgumentConvention::Indirect_In:
    case SILArgumentConvention::Indirect_In_Constant:
    case SILArgumentConvention::Direct_Owned:
      break;
    case SILArgumentConvention::Indirect_Inout:
    case SILArgumentConvention::Indirect_InoutAliasable:
    case SILArgumentConvention::Indirect_Out:
      llvm_unreachable("wrong convention for setter/initializer src argument");
  }
  args.push_back(src);
  ++argIdx;
}

static void getAssignByWrapperArgs(SmallVectorImpl<SILValue> &args,
            SILValue src, const SILFunctionConventions &convention,
            SILBuilder &forProjections, SILBuilder &forCleanup) {
  unsigned argIdx = convention.getSILArgIndexOfFirstParam();
  getAssignByWrapperArgsRecursively(args, src, argIdx, convention,
                              forProjections, forCleanup);
  assert(argIdx == convention.getNumSILArguments() &&
         "initializer or setter has too many arguments");
}

static void
lowerAssignByWrapperInstruction(SILBuilderWithScope &b,
                                AssignByWrapperInst *inst,
                                SmallSetVector<SILValue, 8> &toDelete) {
  LLVM_DEBUG(llvm::dbgs() << "  *** Lowering " << *inst << "\n");

  ++numAssignRewritten;

  SILValue src = inst->getSrc();
  SILValue dest = inst->getDest();
  SILLocation loc = inst->getLoc();
  SILBuilderWithScope forCleanup(std::next(inst->getIterator()));

  switch (inst->getMode()) {
    case AssignByWrapperInst::Unknown:
      assert(b.getModule().getASTContext().hadError() &&
             "assign_by_wrapper must have a valid mode");
      // In case DefiniteInitialization already gave up with an error, just
      // treat the assign_by_wrapper as an "init".
      LLVM_FALLTHROUGH;
    case AssignByWrapperInst::Initialization:
    case AssignByWrapperInst::Assign: {
      switch (inst->getOriginator()) {
      case AssignByWrapperInst::Originator::TypeWrapper: {
        bool initialization =
            inst->getMode() == AssignByWrapperInst::Initialization;

        if (inst->getDest()->getType().isAddressOnly(*inst->getFunction())) {
          b.createCopyAddr(loc, src, dest, IsTake,
                           initialization ? IsInitialization
                                          : IsNotInitialization);
        } else {
          b.createTrivialStoreOr(loc, src, dest,
                                 initialization
                                     ? StoreOwnershipQualifier::Init
                                     : StoreOwnershipQualifier::Assign);
        }
        break;
      }

      case AssignByWrapperInst::Originator::PropertyWrapper: {
        SILValue initFn = inst->getInitializer();
        CanSILFunctionType fTy = initFn->getType().castTo<SILFunctionType>();
        SILFunctionConventions convention(fTy, inst->getModule());
        SmallVector<SILValue, 4> args;
        if (convention.hasIndirectSILResults()) {
          if (inst->getMode() == AssignByWrapperInst::Assign)
            b.createDestroyAddr(loc, dest);

          args.push_back(dest);
          getAssignByWrapperArgs(args, src, convention, b, forCleanup);
          b.createApply(loc, initFn, SubstitutionMap(), args);
        } else {
          getAssignByWrapperArgs(args, src, convention, b, forCleanup);
          SILValue wrappedSrc =
              b.createApply(loc, initFn, SubstitutionMap(), args);
          if (inst->getMode() == AssignByWrapperInst::Initialization ||
              inst->getDest()->getType().isTrivial(*inst->getFunction())) {
            b.createTrivialStoreOr(loc, wrappedSrc, dest,
                                   StoreOwnershipQualifier::Init);
          } else {
            b.createStore(loc, wrappedSrc, dest,
                          StoreOwnershipQualifier::Assign);
          }
        }
        break;
      }
      }

      // The unused partial_apply violates memory lifetime rules in case "self"
      // is an inout. Therefore we cannot keep it as a dead closure to be
      // cleaned up later. We have to delete it in this pass.
      toDelete.insert(inst->getSetter());

      // Also the argument of the closure (which usually is a "load") has to be
      // deleted to avoid memory lifetime violations.
      auto *setterPA = dyn_cast<PartialApplyInst>(inst->getSetter());
      if (setterPA && setterPA->getNumArguments() == 1)
        toDelete.insert(setterPA->getArgument(0));
      break;
    }
    case AssignByWrapperInst::AssignWrappedValue: {
      SILValue setterFn = inst->getSetter();
      CanSILFunctionType fTy = setterFn->getType().castTo<SILFunctionType>();
      SILFunctionConventions convention(fTy, inst->getModule());
      assert(!convention.hasIndirectSILResults());
      SmallVector<SILValue, 4> args;
      getAssignByWrapperArgs(args, src, convention, b, forCleanup);
      b.createApply(loc, setterFn, SubstitutionMap(), args);

      // The destination address is not used. Remove it if it is a dead access
      // marker. This is important, because also the setter function contains
      // access marker. In case those markers are dynamic it would cause a
      // nested access violation.
      if (isa<BeginAccessInst>(dest))
        toDelete.insert(dest);

      // Again, we have to delete the unused dead closure.
      toDelete.insert(inst->getInitializer());
      break;
    }
  }
  inst->eraseFromParent();
}

static void deleteDeadAccessMarker(BeginAccessInst *BA) {
  SmallVector<SILInstruction *, 4> Users;
  for (Operand *Op : BA->getUses()) {
    SILInstruction *User = Op->getUser();
    if (!isa<EndAccessInst>(User))
      return;

    Users.push_back(User);
  }
  for (SILInstruction *User: Users) {
    User->eraseFromParent();
  }
  BA->eraseFromParent();
}

/// Delete a dead load for a dead setter-closure.
static void deleteDeadClosureArg(LoadInst *load) {
  if (load->getOwnershipQualifier() != LoadOwnershipQualifier::Trivial &&
      load->getOwnershipQualifier() != LoadOwnershipQualifier::Copy)
    return;

  for (Operand *use : load->getUses()) {
    if (!isa<DestroyValueInst>(use->getUser()))
      return;
  }
  while (!load->use_empty()) {
    load->use_begin()->getUser()->eraseFromParent();
  }
  load->eraseFromParent();
}

/// lowerRawSILOperations - There are a variety of raw-sil instructions like
/// 'assign' that are only used by this pass.  Now that definite initialization
/// checking is done, remove them.
static bool lowerRawSILOperations(SILFunction &fn) {
  bool changed = false;

  for (auto &bb : fn) {
    SmallSetVector<SILValue, 8> toDelete;

    auto i = bb.begin(), e = bb.end();
    while (i != e) {
      SILInstruction *inst = &*i;
      ++i;

      // Lower 'assign' depending on initialization kind defined by definite
      // initialization.
      //
      // * Unknown is considered unprocessed and is treated as [reassign] or
      //   [init] if the destination type is trivial.
      // * Init becomes a store [init] or a store [trivial] if the destination's
      //   type is trivial.
      // * Reinit becomes a load [take], store [init], and a
      //   dealloc_partial_ref.
      // * Reassign becomes a store [assign].
      if (auto *ai = dyn_cast<AssignInst>(inst)) {
        SILBuilderWithScope b(ai);
        lowerAssignInstruction(b, ai);
        // Assign lowering may split the block. If it did,
        // reset our iteration range to the block after the insertion.
        if (b.getInsertionBB() != &bb)
          i = e;
        changed = true;
        continue;
      }

      if (auto *ai = dyn_cast<AssignByWrapperInst>(inst)) {
        SILBuilderWithScope b(ai);
        lowerAssignByWrapperInstruction(b, ai, toDelete);
        changed = true;
        continue;
      }

      // mark_uninitialized just becomes a noop, resolving to its operand.
      if (auto *mui = dyn_cast<MarkUninitializedInst>(inst)) {
        mui->replaceAllUsesWith(mui->getOperand());
        mui->eraseFromParent();
        changed = true;
        continue;
      }

      // mark_function_escape just gets zapped.
      if (isa<MarkFunctionEscapeInst>(inst)) {
        inst->eraseFromParent();
        changed = true;
        continue;
      }
    }
    for (SILValue deadVal : toDelete) {
      if (auto *beginAccess = dyn_cast<BeginAccessInst>(deadVal)) {
        deleteDeadAccessMarker(beginAccess);
      } else if (auto *load = dyn_cast<LoadInst>(deadVal)) {
        deleteDeadClosureArg(load);
      } else if (auto *svi = dyn_cast<SingleValueInstruction>(deadVal)) {
        tryDeleteDeadClosure(svi);
      }
    }
  }
  return changed;
}

//===----------------------------------------------------------------------===//
//                            Top Level Entrypoint
//===----------------------------------------------------------------------===//

namespace {

class RawSILInstLowering : public SILFunctionTransform {
  void run() override {
    // Do not try to relower raw instructions in canonical SIL. There won't be
    // any there.
    if (getFunction()->wasDeserializedCanonical()) {
      return;
    }

    // Lower raw-sil only instructions used by this pass, like "assign".
    if (lowerRawSILOperations(*getFunction()))
      invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
  }
};

} // end anonymous namespace

SILTransform *swift::createRawSILInstLowering() {
  return new RawSILInstLowering();
}
<|endoftext|>


<commit_before>// This file is part of Poseidon.
// Copyleft 2020, LH_Mouse. All wrongs reserved.

#ifndef POSEIDON_CORE_PROMISE_HPP_
#define POSEIDON_CORE_PROMISE_HPP_

#include "future.hpp"

namespace poseidon {

template<typename ValueT>
class Promise
  {
    friend Future<ValueT>;

  private:
    rcptr<Future<ValueT>> m_futp;

  public:
    Promise()
    noexcept
      { }

    Promise(Promise&& other)
    noexcept
      : m_futp(::std::move(other.m_futp))
      { }

    Promise&
    operator=(Promise&& other)
    noexcept
      {
        if(this->m_futp == other.m_futp)
          return *this;

        this->do_dispose();
        this->m_futp = ::std::move(other.m_futp);
        return *this;
      }

    ~Promise()
      { this->do_dispose();  }

  private:
    bool
    do_dispose()
    noexcept
      {
        auto futp = this->m_futp.get();
        if(!futp)
          return false;

        Si_Mutex::unique_lock lock(futp->m_mutex);
        if(futp->m_stor.index() != future_state_empty)
          return false;

        // Mark the future broken.
        futp->m_stor.template emplace<future_state_except>();
        return true;
      }

    [[noreturn]]
    void
    do_throw_no_future()
    const
      {
        ::rocket::sprintf_and_throw<::std::invalid_argument>(
          "Promise: no future associated (value type `%s`)",
          typeid(ValueT).name());
      }

  public:
    // Gets a reference to the associated future.
    // If `m_futp` is null, a new future is created and associated.
    futp<ValueT>
    future()
      {
        auto futp = this->m_futp;
        if(futp)
          return futp;

        // Create a new future if one hasn't been allocated.
        futp = ::rocket::make_refcnt<Future<ValueT>>();
        this->m_futp = futp;
        return futp;
      }

    // Value-initializes a value into the associated future.
    // If the future is not empty, `false` is returned, and there is no effect.
    bool
    set_value()
      {
        auto futp = this->m_futp.get();
        if(!futp)
          this->do_throw_no_future();

        Si_Mutex::unique_lock lock(futp->m_mutex);
        if(futp->m_stor.index() != future_state_empty)
          return false;

        // Construct a new value in the future.
        futp->m_stor.template emplace<future_state_value>();
        return true;
      }

    // Puts a value into the associated future.
    // If the future is not empty, `false` is returned, and there is no effect.
    template<typename... ParamsT,
    ROCKET_DISABLE_IF(::std::is_void<typename ::std::conditional<
                               sizeof...(ParamsT), ValueT, ValueT>::type>::value)>
    bool
    set_value(ParamsT&&... params)
      {
        auto futp = this->m_futp.get();
        if(!futp)
          this->do_throw_no_future();

        Si_Mutex::unique_lock lock(futp->m_mutex);
        if(futp->m_stor.index() != future_state_empty)
          return false;

        // Construct a new value in the future.
        futp->m_stor.template emplace<future_state_value>(
                                ::std::forward<ParamsT>(params)...);
        return true;
      }

    // Puts an exception into the associated future.
    // If the future is not empty, `false` is returned, and there is no effect.
    bool
    set_exception(const ::std::exception_ptr& eptr_opt)
      {
        auto futp = this->m_futp.get();
        if(!futp)
          this->do_throw_no_future();

        // Get a pointer to the exception to set.
        // If the user passes a null pointer, the current exception is used.
        auto eptr = eptr_opt;
        if(!eptr)
          eptr = ::std::current_exception();

        if(!eptr)
          ::rocket::sprintf_and_throw<::std::invalid_argument>(
            "Promise: no current exception (value type `%s`)",
            typeid(ValueT).name());

        // Check future state.
        Si_Mutex::unique_lock lock(futp->m_mutex);
        if(futp->m_stor.index() != future_state_empty)
          return false;

        // Construct a exception pointer in the future.
        futp->m_stor.template emplace<future_state_except>(
                                ::std::move(eptr));
        return true;
      }
  };

}  // namespace poseidon

#endif
<commit_msg>core/promise: Cleanup<commit_after>// This file is part of Poseidon.
// Copyleft 2020, LH_Mouse. All wrongs reserved.

#ifndef POSEIDON_CORE_PROMISE_HPP_
#define POSEIDON_CORE_PROMISE_HPP_

#include "future.hpp"

namespace poseidon {

template<typename ValueT>
class Promise
  {
    friend Future<ValueT>;

  private:
    rcptr<Future<ValueT>> m_futp;

  public:
    Promise()
    noexcept
      { }

    Promise(Promise&& other)
    noexcept
      : m_futp(::std::move(other.m_futp))
      { }

    Promise&
    operator=(Promise&& other)
    noexcept
      {
        if(this->m_futp == other.m_futp)
          return *this;

        this->do_dispose();
        this->m_futp = ::std::move(other.m_futp);
        return *this;
      }

    ~Promise()
      { this->do_dispose();  }

  private:
    bool
    do_dispose()
    noexcept
      {
        auto futp = this->m_futp.get();
        if(!futp)
          return false;

        Si_Mutex::unique_lock lock(futp->m_mutex);
        if(futp->m_stor.index() != future_state_empty)
          return false;

        // Mark the future broken.
        futp->m_stor.template emplace<future_state_except>();
        return true;
      }

    [[noreturn]]
    void
    do_throw_no_future()
    const
      {
        ::rocket::sprintf_and_throw<::std::invalid_argument>(
          "Promise: no future associated (value type `%s`)",
          typeid(ValueT).name());
      }

  public:
    // Gets a reference to the associated future.
    // If `m_futp` is null, a new future is created and associated.
    futp<ValueT>
    future()
      {
        auto futp = this->m_futp;
        if(futp)
          return futp;

        // Create a new future if one hasn't been allocated.
        futp = ::rocket::make_refcnt<Future<ValueT>>();
        this->m_futp = futp;
        return futp;
      }

    // Puts a value into the associated future.
    // If the future is not empty, `false` is returned, and there is no effect.
    template<typename... ParamsT,
    ROCKET_DISABLE_IF(::std::is_void<ValueT>::type && sizeof...(ParamsT))>
    bool
    set_value(ParamsT&&... params)
      {
        auto futp = this->m_futp.get();
        if(!futp)
          this->do_throw_no_future();

        Si_Mutex::unique_lock lock(futp->m_mutex);
        if(futp->m_stor.index() != future_state_empty)
          return false;

        // Construct a new value in the future.
        futp->m_stor.template emplace<future_state_value>(
                                ::std::forward<ParamsT>(params)...);
        return true;
      }

    // Puts an exception into the associated future.
    // If the future is not empty, `false` is returned, and there is no effect.
    bool
    set_exception(const ::std::exception_ptr& eptr_opt)
      {
        auto futp = this->m_futp.get();
        if(!futp)
          this->do_throw_no_future();

        // Get a pointer to the exception to set.
        // If the user passes a null pointer, the current exception is used.
        auto eptr = eptr_opt;
        if(!eptr)
          eptr = ::std::current_exception();

        if(!eptr)
          ::rocket::sprintf_and_throw<::std::invalid_argument>(
            "Promise: no current exception (value type `%s`)",
            typeid(ValueT).name());

        // Check future state.
        Si_Mutex::unique_lock lock(futp->m_mutex);
        if(futp->m_stor.index() != future_state_empty)
          return false;

        // Construct a exception pointer in the future.
        futp->m_stor.template emplace<future_state_except>(
                                ::std::move(eptr));
        return true;
      }
  };

}  // namespace poseidon

#endif
<|endoftext|>


<commit_before>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "packageinstalljob.h"
#include "session.h"

#include <QDBusInterface>
#include <QDebug>
#include <QFile>

#include <KGlobal>
#include <KService>
#include <KServiceTypeTrader>
#include <KStandardDirs>
#include <Plasma/Package>

using namespace Bodega;

PackageInstallJob::PackageInstallJob(QNetworkReply *reply, Session *session)
    : InstallJob(reply, session)
{
}

PackageInstallJob::~PackageInstallJob()
{
}

void PackageInstallJob::downloadFinished(const QString &packageFile)
{
    //Figure out the type of package
    QString type;
    QString packageRoot;
    QString servicePrefix;
    Plasma::PackageStructure *installer = 0;
    // Check type for common plasma packages
    Plasma::PackageStructure package;
    package.setPath(packageFile);
    QString serviceType = package.metadata().serviceType();
    if (!serviceType.isEmpty()) {
        if (serviceType.contains(QLatin1String("Plasma/Applet")) ||
            serviceType.contains(QLatin1String("Plasma/PopupApplet")) ||
            serviceType.contains(QLatin1String("Plasma/Containment"))) {
            type = QLatin1String("plasmoid");
        } else if (serviceType == QLatin1String("Plasma/DataEngine")) {
            type = QLatin1String("dataengine");
        } else if (serviceType == QLatin1String("Plasma/Runner")) {
            type = QLatin1String("runner");
        } else if (serviceType == QLatin1String("Plasma/Wallpaper")) {
            // This also changes type to wallpaperplugin when --type wallpaper
            // was specified and we have wallpaper plugin package (instead of
            // wallpaper image package)
            type = QLatin1String("wallpaperplugin");
        } else {
            type = serviceType;
            qDebug() << "fallthrough type is" << serviceType;
        }
    }

    if (type == QLatin1String("plasmoid")) {
        packageRoot = QLatin1String("plasma/plasmoids/");
        servicePrefix = QLatin1String("plasma-applet-");
    } else if (type == QLatin1String("theme")) {
        packageRoot = QLatin1String("desktoptheme/");
    } else if (type == QLatin1String("wallpaper")) {
        packageRoot = QLatin1String("wallpapers/");
    } else if (type == QLatin1String("dataengine")) {
        packageRoot = QLatin1String("plasma/dataengines/");
        servicePrefix = QLatin1String("plasma-dataengine-");
    } else if (type == QLatin1String("runner")) {
        packageRoot = QLatin1String("plasma/runners/");
        servicePrefix = QLatin1String("plasma-runner-");
    } else if (type == QLatin1String("wallpaperplugin")) {
        packageRoot = QLatin1String("plasma/wallpapers/");
        servicePrefix = QLatin1String("plasma-wallpaper-");
    } else if (type == QLatin1String("layout-template")) {
        packageRoot = QLatin1String("plasma/layout-templates/");
        servicePrefix = QLatin1String("plasma-layout-");
    } else if (type == QLatin1String("kwineffect")) {
        packageRoot = QLatin1String("kwin/effects/");
        servicePrefix = QLatin1String("kwin-effect-");
    } else if (type == QLatin1String("windowswitcher")) {
        packageRoot = QLatin1String("kwin/tabbox/");
        servicePrefix = QLatin1String("kwin-windowswitcher-");
    } else if (type == QLatin1String("kwinscript")) {
        packageRoot = QLatin1String("kwin/scripts/");
        servicePrefix = QLatin1String("kwin-script-");
    } else {
        const QString constraint = QString(QLatin1String("[X-KDE-PluginInfo-Name] == '%1'")).arg(type);
        KService::List offers = KServiceTypeTrader::self()->query(QLatin1String("Plasma/PackageStructure"), constraint);
        if (offers.isEmpty()) {
            setError(Error(Error::Session,
                       QLatin1String("package/01"),
                       tr("Install failed"),
                       tr(QString(QLatin1String("Could not find a suitable installer for package of type %1")).arg(type).toLatin1())));
            return;
        }

        KService::Ptr offer = offers.first();
        QString error;
        installer = offer->createInstance<Plasma::PackageStructure>(0, QVariantList(), &error);

        if (!installer) {
            setError(Error(Error::Session,
                       QLatin1String("package/02"),
                       tr("Install failed"),
                       tr(QString(QLatin1String("Could not load installer for package of type %1. Error reported was: %2")).arg(type).arg(error).toLatin1())));
            return;
        }

        packageRoot = installer->defaultPackageRoot();
    }

    // install, remove or upgrade
    if (!installer) {
        installer = new Plasma::PackageStructure();
        installer->setServicePrefix(servicePrefix);
    }

    packageRoot = KStandardDirs::locateLocal("data", packageRoot);

    if (installer->installPackage(packageFile, packageRoot)) {
        qDebug() << "Successfully installed" << packageFile;
    } else {
        setError(Error(Error::Session,
                       QLatin1String("package/02"),
                       tr("Install failed"),
                       tr(QString::fromLatin1("Installation of %1 failed.").arg(packageFile).toLatin1())));
        delete installer;
        return;
    }

    QDBusInterface dbus(QLatin1String("org.kde.kded"), QLatin1String("/kbuildsycoca"), QLatin1String("org.kde.kbuildsycoca"));
    dbus.call(QDBus::NoBlock, QLatin1String("recreate"));

    //Delete the downloaded package
    QFile f(packageFile);
    f.remove();
    setFinished();
}

#include "packageinstalljob.moc"
<commit_msg>simplify a bit<commit_after>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "packageinstalljob.h"
#include "session.h"

#include <QDBusInterface>
#include <QDebug>
#include <QFile>

#include <KGlobal>
#include <KService>
#include <KServiceTypeTrader>
#include <KStandardDirs>
#include <Plasma/Package>

using namespace Bodega;

PackageInstallJob::PackageInstallJob(QNetworkReply *reply, Session *session)
    : InstallJob(reply, session)
{
}

PackageInstallJob::~PackageInstallJob()
{
}

void PackageInstallJob::downloadFinished(const QString &packageFile)
{
    //Figure out the type of package
    QString type;
    QString packageRoot;
    QString servicePrefix;
    Plasma::PackageStructure *installer = 0;
    // Check type for common plasma packages
    Plasma::PackageStructure package;
    package.setPath(packageFile);
    QString serviceType = package.metadata().serviceType();
    if (!serviceType.isEmpty()) {
        if (serviceType.contains(QLatin1String("Plasma/Applet")) ||
            serviceType.contains(QLatin1String("Plasma/PopupApplet")) ||
            serviceType.contains(QLatin1String("Plasma/Containment"))) {
            type = QLatin1String("plasmoid");
        } else if (serviceType == QLatin1String("Plasma/DataEngine")) {
            type = QLatin1String("dataengine");
        } else if (serviceType == QLatin1String("Plasma/Runner")) {
            type = QLatin1String("runner");
        } else if (serviceType == QLatin1String("Plasma/Wallpaper")) {
            // This also changes type to wallpaperplugin when --type wallpaper
            // was specified and we have wallpaper plugin package (instead of
            // wallpaper image package)
            type = QLatin1String("wallpaperplugin");
        } else {
            type = serviceType;
            qDebug() << "fallthrough type is" << serviceType;
        }
    }

    if (type == QLatin1String("plasmoid")) {
        packageRoot = QLatin1String("plasma/plasmoids/");
        servicePrefix = QLatin1String("plasma-applet-");
    } else if (type == QLatin1String("theme")) {
        packageRoot = QLatin1String("desktoptheme/");
    } else if (type == QLatin1String("wallpaper")) {
        packageRoot = QLatin1String("wallpapers/");
    } else if (type == QLatin1String("dataengine")) {
        packageRoot = QLatin1String("plasma/dataengines/");
        servicePrefix = QLatin1String("plasma-dataengine-");
    } else if (type == QLatin1String("runner")) {
        packageRoot = QLatin1String("plasma/runners/");
        servicePrefix = QLatin1String("plasma-runner-");
    } else if (type == QLatin1String("wallpaperplugin")) {
        packageRoot = QLatin1String("plasma/wallpapers/");
        servicePrefix = QLatin1String("plasma-wallpaper-");
    } else if (type == QLatin1String("layout-template")) {
        packageRoot = QLatin1String("plasma/layout-templates/");
        servicePrefix = QLatin1String("plasma-layout-");
    } else if (type == QLatin1String("kwineffect")) {
        packageRoot = QLatin1String("kwin/effects/");
        servicePrefix = QLatin1String("kwin-effect-");
    } else if (type == QLatin1String("windowswitcher")) {
        packageRoot = QLatin1String("kwin/tabbox/");
        servicePrefix = QLatin1String("kwin-windowswitcher-");
    } else if (type == QLatin1String("kwinscript")) {
        packageRoot = QLatin1String("kwin/scripts/");
        servicePrefix = QLatin1String("kwin-script-");
    } else {
        const QString constraint = QString(QLatin1String("[X-KDE-PluginInfo-Name] == '%1'")).arg(type);
        KService::List offers = KServiceTypeTrader::self()->query(QLatin1String("Plasma/PackageStructure"), constraint);
        if (offers.isEmpty()) {
            setError(Error(Error::Session,
                       QLatin1String("package/01"),
                       tr("Install failed"),
                       tr(QString::fromLatin1("Could not find a suitable installer for package of type %1").arg(type).toLatin1())));
            return;
        }

        KService::Ptr offer = offers.first();
        QString error;
        installer = offer->createInstance<Plasma::PackageStructure>(0, QVariantList(), &error);

        if (!installer) {
            setError(Error(Error::Session,
                       QLatin1String("package/02"),
                       tr("Install failed"),
                       tr(QString::fromLatin1("Could not load installer for package of type %1. Error reported was: %2").arg(type).arg(error).toLatin1())));
            return;
        }

        packageRoot = installer->defaultPackageRoot();
    }

    // install, remove or upgrade
    if (!installer) {
        installer = new Plasma::PackageStructure();
        installer->setServicePrefix(servicePrefix);
    }

    packageRoot = KStandardDirs::locateLocal("data", packageRoot);

    if (installer->installPackage(packageFile, packageRoot)) {
        qDebug() << "Successfully installed" << packageFile;
    } else {
        setError(Error(Error::Session,
                       QLatin1String("package/02"),
                       tr("Install failed"),
                       tr(QString::fromLatin1("Installation of %1 failed.").arg(packageFile).toLatin1())));
        delete installer;
        return;
    }

    QDBusInterface dbus(QLatin1String("org.kde.kded"), QLatin1String("/kbuildsycoca"), QLatin1String("org.kde.kbuildsycoca"));
    dbus.call(QDBus::NoBlock, QLatin1String("recreate"));

    //Delete the downloaded package
    QFile f(packageFile);
    f.remove();
    setFinished();
}

#include "packageinstalljob.moc"
<|endoftext|>


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

#include "libcef/browser/url_request_context_getter_impl.h"

#if defined(OS_WIN)
#include <winhttp.h>
#endif
#include <string>
#include <vector>

#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/browser/scheme_handler.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/url_network_delegate.h"
#include "libcef/browser/url_request_interceptor.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/content_client.h"

#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
#include "chrome/browser/net/proxy_service_factory.h"
#include "content/browser/net/sqlite_persistent_cookie_store.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_crypto_delegate.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/dns/host_resolver.h"
#include "net/ftp/ftp_network_layer.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_util.h"
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_service.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/default_channel_id_store.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "url/url_constants.h"
#include "net/url_request/http_user_agent_settings.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "net/url_request/url_request_intercepting_job_factory.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_job_manager.h"

#if defined(USE_NSS)
#include "net/ocsp/nss_ocsp.h"
#endif

using content::BrowserThread;

#if defined(OS_WIN)
#pragma comment(lib, "winhttp.lib")
#endif

namespace {

// An implementation of |HttpUserAgentSettings| that provides a static
// HTTP Accept-Language header value and uses |content::GetUserAgent|
// to provide the HTTP User-Agent header value.
class CefHttpUserAgentSettings : public net::HttpUserAgentSettings {
 public:
  explicit CefHttpUserAgentSettings(const std::string& raw_language_list)
      : http_accept_language_(net::HttpUtil::GenerateAcceptLanguageHeader(
            raw_language_list)) {
    CEF_REQUIRE_IOT();
  }

  // net::HttpUserAgentSettings implementation
  std::string GetAcceptLanguage() const override {
    CEF_REQUIRE_IOT();
    return http_accept_language_;
  }

  std::string GetUserAgent() const override {
    CEF_REQUIRE_IOT();
    return CefContentClient::Get()->GetUserAgent();
  }

 private:
  const std::string http_accept_language_;

  DISALLOW_COPY_AND_ASSIGN(CefHttpUserAgentSettings);
};

}  // namespace

CefURLRequestContextGetterImpl::CefURLRequestContextGetterImpl(
    base::MessageLoop* io_loop,
    base::MessageLoop* file_loop,
    content::ProtocolHandlerMap* protocol_handlers,
    content::URLRequestInterceptorScopedVector request_interceptors)
    : io_loop_(io_loop),
      file_loop_(file_loop),
      request_interceptors_(request_interceptors.Pass()) {
  // Must first be created on the UI thread.
  CEF_REQUIRE_UIT();

  std::swap(protocol_handlers_, *protocol_handlers);
}

CefURLRequestContextGetterImpl::~CefURLRequestContextGetterImpl() {
  CEF_REQUIRE_IOT();

  // Delete the ProxyService object here so that any pending requests will be
  // canceled before the associated URLRequestContext is destroyed in this
  // object's destructor.
  storage_->set_proxy_service(NULL);
}

net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() {
  CEF_REQUIRE_IOT();

  if (!url_request_context_.get()) {
    const base::FilePath& cache_path = CefContext::Get()->cache_path();
    const base::CommandLine* command_line =
        base::CommandLine::ForCurrentProcess();
    const CefSettings& settings = CefContext::Get()->settings();

    url_request_context_.reset(new CefURLRequestContextImpl());
    storage_.reset(
        new net::URLRequestContextStorage(url_request_context_.get()));

    bool persist_session_cookies =
        (settings.persist_session_cookies ||
         command_line->HasSwitch(switches::kPersistSessionCookies));
    SetCookieStoragePath(cache_path, persist_session_cookies);

    storage_->set_network_delegate(new CefNetworkDelegate);

    storage_->set_channel_id_service(make_scoped_ptr(
        new net::ChannelIDService(
            new net::DefaultChannelIDStore(NULL),
            base::WorkerPool::GetTaskRunner(true))));

    std::string accept_language;
    if (settings.accept_language_list.length > 0) {
      accept_language =
          net::HttpUtil::GenerateAcceptLanguageHeader(
              CefString(&settings.accept_language_list));
    } else {
      accept_language = "en-US,en";
    }
    storage_->set_http_user_agent_settings(
        new CefHttpUserAgentSettings(accept_language));

    storage_->set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
    storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
    storage_->set_transport_security_state(new net::TransportSecurityState);

    scoped_ptr<net::ProxyService> system_proxy_service;
    system_proxy_service.reset(
        ProxyServiceFactory::CreateProxyService(
            NULL,
            url_request_context_.get(),
            url_request_context_->network_delegate(),
            CefContentBrowserClient::Get()->proxy_config_service().release(),
            *command_line,
            true));
    storage_->set_proxy_service(system_proxy_service.release());

    storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);

    // Add support for single sign-on.
    url_security_manager_.reset(net::URLSecurityManager::Create(NULL, NULL));

    std::vector<std::string> supported_schemes;
    supported_schemes.push_back("basic");
    supported_schemes.push_back("digest");
    supported_schemes.push_back("ntlm");
    supported_schemes.push_back("negotiate");

    storage_->set_http_auth_handler_factory(
        net::HttpAuthHandlerRegistryFactory::Create(
            supported_schemes,
            url_security_manager_.get(),
            url_request_context_->host_resolver(),
            std::string(),
            false,
            false));
    storage_->set_http_server_properties(
        make_scoped_ptr<net::HttpServerProperties>(
            new net::HttpServerPropertiesImpl));

    net::HttpCache::DefaultBackend* main_backend =
        new net::HttpCache::DefaultBackend(
            cache_path.empty() ? net::MEMORY_CACHE : net::DISK_CACHE,
            net::CACHE_BACKEND_DEFAULT,
            cache_path,
            0,
            BrowserThread::GetMessageLoopProxyForThread(
                BrowserThread::CACHE));

    net::HttpNetworkSession::Params network_session_params;
    network_session_params.host_resolver =
        url_request_context_->host_resolver();
    network_session_params.cert_verifier =
        url_request_context_->cert_verifier();
    network_session_params.transport_security_state =
        url_request_context_->transport_security_state();
    network_session_params.channel_id_service =
        url_request_context_->channel_id_service();
    network_session_params.proxy_service =
        url_request_context_->proxy_service();
    network_session_params.ssl_config_service =
        url_request_context_->ssl_config_service();
    network_session_params.http_auth_handler_factory =
        url_request_context_->http_auth_handler_factory();
    network_session_params.network_delegate =
        url_request_context_->network_delegate();
    network_session_params.http_server_properties =
        url_request_context_->http_server_properties();
    network_session_params.ignore_certificate_errors =
        (settings.ignore_certificate_errors ||
         command_line->HasSwitch(switches::kIgnoreCertificateErrors));

    net::HttpCache* main_cache = new net::HttpCache(network_session_params,
                                                    main_backend);
    storage_->set_http_transaction_factory(main_cache);

#if !defined(DISABLE_FTP_SUPPORT)
    ftp_transaction_factory_.reset(
        new net::FtpNetworkLayer(network_session_params.host_resolver));
#endif

    scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
        new net::URLRequestJobFactoryImpl());
    job_factory_impl_ = job_factory.get();

    scheme::InstallInternalProtectedHandlers(job_factory.get(),
                                             &protocol_handlers_,
                                             ftp_transaction_factory_.get());
    protocol_handlers_.clear();

    request_interceptors_.push_back(new CefRequestInterceptor());

    // Set up interceptors in the reverse order.
    scoped_ptr<net::URLRequestJobFactory> top_job_factory =
        job_factory.Pass();
    for (content::URLRequestInterceptorScopedVector::reverse_iterator i =
             request_interceptors_.rbegin();
         i != request_interceptors_.rend();
         ++i) {
      top_job_factory.reset(new net::URLRequestInterceptingJobFactory(
          top_job_factory.Pass(), make_scoped_ptr(*i)));
    }
    request_interceptors_.weak_clear();

    storage_->set_job_factory(top_job_factory.release());

#if defined(USE_NSS)
    net::SetURLRequestContextForNSSHttpIO(url_request_context_.get());
#endif
  }

  return url_request_context_.get();
}

scoped_refptr<base::SingleThreadTaskRunner>
    CefURLRequestContextGetterImpl::GetNetworkTaskRunner() const {
  return BrowserThread::GetMessageLoopProxyForThread(CEF_IOT);
}

net::HostResolver* CefURLRequestContextGetterImpl::GetHostResolver() const {
  return url_request_context_->host_resolver();
}

void CefURLRequestContextGetterImpl::SetCookieStoragePath(
    const base::FilePath& path,
    bool persist_session_cookies) {
  CEF_REQUIRE_IOT();

  if (url_request_context_->cookie_store() &&
      ((cookie_store_path_.empty() && path.empty()) ||
       cookie_store_path_ == path)) {
    // The path has not changed so don't do anything.
    return;
  }

  scoped_refptr<content::SQLitePersistentCookieStore> persistent_store;
  if (!path.empty()) {
    // TODO(cef): Move directory creation to the blocking pool instead of
    // allowing file IO on this thread.
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    if (base::DirectoryExists(path) ||
        base::CreateDirectory(path)) {
      const base::FilePath& cookie_path = path.AppendASCII("Cookies");
      persistent_store =
          new content::SQLitePersistentCookieStore(
              cookie_path,
              BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
              BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
              persist_session_cookies,
              NULL,
              NULL);
    } else {
      NOTREACHED() << "The cookie storage directory could not be created";
    }
  }

  // Set the new cookie store that will be used for all new requests. The old
  // cookie store, if any, will be automatically flushed and closed when no
  // longer referenced.
  scoped_refptr<net::CookieMonster> cookie_monster =
      new net::CookieMonster(persistent_store.get(), NULL);
  storage_->set_cookie_store(cookie_monster.get());
  if (persistent_store.get() && persist_session_cookies)
      cookie_monster->SetPersistSessionCookies(true);
  cookie_store_path_ = path;

  // Restore the previously supported schemes.
  SetCookieSupportedSchemes(cookie_supported_schemes_);
}

void CefURLRequestContextGetterImpl::SetCookieSupportedSchemes(
    const std::vector<std::string>& schemes) {
  CEF_REQUIRE_IOT();

  cookie_supported_schemes_ = schemes;

  if (cookie_supported_schemes_.empty()) {
    cookie_supported_schemes_.push_back("http");
    cookie_supported_schemes_.push_back("https");
  }

  std::set<std::string> scheme_set;
  std::vector<std::string>::const_iterator it =
      cookie_supported_schemes_.begin();
  for (; it != cookie_supported_schemes_.end(); ++it)
    scheme_set.insert(*it);

  const char** arr = new const char*[scheme_set.size()];
  std::set<std::string>::const_iterator it2 = scheme_set.begin();
  for (int i = 0; it2 != scheme_set.end(); ++it2, ++i)
    arr[i] = it2->c_str();

  url_request_context_->cookie_store()->GetCookieMonster()->
      SetCookieableSchemes(arr, scheme_set.size());

  delete [] arr;
}

void CefURLRequestContextGetterImpl::CreateProxyConfigService() {
  if (proxy_config_service_.get())
    return;

  proxy_config_service_.reset(
      net::ProxyService::CreateSystemProxyConfigService(
          io_loop_->message_loop_proxy(), file_loop_->message_loop_proxy()));
}
<commit_msg>Support configuration of the "Accept-Language" HTTP header globally or on a per-browser basis using new CefSettings.accept_language_list and CefBrowserSettings.accept_language_list members (issue #318).<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "libcef/browser/url_request_context_getter_impl.h"

#if defined(OS_WIN)
#include <winhttp.h>
#endif
#include <string>
#include <vector>

#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/browser/scheme_handler.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/url_network_delegate.h"
#include "libcef/browser/url_request_interceptor.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/content_client.h"

#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
#include "chrome/browser/net/proxy_service_factory.h"
#include "content/browser/net/sqlite_persistent_cookie_store.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_crypto_delegate.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/dns/host_resolver.h"
#include "net/ftp/ftp_network_layer.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_util.h"
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_service.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/default_channel_id_store.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "url/url_constants.h"
#include "net/url_request/http_user_agent_settings.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "net/url_request/url_request_intercepting_job_factory.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_job_manager.h"

#if defined(USE_NSS)
#include "net/ocsp/nss_ocsp.h"
#endif

using content::BrowserThread;

#if defined(OS_WIN)
#pragma comment(lib, "winhttp.lib")
#endif

namespace {

// An implementation of |HttpUserAgentSettings| that provides a static
// HTTP Accept-Language header value and uses |content::GetUserAgent|
// to provide the HTTP User-Agent header value.
class CefHttpUserAgentSettings : public net::HttpUserAgentSettings {
 public:
  explicit CefHttpUserAgentSettings(const std::string& raw_language_list)
      : http_accept_language_(net::HttpUtil::GenerateAcceptLanguageHeader(
            raw_language_list)) {
    CEF_REQUIRE_IOT();
  }

  // net::HttpUserAgentSettings implementation
  std::string GetAcceptLanguage() const override {
    CEF_REQUIRE_IOT();
    return http_accept_language_;
  }

  std::string GetUserAgent() const override {
    CEF_REQUIRE_IOT();
    return CefContentClient::Get()->GetUserAgent();
  }

 private:
  const std::string http_accept_language_;

  DISALLOW_COPY_AND_ASSIGN(CefHttpUserAgentSettings);
};

}  // namespace

CefURLRequestContextGetterImpl::CefURLRequestContextGetterImpl(
    base::MessageLoop* io_loop,
    base::MessageLoop* file_loop,
    content::ProtocolHandlerMap* protocol_handlers,
    content::URLRequestInterceptorScopedVector request_interceptors)
    : io_loop_(io_loop),
      file_loop_(file_loop),
      request_interceptors_(request_interceptors.Pass()) {
  // Must first be created on the UI thread.
  CEF_REQUIRE_UIT();

  std::swap(protocol_handlers_, *protocol_handlers);
}

CefURLRequestContextGetterImpl::~CefURLRequestContextGetterImpl() {
  CEF_REQUIRE_IOT();

  // Delete the ProxyService object here so that any pending requests will be
  // canceled before the associated URLRequestContext is destroyed in this
  // object's destructor.
  storage_->set_proxy_service(NULL);
}

net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() {
  CEF_REQUIRE_IOT();

  if (!url_request_context_.get()) {
    const base::FilePath& cache_path = CefContext::Get()->cache_path();
    const base::CommandLine* command_line =
        base::CommandLine::ForCurrentProcess();
    const CefSettings& settings = CefContext::Get()->settings();

    url_request_context_.reset(new CefURLRequestContextImpl());
    storage_.reset(
        new net::URLRequestContextStorage(url_request_context_.get()));

    bool persist_session_cookies =
        (settings.persist_session_cookies ||
         command_line->HasSwitch(switches::kPersistSessionCookies));
    SetCookieStoragePath(cache_path, persist_session_cookies);

    storage_->set_network_delegate(new CefNetworkDelegate);

    storage_->set_channel_id_service(make_scoped_ptr(
        new net::ChannelIDService(
            new net::DefaultChannelIDStore(NULL),
            base::WorkerPool::GetTaskRunner(true))));

    const std::string& accept_language =
        settings.accept_language_list.length > 0 ?
            CefString(&settings.accept_language_list): "en-US,en";
    storage_->set_http_user_agent_settings(
        new CefHttpUserAgentSettings(accept_language));

    storage_->set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
    storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
    storage_->set_transport_security_state(new net::TransportSecurityState);

    scoped_ptr<net::ProxyService> system_proxy_service;
    system_proxy_service.reset(
        ProxyServiceFactory::CreateProxyService(
            NULL,
            url_request_context_.get(),
            url_request_context_->network_delegate(),
            CefContentBrowserClient::Get()->proxy_config_service().release(),
            *command_line,
            true));
    storage_->set_proxy_service(system_proxy_service.release());

    storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);

    // Add support for single sign-on.
    url_security_manager_.reset(net::URLSecurityManager::Create(NULL, NULL));

    std::vector<std::string> supported_schemes;
    supported_schemes.push_back("basic");
    supported_schemes.push_back("digest");
    supported_schemes.push_back("ntlm");
    supported_schemes.push_back("negotiate");

    storage_->set_http_auth_handler_factory(
        net::HttpAuthHandlerRegistryFactory::Create(
            supported_schemes,
            url_security_manager_.get(),
            url_request_context_->host_resolver(),
            std::string(),
            false,
            false));
    storage_->set_http_server_properties(
        make_scoped_ptr<net::HttpServerProperties>(
            new net::HttpServerPropertiesImpl));

    net::HttpCache::DefaultBackend* main_backend =
        new net::HttpCache::DefaultBackend(
            cache_path.empty() ? net::MEMORY_CACHE : net::DISK_CACHE,
            net::CACHE_BACKEND_DEFAULT,
            cache_path,
            0,
            BrowserThread::GetMessageLoopProxyForThread(
                BrowserThread::CACHE));

    net::HttpNetworkSession::Params network_session_params;
    network_session_params.host_resolver =
        url_request_context_->host_resolver();
    network_session_params.cert_verifier =
        url_request_context_->cert_verifier();
    network_session_params.transport_security_state =
        url_request_context_->transport_security_state();
    network_session_params.channel_id_service =
        url_request_context_->channel_id_service();
    network_session_params.proxy_service =
        url_request_context_->proxy_service();
    network_session_params.ssl_config_service =
        url_request_context_->ssl_config_service();
    network_session_params.http_auth_handler_factory =
        url_request_context_->http_auth_handler_factory();
    network_session_params.network_delegate =
        url_request_context_->network_delegate();
    network_session_params.http_server_properties =
        url_request_context_->http_server_properties();
    network_session_params.ignore_certificate_errors =
        (settings.ignore_certificate_errors ||
         command_line->HasSwitch(switches::kIgnoreCertificateErrors));

    net::HttpCache* main_cache = new net::HttpCache(network_session_params,
                                                    main_backend);
    storage_->set_http_transaction_factory(main_cache);

#if !defined(DISABLE_FTP_SUPPORT)
    ftp_transaction_factory_.reset(
        new net::FtpNetworkLayer(network_session_params.host_resolver));
#endif

    scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
        new net::URLRequestJobFactoryImpl());
    job_factory_impl_ = job_factory.get();

    scheme::InstallInternalProtectedHandlers(job_factory.get(),
                                             &protocol_handlers_,
                                             ftp_transaction_factory_.get());
    protocol_handlers_.clear();

    request_interceptors_.push_back(new CefRequestInterceptor());

    // Set up interceptors in the reverse order.
    scoped_ptr<net::URLRequestJobFactory> top_job_factory =
        job_factory.Pass();
    for (content::URLRequestInterceptorScopedVector::reverse_iterator i =
             request_interceptors_.rbegin();
         i != request_interceptors_.rend();
         ++i) {
      top_job_factory.reset(new net::URLRequestInterceptingJobFactory(
          top_job_factory.Pass(), make_scoped_ptr(*i)));
    }
    request_interceptors_.weak_clear();

    storage_->set_job_factory(top_job_factory.release());

#if defined(USE_NSS)
    net::SetURLRequestContextForNSSHttpIO(url_request_context_.get());
#endif
  }

  return url_request_context_.get();
}

scoped_refptr<base::SingleThreadTaskRunner>
    CefURLRequestContextGetterImpl::GetNetworkTaskRunner() const {
  return BrowserThread::GetMessageLoopProxyForThread(CEF_IOT);
}

net::HostResolver* CefURLRequestContextGetterImpl::GetHostResolver() const {
  return url_request_context_->host_resolver();
}

void CefURLRequestContextGetterImpl::SetCookieStoragePath(
    const base::FilePath& path,
    bool persist_session_cookies) {
  CEF_REQUIRE_IOT();

  if (url_request_context_->cookie_store() &&
      ((cookie_store_path_.empty() && path.empty()) ||
       cookie_store_path_ == path)) {
    // The path has not changed so don't do anything.
    return;
  }

  scoped_refptr<content::SQLitePersistentCookieStore> persistent_store;
  if (!path.empty()) {
    // TODO(cef): Move directory creation to the blocking pool instead of
    // allowing file IO on this thread.
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    if (base::DirectoryExists(path) ||
        base::CreateDirectory(path)) {
      const base::FilePath& cookie_path = path.AppendASCII("Cookies");
      persistent_store =
          new content::SQLitePersistentCookieStore(
              cookie_path,
              BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
              BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
              persist_session_cookies,
              NULL,
              NULL);
    } else {
      NOTREACHED() << "The cookie storage directory could not be created";
    }
  }

  // Set the new cookie store that will be used for all new requests. The old
  // cookie store, if any, will be automatically flushed and closed when no
  // longer referenced.
  scoped_refptr<net::CookieMonster> cookie_monster =
      new net::CookieMonster(persistent_store.get(), NULL);
  storage_->set_cookie_store(cookie_monster.get());
  if (persistent_store.get() && persist_session_cookies)
      cookie_monster->SetPersistSessionCookies(true);
  cookie_store_path_ = path;

  // Restore the previously supported schemes.
  SetCookieSupportedSchemes(cookie_supported_schemes_);
}

void CefURLRequestContextGetterImpl::SetCookieSupportedSchemes(
    const std::vector<std::string>& schemes) {
  CEF_REQUIRE_IOT();

  cookie_supported_schemes_ = schemes;

  if (cookie_supported_schemes_.empty()) {
    cookie_supported_schemes_.push_back("http");
    cookie_supported_schemes_.push_back("https");
  }

  std::set<std::string> scheme_set;
  std::vector<std::string>::const_iterator it =
      cookie_supported_schemes_.begin();
  for (; it != cookie_supported_schemes_.end(); ++it)
    scheme_set.insert(*it);

  const char** arr = new const char*[scheme_set.size()];
  std::set<std::string>::const_iterator it2 = scheme_set.begin();
  for (int i = 0; it2 != scheme_set.end(); ++it2, ++i)
    arr[i] = it2->c_str();

  url_request_context_->cookie_store()->GetCookieMonster()->
      SetCookieableSchemes(arr, scheme_set.size());

  delete [] arr;
}

void CefURLRequestContextGetterImpl::CreateProxyConfigService() {
  if (proxy_config_service_.get())
    return;

  proxy_config_service_.reset(
      net::ProxyService::CreateSystemProxyConfigService(
          io_loop_->message_loop_proxy(), file_loop_->message_loop_proxy()));
}
<|endoftext|>


<commit_before>/*********************************************************************
  libvideogfx/graphics/draw/pixelops.hh

  purpose:
    Single pixel operations that are applied to full bitmaps.

  notes:

  to do:

  author(s):
   - Dirk Farin, dirk.farin@gmx.de

  modifications:
   30/Jan/2002 - Dirk Farin - adapted the interface
   27/Apr/2001 - Dirk Farin - first implementation
 ********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_DRAW_PIXELOPS_HH
#define LIBVIDEOGFX_GRAPHICS_DRAW_PIXELOPS_HH

#include <libvideogfx/graphics/datatypes/bitmap.hh>

namespace videogfx {

  template <class T> void MakeAbsolute(Bitmap<T>&);
  template <class T> void Inverse(const Bitmap<T>&,T maxval);
  template <class T> void AddValues(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b);
  template <class T> void HalfPlusOffset(Bitmap<T>& bm,T offset); // p = p/2+offset

  /* dest = a-b */
  template <class T> void AbsoluteDifference(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b);
  template <class T> void ContrastBrightness(Bitmap<T>& bm,double contrast,double brightness);
  template <class T> void ClipValues(Bitmap<T>& bm,T low,T high);
  template <class T> void SearchForMinMaxValues(const Bitmap<T>& bm,T& low,T& high);
  template <class T> void StretchValues(Bitmap<T>& bm,T low,T high);

  // --------------------- implementation ------------------------

  template <class T> void MakeAbsolute(Bitmap<T>& bm)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = abs(p[y][x]);
  }

  template <class T> void Inverse(Bitmap<T>& bm,T maxval)
  {
    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    T*const* p = bm.AskFrame();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = maxval-p[y][x];
  }

  template <class T> void AddValues(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b)
  {
    const int w = a.AskWidth();
    const int h = a.AskHeight();

    dest.Create(w,h);

    T*const* pd = dest.AskFrame(); // get this pointer first, in case pd==pa or pd==pb
    const T*const* pa = a.AskFrame();
    const T*const* pb = b.AskFrame();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  pd[y][x] = (pa[y][x]+pb[y][x]); /// TODO
	}
  }

  template <class T> void AbsoluteDifference(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b)
  {
    const int w = a.AskWidth();
    const int h = a.AskHeight();

    dest.Create(w,h);

    T*const* pd = dest.AskFrame(); // get this pointer first, in case pd==pa or pd==pb
    const T*const* pa = a.AskFrame();
    const T*const* pb = b.AskFrame();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  pd[y][x] = abs(pa[y][x]-pb[y][x]); /// TODO
	}
  }

  template <class T> void ContrastBrightness(Bitmap<T>& bm,double contrast,double brightness)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = (T)(contrast*p[y][x]+brightness);
  }

  template <class T> void HalfPlusOffset(Bitmap<T>& bm,T offset)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = (T)(p[y][x]/2+offset);
  }

  template <class T> void ClipValues(Bitmap<T>& bm,T low,T high)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  if (p[y][x] < low) p[y][x]=low;
	  else if (p[y][x] > high) p[y][x]=high;
	}
  }

  template <class T> void SearchForMinMaxValues(const Bitmap<T>& bm,T& low,T& high)
  {
    const T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    low=high=p[0][0];

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  if (p[y][x] < low)  low =p[y][x];
	  if (p[y][x] > high) high=p[y][x];
	}
  }

  template <class T> void StretchValues(Bitmap<T>& bm,T low,T high)
  {
    T mini,maxi;
    SearchForMinMaxValues(bm,mini,maxi);

    ContrastBrightness(bm,1.0,-mini);
    maxi -= mini;
    mini  = 0;
    ContrastBrightness(bm,((double)(high-low))/maxi,0.0);
    maxi = high-low;
    mini = 0;

    if (low!=0) ContrastBrightness(bm,1.0,low);
    maxi = high;
    mini = low;
  }

}

#endif
<commit_msg>new pixel operation: add value to all pixels<commit_after>/*********************************************************************
  libvideogfx/graphics/draw/pixelops.hh

  purpose:
    Single pixel operations that are applied to full bitmaps.

  notes:

  to do:

  author(s):
   - Dirk Farin, dirk.farin@gmx.de

  modifications:
   30/Jan/2002 - Dirk Farin - adapted the interface
   27/Apr/2001 - Dirk Farin - first implementation
 ********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_DRAW_PIXELOPS_HH
#define LIBVIDEOGFX_GRAPHICS_DRAW_PIXELOPS_HH

#include <libvideogfx/graphics/datatypes/bitmap.hh>

namespace videogfx {

  template <class T> void MakeAbsolute(Bitmap<T>&);
  template <class T> void Inverse(const Bitmap<T>&,T maxval);
  template <class T> void AddValues(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b);
  template <class T> void Add(Bitmap<T>& dest,T val);
  template <class T> void HalfPlusOffset(Bitmap<T>& bm,T offset); // p = p/2+offset

  /* dest = a-b */
  template <class T> void AbsoluteDifference(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b);
  template <class T> void ContrastBrightness(Bitmap<T>& bm,double contrast,double brightness);
  template <class T> void ClipValues(Bitmap<T>& bm,T low,T high);
  template <class T> void SearchForMinMaxValues(const Bitmap<T>& bm,T& low,T& high);
  template <class T> void StretchValues(Bitmap<T>& bm,T low,T high);

  // --------------------- implementation ------------------------

  template <class T> void MakeAbsolute(Bitmap<T>& bm)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = abs(p[y][x]);
  }

  template <class T> void Inverse(Bitmap<T>& bm,T maxval)
  {
    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    T*const* p = bm.AskFrame();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = maxval-p[y][x];
  }

  template <class T> void Add(Bitmap<T>& dest,T val)
  {
    const int w = dest.AskWidth();
    const int h = dest.AskHeight();

    dest.Create(w,h);

    T*const* pd = dest.AskFrame(); // get this pointer first, in case pd==pa or pd==pb

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  pd[y][x] += val;
	}
  }

  template <class T> void AddValues(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b)
  {
    const int w = a.AskWidth();
    const int h = a.AskHeight();

    dest.Create(w,h);

    T*const* pd = dest.AskFrame(); // get this pointer first, in case pd==pa or pd==pb
    const T*const* pa = a.AskFrame();
    const T*const* pb = b.AskFrame();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  pd[y][x] = (pa[y][x]+pb[y][x]); /// TODO
	}
  }

  template <class T> void AbsoluteDifference(Bitmap<T>& dest,const Bitmap<T>& a,const Bitmap<T>& b)
  {
    const int w = a.AskWidth();
    const int h = a.AskHeight();

    dest.Create(w,h);

    T*const* pd = dest.AskFrame(); // get this pointer first, in case pd==pa or pd==pb
    const T*const* pa = a.AskFrame();
    const T*const* pb = b.AskFrame();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  pd[y][x] = abs(pa[y][x]-pb[y][x]); /// TODO
	}
  }

  template <class T> void ContrastBrightness(Bitmap<T>& bm,double contrast,double brightness)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = (T)(contrast*p[y][x]+brightness);
  }

  template <class T> void HalfPlusOffset(Bitmap<T>& bm,T offset)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	p[y][x] = (T)(p[y][x]/2+offset);
  }

  template <class T> void ClipValues(Bitmap<T>& bm,T low,T high)
  {
    T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  if (p[y][x] < low) p[y][x]=low;
	  else if (p[y][x] > high) p[y][x]=high;
	}
  }

  template <class T> void SearchForMinMaxValues(const Bitmap<T>& bm,T& low,T& high)
  {
    const T*const* p = bm.AskFrame();

    const int w = bm.AskWidth();
    const int h = bm.AskHeight();

    low=high=p[0][0];

    for (int y=0;y<h;y++)
      for (int x=0;x<w;x++)
	{
	  if (p[y][x] < low)  low =p[y][x];
	  if (p[y][x] > high) high=p[y][x];
	}
  }

  template <class T> void StretchValues(Bitmap<T>& bm,T low,T high)
  {
    T mini,maxi;
    SearchForMinMaxValues(bm,mini,maxi);

    ContrastBrightness(bm,1.0,-mini);
    maxi -= mini;
    mini  = 0;
    ContrastBrightness(bm,((double)(high-low))/maxi,0.0);
    maxi = high-low;
    mini = 0;

    if (low!=0) ContrastBrightness(bm,1.0,low);
    maxi = high;
    mini = low;
  }

}

#endif
<|endoftext|>