<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/extensions/extension_toolbar_model.h"

#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"

ExtensionToolbarModel::ExtensionToolbarModel(ExtensionsService* service)
    : service_(service),
      prefs_(service->profile()->GetPrefs()),
      extensions_initialized_(false) {
  DCHECK(service_);

  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
                 Source<Profile>(service_->profile()));
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 Source<Profile>(service_->profile()));
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
                 Source<Profile>(service_->profile()));
  registrar_.Add(this, NotificationType::EXTENSIONS_READY,
                 Source<Profile>(service_->profile()));

  visible_icon_count_ = prefs_->GetInteger(prefs::kExtensionToolbarSize);
}

ExtensionToolbarModel::~ExtensionToolbarModel() {
}

void ExtensionToolbarModel::DestroyingProfile() {
  registrar_.RemoveAll();
}

void ExtensionToolbarModel::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void ExtensionToolbarModel::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

void ExtensionToolbarModel::MoveBrowserAction(Extension* extension,
                                              int index) {
  ExtensionList::iterator pos = std::find(begin(), end(), extension);
  if (pos == end()) {
    NOTREACHED();
    return;
  }
  toolitems_.erase(pos);

  int i = 0;
  bool inserted = false;
  for (ExtensionList::iterator iter = begin(); iter != end(); ++iter, ++i) {
    if (i == index) {
      toolitems_.insert(iter, extension);
      inserted = true;
      break;
    }
  }

  if (!inserted) {
    DCHECK_EQ(index, static_cast<int>(toolitems_.size()));
    index = toolitems_.size();

    toolitems_.push_back(extension);
  }

  FOR_EACH_OBSERVER(Observer, observers_, BrowserActionMoved(extension, index));

  UpdatePrefs();
}

void ExtensionToolbarModel::SetVisibleIconCount(int count) {
  visible_icon_count_ = count == static_cast<int>(size()) ? -1 : count;
  prefs_->SetInteger(prefs::kExtensionToolbarSize, visible_icon_count_);
}

void ExtensionToolbarModel::Observe(NotificationType type,
                                    const NotificationSource& source,
                                    const NotificationDetails& details) {
  if (type == NotificationType::EXTENSIONS_READY) {
    InitializeExtensionList();
    return;
  }

  if (!service_->is_ready())
    return;

  Extension* extension = Details<Extension>(details).ptr();
  if (type == NotificationType::EXTENSION_LOADED) {
    AddExtension(extension);
  } else if (type == NotificationType::EXTENSION_UNLOADED ||
             type == NotificationType::EXTENSION_UNLOADED_DISABLED) {
    RemoveExtension(extension);
  } else {
    NOTREACHED() << "Received unexpected notification";
  }
}

void ExtensionToolbarModel::AddExtension(Extension* extension) {
  // We only care about extensions with browser actions.
  if (!extension->browser_action())
    return;

  if (extension->id() == last_extension_removed_ &&
      last_extension_removed_index_ < toolitems_.size()) {
    toolitems_.insert(begin() + last_extension_removed_index_, extension);
    FOR_EACH_OBSERVER(Observer, observers_,
        BrowserActionAdded(extension, last_extension_removed_index_));
  } else {
    toolitems_.push_back(extension);
    FOR_EACH_OBSERVER(Observer, observers_,
                      BrowserActionAdded(extension, toolitems_.size() - 1));
  }

  last_extension_removed_ = "";
  last_extension_removed_index_ = -1;

  UpdatePrefs();
}

void ExtensionToolbarModel::RemoveExtension(Extension* extension) {
  ExtensionList::iterator pos = std::find(begin(), end(), extension);
  if (pos == end()) {
    return;
  }

  last_extension_removed_ = extension->id();
  last_extension_removed_index_ = pos - begin();

  toolitems_.erase(pos);
  FOR_EACH_OBSERVER(Observer, observers_,
                    BrowserActionRemoved(extension));

  UpdatePrefs();
}

// Combine the currently enabled extensions that have browser actions (which
// we get from the ExtensionsService) with the ordering we get from the
// pref service. For robustness we use a somewhat inefficient process:
// 1. Create a vector of extensions sorted by their pref values. This vector may
// have holes.
// 2. Create a vector of extensions that did not have a pref value.
// 3. Remove holes from the sorted vector and append the unsorted vector.
void ExtensionToolbarModel::InitializeExtensionList() {
  DCHECK(service_->is_ready());

  std::vector<std::string> pref_order = service_->extension_prefs()->
      GetToolbarOrder();
  // Items that have a pref for their position.
  ExtensionList sorted;
  sorted.resize(pref_order.size(), NULL);
  // The items that don't have a pref for their position.
  ExtensionList unsorted;

  // Create the lists.
  for (size_t i = 0; i < service_->extensions()->size(); ++i) {
    Extension* extension = service_->extensions()->at(i);
    if (!extension->browser_action())
      continue;

    std::vector<std::string>::iterator pos =
        std::find(pref_order.begin(), pref_order.end(), extension->id());
    if (pos != pref_order.end()) {
      int index = std::distance(pref_order.begin(), pos);
      sorted[index] = extension;
    } else {
      unsorted.push_back(extension);
    }
  }

  // Merge the lists.
  toolitems_.reserve(sorted.size() + unsorted.size());
  for (ExtensionList::iterator iter = sorted.begin();
       iter != sorted.end(); ++iter) {
    if (*iter != NULL)
      toolitems_.push_back(*iter);
  }
  toolitems_.insert(toolitems_.end(), unsorted.begin(), unsorted.end());

  // Inform observers.
  for (size_t i = 0; i < toolitems_.size(); i++) {
    FOR_EACH_OBSERVER(Observer, observers_,
                      BrowserActionAdded(toolitems_[i], i));
  }

  UpdatePrefs();

  extensions_initialized_ = true;
  FOR_EACH_OBSERVER(Observer, observers_, ModelLoaded());
}

void ExtensionToolbarModel::UpdatePrefs() {
  if (!service_->extension_prefs())
    return;

  std::vector<std::string> ids;
  ids.reserve(toolitems_.size());
  for (ExtensionList::iterator iter = begin(); iter != end(); ++iter)
    ids.push_back((*iter)->id());
  service_->extension_prefs()->SetToolbarOrder(ids);
}

Extension* ExtensionToolbarModel::GetExtensionByIndex(int index) const {
  return toolitems_.at(index);
}

int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) {
  int original_index = 0, i = 0;
  for (ExtensionList::iterator iter = begin(); iter != end();
       ++iter, ++original_index) {
    if (service_->IsIncognitoEnabled(*iter)) {
      if (incognito_index == i)
        break;
      ++i;
    }
  }
  return original_index;
}

int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) {
  int incognito_index = 0, i = 0;
  for (ExtensionList::iterator iter = begin(); iter != end();
       ++iter, ++i) {
    if (original_index == i)
      break;
    if (service_->IsIncognitoEnabled(*iter))
      ++incognito_index;
  }
  return incognito_index;
}
<commit_msg>add a pref save when changing the visible icon count<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/extensions/extension_toolbar_model.h"

#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"

ExtensionToolbarModel::ExtensionToolbarModel(ExtensionsService* service)
    : service_(service),
      prefs_(service->profile()->GetPrefs()),
      extensions_initialized_(false) {
  DCHECK(service_);

  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
                 Source<Profile>(service_->profile()));
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 Source<Profile>(service_->profile()));
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
                 Source<Profile>(service_->profile()));
  registrar_.Add(this, NotificationType::EXTENSIONS_READY,
                 Source<Profile>(service_->profile()));

  visible_icon_count_ = prefs_->GetInteger(prefs::kExtensionToolbarSize);
}

ExtensionToolbarModel::~ExtensionToolbarModel() {
}

void ExtensionToolbarModel::DestroyingProfile() {
  registrar_.RemoveAll();
}

void ExtensionToolbarModel::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void ExtensionToolbarModel::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

void ExtensionToolbarModel::MoveBrowserAction(Extension* extension,
                                              int index) {
  ExtensionList::iterator pos = std::find(begin(), end(), extension);
  if (pos == end()) {
    NOTREACHED();
    return;
  }
  toolitems_.erase(pos);

  int i = 0;
  bool inserted = false;
  for (ExtensionList::iterator iter = begin(); iter != end(); ++iter, ++i) {
    if (i == index) {
      toolitems_.insert(iter, extension);
      inserted = true;
      break;
    }
  }

  if (!inserted) {
    DCHECK_EQ(index, static_cast<int>(toolitems_.size()));
    index = toolitems_.size();

    toolitems_.push_back(extension);
  }

  FOR_EACH_OBSERVER(Observer, observers_, BrowserActionMoved(extension, index));

  UpdatePrefs();
}

void ExtensionToolbarModel::SetVisibleIconCount(int count) {
  visible_icon_count_ = count == static_cast<int>(size()) ? -1 : count;
  prefs_->SetInteger(prefs::kExtensionToolbarSize, visible_icon_count_);
  prefs_->ScheduleSavePersistentPrefs();
}

void ExtensionToolbarModel::Observe(NotificationType type,
                                    const NotificationSource& source,
                                    const NotificationDetails& details) {
  if (type == NotificationType::EXTENSIONS_READY) {
    InitializeExtensionList();
    return;
  }

  if (!service_->is_ready())
    return;

  Extension* extension = Details<Extension>(details).ptr();
  if (type == NotificationType::EXTENSION_LOADED) {
    AddExtension(extension);
  } else if (type == NotificationType::EXTENSION_UNLOADED ||
             type == NotificationType::EXTENSION_UNLOADED_DISABLED) {
    RemoveExtension(extension);
  } else {
    NOTREACHED() << "Received unexpected notification";
  }
}

void ExtensionToolbarModel::AddExtension(Extension* extension) {
  // We only care about extensions with browser actions.
  if (!extension->browser_action())
    return;

  if (extension->id() == last_extension_removed_ &&
      last_extension_removed_index_ < toolitems_.size()) {
    toolitems_.insert(begin() + last_extension_removed_index_, extension);
    FOR_EACH_OBSERVER(Observer, observers_,
        BrowserActionAdded(extension, last_extension_removed_index_));
  } else {
    toolitems_.push_back(extension);
    FOR_EACH_OBSERVER(Observer, observers_,
                      BrowserActionAdded(extension, toolitems_.size() - 1));
  }

  last_extension_removed_ = "";
  last_extension_removed_index_ = -1;

  UpdatePrefs();
}

void ExtensionToolbarModel::RemoveExtension(Extension* extension) {
  ExtensionList::iterator pos = std::find(begin(), end(), extension);
  if (pos == end()) {
    return;
  }

  last_extension_removed_ = extension->id();
  last_extension_removed_index_ = pos - begin();

  toolitems_.erase(pos);
  FOR_EACH_OBSERVER(Observer, observers_,
                    BrowserActionRemoved(extension));

  UpdatePrefs();
}

// Combine the currently enabled extensions that have browser actions (which
// we get from the ExtensionsService) with the ordering we get from the
// pref service. For robustness we use a somewhat inefficient process:
// 1. Create a vector of extensions sorted by their pref values. This vector may
// have holes.
// 2. Create a vector of extensions that did not have a pref value.
// 3. Remove holes from the sorted vector and append the unsorted vector.
void ExtensionToolbarModel::InitializeExtensionList() {
  DCHECK(service_->is_ready());

  std::vector<std::string> pref_order = service_->extension_prefs()->
      GetToolbarOrder();
  // Items that have a pref for their position.
  ExtensionList sorted;
  sorted.resize(pref_order.size(), NULL);
  // The items that don't have a pref for their position.
  ExtensionList unsorted;

  // Create the lists.
  for (size_t i = 0; i < service_->extensions()->size(); ++i) {
    Extension* extension = service_->extensions()->at(i);
    if (!extension->browser_action())
      continue;

    std::vector<std::string>::iterator pos =
        std::find(pref_order.begin(), pref_order.end(), extension->id());
    if (pos != pref_order.end()) {
      int index = std::distance(pref_order.begin(), pos);
      sorted[index] = extension;
    } else {
      unsorted.push_back(extension);
    }
  }

  // Merge the lists.
  toolitems_.reserve(sorted.size() + unsorted.size());
  for (ExtensionList::iterator iter = sorted.begin();
       iter != sorted.end(); ++iter) {
    if (*iter != NULL)
      toolitems_.push_back(*iter);
  }
  toolitems_.insert(toolitems_.end(), unsorted.begin(), unsorted.end());

  // Inform observers.
  for (size_t i = 0; i < toolitems_.size(); i++) {
    FOR_EACH_OBSERVER(Observer, observers_,
                      BrowserActionAdded(toolitems_[i], i));
  }

  UpdatePrefs();

  extensions_initialized_ = true;
  FOR_EACH_OBSERVER(Observer, observers_, ModelLoaded());
}

void ExtensionToolbarModel::UpdatePrefs() {
  if (!service_->extension_prefs())
    return;

  std::vector<std::string> ids;
  ids.reserve(toolitems_.size());
  for (ExtensionList::iterator iter = begin(); iter != end(); ++iter)
    ids.push_back((*iter)->id());
  service_->extension_prefs()->SetToolbarOrder(ids);
}

Extension* ExtensionToolbarModel::GetExtensionByIndex(int index) const {
  return toolitems_.at(index);
}

int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) {
  int original_index = 0, i = 0;
  for (ExtensionList::iterator iter = begin(); iter != end();
       ++iter, ++original_index) {
    if (service_->IsIncognitoEnabled(*iter)) {
      if (incognito_index == i)
        break;
      ++i;
    }
  }
  return original_index;
}

int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) {
  int incognito_index = 0, i = 0;
  for (ExtensionList::iterator iter = begin(); iter != end();
       ++iter, ++i) {
    if (original_index == i)
      break;
    if (service_->IsIncognitoEnabled(*iter))
      ++incognito_index;
  }
  return incognito_index;
}
<|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 "chrome/browser/storage_monitor/media_storage_util.h"

#include <vector>

#include "base/callback.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/storage_monitor/media_device_notifications_utils.h"
#include "chrome/browser/storage_monitor/storage_monitor.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_LINUX)  // Implies OS_CHROMEOS
#include "chrome/browser/storage_monitor/media_transfer_protocol_device_observer_linux.h"
#endif

using content::BrowserThread;

const char kRootPath[] = "/";

namespace chrome {

namespace {

// MediaDeviceNotification.DeviceInfo histogram values.
enum DeviceInfoHistogramBuckets {
  MASS_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE,
  MASS_STORAGE_DEVICE_UUID_MISSING,
  MASS_STORAGE_DEVICE_NAME_MISSING,
  MASS_STORAGE_DEVICE_NAME_AND_UUID_MISSING,
  MTP_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE,
  MTP_STORAGE_DEVICE_UUID_MISSING,
  MTP_STORAGE_DEVICE_NAME_MISSING,
  MTP_STORAGE_DEVICE_NAME_AND_UUID_MISSING,
  DEVICE_INFO_BUCKET_BOUNDARY
};

// Prefix constants for different device id spaces.
const char kRemovableMassStorageWithDCIMPrefix[] = "dcim:";
const char kRemovableMassStorageNoDCIMPrefix[] = "nodcim:";
const char kFixedMassStoragePrefix[] = "path:";
const char kMtpPtpPrefix[] = "mtp:";
const char kMacImageCapture[] = "ic:";

void ValidatePathOnFileThread(
    const base::FilePath& path,
    const MediaStorageUtil::BoolCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                          base::Bind(callback, file_util::PathExists(path)));
}

typedef std::vector<StorageInfo> StorageInfoList;

bool IsRemovableStorageAttached(const std::string& id) {
  StorageInfoList devices = StorageMonitor::GetInstance()->GetAttachedStorage();
  for (StorageInfoList::const_iterator it = devices.begin();
       it != devices.end(); ++it) {
    if (it->device_id == id)
      return true;
  }
  return false;
}

base::FilePath::StringType FindRemovableStorageLocationById(
    const std::string& device_id) {
  StorageInfoList devices = StorageMonitor::GetInstance()->GetAttachedStorage();
  for (StorageInfoList::const_iterator it = devices.begin();
       it != devices.end(); ++it) {
    if (it->device_id == device_id)
      return it->location;
  }
  return base::FilePath::StringType();
}

void FilterAttachedDevicesOnFileThread(MediaStorageUtil::DeviceIdSet* devices) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  MediaStorageUtil::DeviceIdSet missing_devices;

  for (MediaStorageUtil::DeviceIdSet::const_iterator it = devices->begin();
       it != devices->end();
       ++it) {
    MediaStorageUtil::Type type;
    std::string unique_id;
    if (!MediaStorageUtil::CrackDeviceId(*it, &type, &unique_id)) {
      missing_devices.insert(*it);
      continue;
    }

    if (type == MediaStorageUtil::FIXED_MASS_STORAGE) {
      if (!file_util::PathExists(base::FilePath::FromUTF8Unsafe(unique_id)))
        missing_devices.insert(*it);
      continue;
    }

    if (!IsRemovableStorageAttached(*it))
      missing_devices.insert(*it);
  }

  for (MediaStorageUtil::DeviceIdSet::const_iterator it =
           missing_devices.begin();
       it != missing_devices.end();
       ++it) {
    devices->erase(*it);
  }
}

// For a device with |device_name| and a relative path |sub_folder|, construct
// a display name. If |sub_folder| is empty, then just return |device_name|.
string16 GetDisplayNameForSubFolder(const string16& device_name,
                                    const base::FilePath& sub_folder) {
  if (sub_folder.empty())
    return device_name;
  return (sub_folder.BaseName().LossyDisplayName() +
          ASCIIToUTF16(" - ") +
          device_name);
}

}  // namespace

// static
std::string MediaStorageUtil::MakeDeviceId(Type type,
                                           const std::string& unique_id) {
  DCHECK(!unique_id.empty());
  switch (type) {
    case REMOVABLE_MASS_STORAGE_WITH_DCIM:
      return std::string(kRemovableMassStorageWithDCIMPrefix) + unique_id;
    case REMOVABLE_MASS_STORAGE_NO_DCIM:
      return std::string(kRemovableMassStorageNoDCIMPrefix) + unique_id;
    case FIXED_MASS_STORAGE:
      return std::string(kFixedMassStoragePrefix) + unique_id;
    case MTP_OR_PTP:
      return std::string(kMtpPtpPrefix) + unique_id;
    case MAC_IMAGE_CAPTURE:
      return std::string(kMacImageCapture) + unique_id;
  }
  NOTREACHED();
  return std::string();
}

// static
bool MediaStorageUtil::CrackDeviceId(const std::string& device_id,
                                     Type* type, std::string* unique_id) {
  size_t prefix_length = device_id.find_first_of(':');
  std::string prefix = prefix_length != std::string::npos ?
                       device_id.substr(0, prefix_length + 1) : "";

  Type found_type;
  if (prefix == kRemovableMassStorageWithDCIMPrefix) {
    found_type = REMOVABLE_MASS_STORAGE_WITH_DCIM;
  } else if (prefix == kRemovableMassStorageNoDCIMPrefix) {
    found_type = REMOVABLE_MASS_STORAGE_NO_DCIM;
  } else if (prefix == kFixedMassStoragePrefix) {
    found_type = FIXED_MASS_STORAGE;
  } else if (prefix == kMtpPtpPrefix) {
    found_type = MTP_OR_PTP;
  } else if (prefix == kMacImageCapture) {
    found_type = MAC_IMAGE_CAPTURE;
  } else {
    NOTREACHED();
    return false;
  }
  if (type)
    *type = found_type;

  if (unique_id)
    *unique_id = device_id.substr(prefix_length + 1);
  return true;
}

// static
bool MediaStorageUtil::IsMediaDevice(const std::string& device_id) {
  Type type;
  return CrackDeviceId(device_id, &type, NULL) &&
      (type == REMOVABLE_MASS_STORAGE_WITH_DCIM || type == MTP_OR_PTP ||
       type == MAC_IMAGE_CAPTURE);
}

// static
bool MediaStorageUtil::IsRemovableDevice(const std::string& device_id) {
  Type type;
  return CrackDeviceId(device_id, &type, NULL) && type != FIXED_MASS_STORAGE;
}

// static
bool MediaStorageUtil::IsMassStorageDevice(const std::string& device_id) {
  Type type;
  return CrackDeviceId(device_id, &type, NULL) &&
         (type == REMOVABLE_MASS_STORAGE_WITH_DCIM ||
          type == REMOVABLE_MASS_STORAGE_NO_DCIM ||
          type == FIXED_MASS_STORAGE);
}

// static
bool MediaStorageUtil::CanCreateFileSystem(const std::string& device_id,
                                           const base::FilePath& path) {
  Type type;
  if (!CrackDeviceId(device_id, &type, NULL))
    return false;

  if (type == MAC_IMAGE_CAPTURE)
    return true;

  return path.IsAbsolute() && !path.ReferencesParent();
}

// static
void MediaStorageUtil::IsDeviceAttached(const std::string& device_id,
                                        const BoolCallback& callback) {
  Type type;
  std::string unique_id;
  if (!CrackDeviceId(device_id, &type, &unique_id)) {
    callback.Run(false);
    return;
  }

  if (type == FIXED_MASS_STORAGE) {
    // For this type, the unique_id is the path.
    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE,
        base::Bind(&ValidatePathOnFileThread,
                   base::FilePath::FromUTF8Unsafe(unique_id),
                   callback));
  } else {
    DCHECK(type == MTP_OR_PTP ||
           type == REMOVABLE_MASS_STORAGE_WITH_DCIM ||
           type == REMOVABLE_MASS_STORAGE_NO_DCIM);
    // We should be able to find removable storage.
    callback.Run(IsRemovableStorageAttached(device_id));
  }
}

// static
void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices,
                                             const base::Closure& done) {
  if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
    FilterAttachedDevicesOnFileThread(devices);
    done.Run();
    return;
  }
  BrowserThread::PostTaskAndReply(BrowserThread::FILE,
                                  FROM_HERE,
                                  base::Bind(&FilterAttachedDevicesOnFileThread,
                                             devices),
                                  done);
}

// TODO(kmadhusu) Write unit tests for GetDeviceInfoFromPath().
bool MediaStorageUtil::GetDeviceInfoFromPath(const base::FilePath& path,
                                             StorageInfo* device_info,
                                             base::FilePath* relative_path) {
  if (!path.IsAbsolute())
    return false;

  bool found_device = false;
  StorageInfo info;
  StorageMonitor* monitor = StorageMonitor::GetInstance();
  found_device = monitor->GetStorageInfoForPath(path, &info);

// TODO(gbillock): Move this upstream into the RemovableStorageNotifications
// implementation to handle in its GetDeviceInfoForPath call.
#if defined(OS_LINUX)
  if (!found_device) {
    MediaTransferProtocolDeviceObserverLinux* mtp_manager =
        MediaTransferProtocolDeviceObserverLinux::GetInstance();
    found_device = mtp_manager->GetStorageInfoForPath(path, &info);
  }
#endif

  if (found_device && IsRemovableDevice(info.device_id)) {
    base::FilePath sub_folder_path;
    if (path.value() != info.location) {
      base::FilePath device_path(info.location);
      bool success = device_path.AppendRelativePath(path, &sub_folder_path);
      DCHECK(success);
    }

// TODO(gbillock): Don't do this. Leave for clients to do.
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)  // Implies OS_CHROMEOS
    info.name = GetDisplayNameForDevice(
        monitor->GetStorageSize(info.location),
        GetDisplayNameForSubFolder(info.name, sub_folder_path));
#endif

    if (device_info)
      *device_info = info;
    if (relative_path)
      *relative_path = sub_folder_path;

    return true;
  }

  // On Posix systems, there's one root so any absolute path could be valid.
#if !defined(OS_POSIX)
  if (!found_device)
    return false;
#endif

  // Handle non-removable devices. Note: this is just overwriting
  // good values from RemovableStorageNotifications.
  // TODO(gbillock): Make sure return values from that class are definitive,
  // and don't do this here.
  info.device_id = MakeDeviceId(FIXED_MASS_STORAGE, path.AsUTF8Unsafe());
  info.name = path.BaseName().LossyDisplayName();
  if (device_info)
    *device_info = info;
  if (relative_path)
    *relative_path = base::FilePath();
  return true;
}

// static
base::FilePath MediaStorageUtil::FindDevicePathById(
    const std::string& device_id) {
  Type type;
  std::string unique_id;
  if (!CrackDeviceId(device_id, &type, &unique_id))
    return base::FilePath();

  if (type == FIXED_MASS_STORAGE) {
    // For this type, the unique_id is the path.
    return base::FilePath::FromUTF8Unsafe(unique_id);
  }

  // For ImageCapture, the synthetic filesystem will be rooted at a fake
  // top-level directory which is the device_id.
  if (type == MAC_IMAGE_CAPTURE) {
#if !defined(OS_WIN)
    return base::FilePath(kRootPath + device_id);
#endif
  }

  DCHECK(type == MTP_OR_PTP ||
         type == REMOVABLE_MASS_STORAGE_WITH_DCIM ||
         type == REMOVABLE_MASS_STORAGE_NO_DCIM);
  return base::FilePath(FindRemovableStorageLocationById(device_id));
}

// static
void MediaStorageUtil::RecordDeviceInfoHistogram(bool mass_storage,
                                                 const std::string& device_uuid,
                                                 const string16& device_name) {
  unsigned int event_number = 0;
  if (!mass_storage)
    event_number = 4;

  if (device_name.empty())
    event_number += 2;

  if (device_uuid.empty())
    event_number += 1;
  enum DeviceInfoHistogramBuckets event =
      static_cast<enum DeviceInfoHistogramBuckets>(event_number);
  if (event >= DEVICE_INFO_BUCKET_BOUNDARY) {
    NOTREACHED();
    return;
  }
  UMA_HISTOGRAM_ENUMERATION("MediaDeviceNotifications.DeviceInfo", event,
                            DEVICE_INFO_BUCKET_BOUNDARY);
}

}  // namespace chrome
<commit_msg>Cleanup: Move a global variable into an anonymous namespace in MediaStorageUtil.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/storage_monitor/media_storage_util.h"

#include <vector>

#include "base/callback.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/storage_monitor/media_device_notifications_utils.h"
#include "chrome/browser/storage_monitor/storage_monitor.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_LINUX)  // Implies OS_CHROMEOS
#include "chrome/browser/storage_monitor/media_transfer_protocol_device_observer_linux.h"
#endif

using content::BrowserThread;

namespace chrome {

namespace {

// MediaDeviceNotification.DeviceInfo histogram values.
enum DeviceInfoHistogramBuckets {
  MASS_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE,
  MASS_STORAGE_DEVICE_UUID_MISSING,
  MASS_STORAGE_DEVICE_NAME_MISSING,
  MASS_STORAGE_DEVICE_NAME_AND_UUID_MISSING,
  MTP_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE,
  MTP_STORAGE_DEVICE_UUID_MISSING,
  MTP_STORAGE_DEVICE_NAME_MISSING,
  MTP_STORAGE_DEVICE_NAME_AND_UUID_MISSING,
  DEVICE_INFO_BUCKET_BOUNDARY
};

// Prefix constants for different device id spaces.
const char kRemovableMassStorageWithDCIMPrefix[] = "dcim:";
const char kRemovableMassStorageNoDCIMPrefix[] = "nodcim:";
const char kFixedMassStoragePrefix[] = "path:";
const char kMtpPtpPrefix[] = "mtp:";
const char kMacImageCapture[] = "ic:";

#if !defined(OS_WIN)
const char kRootPath[] = "/";
#endif

void ValidatePathOnFileThread(
    const base::FilePath& path,
    const MediaStorageUtil::BoolCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                          base::Bind(callback, file_util::PathExists(path)));
}

typedef std::vector<StorageInfo> StorageInfoList;

bool IsRemovableStorageAttached(const std::string& id) {
  StorageInfoList devices = StorageMonitor::GetInstance()->GetAttachedStorage();
  for (StorageInfoList::const_iterator it = devices.begin();
       it != devices.end(); ++it) {
    if (it->device_id == id)
      return true;
  }
  return false;
}

base::FilePath::StringType FindRemovableStorageLocationById(
    const std::string& device_id) {
  StorageInfoList devices = StorageMonitor::GetInstance()->GetAttachedStorage();
  for (StorageInfoList::const_iterator it = devices.begin();
       it != devices.end(); ++it) {
    if (it->device_id == device_id)
      return it->location;
  }
  return base::FilePath::StringType();
}

void FilterAttachedDevicesOnFileThread(MediaStorageUtil::DeviceIdSet* devices) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  MediaStorageUtil::DeviceIdSet missing_devices;

  for (MediaStorageUtil::DeviceIdSet::const_iterator it = devices->begin();
       it != devices->end();
       ++it) {
    MediaStorageUtil::Type type;
    std::string unique_id;
    if (!MediaStorageUtil::CrackDeviceId(*it, &type, &unique_id)) {
      missing_devices.insert(*it);
      continue;
    }

    if (type == MediaStorageUtil::FIXED_MASS_STORAGE) {
      if (!file_util::PathExists(base::FilePath::FromUTF8Unsafe(unique_id)))
        missing_devices.insert(*it);
      continue;
    }

    if (!IsRemovableStorageAttached(*it))
      missing_devices.insert(*it);
  }

  for (MediaStorageUtil::DeviceIdSet::const_iterator it =
           missing_devices.begin();
       it != missing_devices.end();
       ++it) {
    devices->erase(*it);
  }
}

// For a device with |device_name| and a relative path |sub_folder|, construct
// a display name. If |sub_folder| is empty, then just return |device_name|.
string16 GetDisplayNameForSubFolder(const string16& device_name,
                                    const base::FilePath& sub_folder) {
  if (sub_folder.empty())
    return device_name;
  return (sub_folder.BaseName().LossyDisplayName() +
          ASCIIToUTF16(" - ") +
          device_name);
}

}  // namespace

// static
std::string MediaStorageUtil::MakeDeviceId(Type type,
                                           const std::string& unique_id) {
  DCHECK(!unique_id.empty());
  switch (type) {
    case REMOVABLE_MASS_STORAGE_WITH_DCIM:
      return std::string(kRemovableMassStorageWithDCIMPrefix) + unique_id;
    case REMOVABLE_MASS_STORAGE_NO_DCIM:
      return std::string(kRemovableMassStorageNoDCIMPrefix) + unique_id;
    case FIXED_MASS_STORAGE:
      return std::string(kFixedMassStoragePrefix) + unique_id;
    case MTP_OR_PTP:
      return std::string(kMtpPtpPrefix) + unique_id;
    case MAC_IMAGE_CAPTURE:
      return std::string(kMacImageCapture) + unique_id;
  }
  NOTREACHED();
  return std::string();
}

// static
bool MediaStorageUtil::CrackDeviceId(const std::string& device_id,
                                     Type* type, std::string* unique_id) {
  size_t prefix_length = device_id.find_first_of(':');
  std::string prefix = prefix_length != std::string::npos ?
                       device_id.substr(0, prefix_length + 1) : "";

  Type found_type;
  if (prefix == kRemovableMassStorageWithDCIMPrefix) {
    found_type = REMOVABLE_MASS_STORAGE_WITH_DCIM;
  } else if (prefix == kRemovableMassStorageNoDCIMPrefix) {
    found_type = REMOVABLE_MASS_STORAGE_NO_DCIM;
  } else if (prefix == kFixedMassStoragePrefix) {
    found_type = FIXED_MASS_STORAGE;
  } else if (prefix == kMtpPtpPrefix) {
    found_type = MTP_OR_PTP;
  } else if (prefix == kMacImageCapture) {
    found_type = MAC_IMAGE_CAPTURE;
  } else {
    NOTREACHED();
    return false;
  }
  if (type)
    *type = found_type;

  if (unique_id)
    *unique_id = device_id.substr(prefix_length + 1);
  return true;
}

// static
bool MediaStorageUtil::IsMediaDevice(const std::string& device_id) {
  Type type;
  return CrackDeviceId(device_id, &type, NULL) &&
      (type == REMOVABLE_MASS_STORAGE_WITH_DCIM || type == MTP_OR_PTP ||
       type == MAC_IMAGE_CAPTURE);
}

// static
bool MediaStorageUtil::IsRemovableDevice(const std::string& device_id) {
  Type type;
  return CrackDeviceId(device_id, &type, NULL) && type != FIXED_MASS_STORAGE;
}

// static
bool MediaStorageUtil::IsMassStorageDevice(const std::string& device_id) {
  Type type;
  return CrackDeviceId(device_id, &type, NULL) &&
         (type == REMOVABLE_MASS_STORAGE_WITH_DCIM ||
          type == REMOVABLE_MASS_STORAGE_NO_DCIM ||
          type == FIXED_MASS_STORAGE);
}

// static
bool MediaStorageUtil::CanCreateFileSystem(const std::string& device_id,
                                           const base::FilePath& path) {
  Type type;
  if (!CrackDeviceId(device_id, &type, NULL))
    return false;

  if (type == MAC_IMAGE_CAPTURE)
    return true;

  return path.IsAbsolute() && !path.ReferencesParent();
}

// static
void MediaStorageUtil::IsDeviceAttached(const std::string& device_id,
                                        const BoolCallback& callback) {
  Type type;
  std::string unique_id;
  if (!CrackDeviceId(device_id, &type, &unique_id)) {
    callback.Run(false);
    return;
  }

  if (type == FIXED_MASS_STORAGE) {
    // For this type, the unique_id is the path.
    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE,
        base::Bind(&ValidatePathOnFileThread,
                   base::FilePath::FromUTF8Unsafe(unique_id),
                   callback));
  } else {
    DCHECK(type == MTP_OR_PTP ||
           type == REMOVABLE_MASS_STORAGE_WITH_DCIM ||
           type == REMOVABLE_MASS_STORAGE_NO_DCIM);
    // We should be able to find removable storage.
    callback.Run(IsRemovableStorageAttached(device_id));
  }
}

// static
void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices,
                                             const base::Closure& done) {
  if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
    FilterAttachedDevicesOnFileThread(devices);
    done.Run();
    return;
  }
  BrowserThread::PostTaskAndReply(BrowserThread::FILE,
                                  FROM_HERE,
                                  base::Bind(&FilterAttachedDevicesOnFileThread,
                                             devices),
                                  done);
}

// TODO(kmadhusu) Write unit tests for GetDeviceInfoFromPath().
bool MediaStorageUtil::GetDeviceInfoFromPath(const base::FilePath& path,
                                             StorageInfo* device_info,
                                             base::FilePath* relative_path) {
  if (!path.IsAbsolute())
    return false;

  bool found_device = false;
  StorageInfo info;
  StorageMonitor* monitor = StorageMonitor::GetInstance();
  found_device = monitor->GetStorageInfoForPath(path, &info);

// TODO(gbillock): Move this upstream into the RemovableStorageNotifications
// implementation to handle in its GetDeviceInfoForPath call.
#if defined(OS_LINUX)
  if (!found_device) {
    MediaTransferProtocolDeviceObserverLinux* mtp_manager =
        MediaTransferProtocolDeviceObserverLinux::GetInstance();
    found_device = mtp_manager->GetStorageInfoForPath(path, &info);
  }
#endif

  if (found_device && IsRemovableDevice(info.device_id)) {
    base::FilePath sub_folder_path;
    if (path.value() != info.location) {
      base::FilePath device_path(info.location);
      bool success = device_path.AppendRelativePath(path, &sub_folder_path);
      DCHECK(success);
    }

// TODO(gbillock): Don't do this. Leave for clients to do.
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)  // Implies OS_CHROMEOS
    info.name = GetDisplayNameForDevice(
        monitor->GetStorageSize(info.location),
        GetDisplayNameForSubFolder(info.name, sub_folder_path));
#endif

    if (device_info)
      *device_info = info;
    if (relative_path)
      *relative_path = sub_folder_path;

    return true;
  }

  // On Posix systems, there's one root so any absolute path could be valid.
#if !defined(OS_POSIX)
  if (!found_device)
    return false;
#endif

  // Handle non-removable devices. Note: this is just overwriting
  // good values from RemovableStorageNotifications.
  // TODO(gbillock): Make sure return values from that class are definitive,
  // and don't do this here.
  info.device_id = MakeDeviceId(FIXED_MASS_STORAGE, path.AsUTF8Unsafe());
  info.name = path.BaseName().LossyDisplayName();
  if (device_info)
    *device_info = info;
  if (relative_path)
    *relative_path = base::FilePath();
  return true;
}

// static
base::FilePath MediaStorageUtil::FindDevicePathById(
    const std::string& device_id) {
  Type type;
  std::string unique_id;
  if (!CrackDeviceId(device_id, &type, &unique_id))
    return base::FilePath();

  if (type == FIXED_MASS_STORAGE) {
    // For this type, the unique_id is the path.
    return base::FilePath::FromUTF8Unsafe(unique_id);
  }

  // For ImageCapture, the synthetic filesystem will be rooted at a fake
  // top-level directory which is the device_id.
  if (type == MAC_IMAGE_CAPTURE) {
#if !defined(OS_WIN)
    return base::FilePath(kRootPath + device_id);
#endif
  }

  DCHECK(type == MTP_OR_PTP ||
         type == REMOVABLE_MASS_STORAGE_WITH_DCIM ||
         type == REMOVABLE_MASS_STORAGE_NO_DCIM);
  return base::FilePath(FindRemovableStorageLocationById(device_id));
}

// static
void MediaStorageUtil::RecordDeviceInfoHistogram(bool mass_storage,
                                                 const std::string& device_uuid,
                                                 const string16& device_name) {
  unsigned int event_number = 0;
  if (!mass_storage)
    event_number = 4;

  if (device_name.empty())
    event_number += 2;

  if (device_uuid.empty())
    event_number += 1;
  enum DeviceInfoHistogramBuckets event =
      static_cast<enum DeviceInfoHistogramBuckets>(event_number);
  if (event >= DEVICE_INFO_BUCKET_BOUNDARY) {
    NOTREACHED();
    return;
  }
  UMA_HISTOGRAM_ENUMERATION("MediaDeviceNotifications.DeviceInfo", event,
                            DEVICE_INFO_BUCKET_BOUNDARY);
}

}  // namespace chrome
<|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 "chrome/browser/ui/webui/constrained_web_dialog_ui.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/values.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
#include "ui/web_dialogs/web_dialog_ui.h"

#if defined(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/tab_helper.h"
#endif

using content::RenderViewHost;
using content::WebContents;
using content::WebUIMessageHandler;

namespace {

const char kConstrainedWebDialogDelegateUserDataKey[] =
    "ConstrainedWebDialogDelegateUserData";

class ConstrainedWebDialogDelegateUserData
    : public base::SupportsUserData::Data {
 public:
  explicit ConstrainedWebDialogDelegateUserData(
      ConstrainedWebDialogDelegate* delegate) : delegate_(delegate) {}
  virtual ~ConstrainedWebDialogDelegateUserData() {}

  ConstrainedWebDialogDelegate* delegate() { return delegate_; }

 private:
  ConstrainedWebDialogDelegate* delegate_;  // unowned

  DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateUserData);
};

}  // namespace

ConstrainedWebDialogUI::ConstrainedWebDialogUI(content::WebUI* web_ui)
    : WebUIController(web_ui) {
#if defined(ENABLE_EXTENSIONS)
  extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents());
#endif
}

ConstrainedWebDialogUI::~ConstrainedWebDialogUI() {
}

void ConstrainedWebDialogUI::RenderViewCreated(
    RenderViewHost* render_view_host) {
  ConstrainedWebDialogDelegate* delegate = GetConstrainedDelegate();
  if (!delegate)
    return;

  ui::WebDialogDelegate* dialog_delegate = delegate->GetWebDialogDelegate();
  std::vector<WebUIMessageHandler*> handlers;
  dialog_delegate->GetWebUIMessageHandlers(&handlers);
  render_view_host->SetWebUIProperty("dialogArguments",
                                     dialog_delegate->GetDialogArgs());
  for (std::vector<WebUIMessageHandler*>::iterator it = handlers.begin();
       it != handlers.end(); ++it) {
    web_ui()->AddMessageHandler(*it);
  }

  // Add a "dialogClose" callback which matches WebDialogUI behavior.
  web_ui()->RegisterMessageCallback("dialogClose",
      base::Bind(&ConstrainedWebDialogUI::OnDialogCloseMessage,
                 base::Unretained(this)));

  dialog_delegate->OnDialogShown(web_ui(), render_view_host);
}

void ConstrainedWebDialogUI::OnDialogCloseMessage(const base::ListValue* args) {
  ConstrainedWebDialogDelegate* delegate = GetConstrainedDelegate();
  if (!delegate)
    return;

  std::string json_retval;
  if (!args->empty() && !args->GetString(0, &json_retval))
    NOTREACHED() << "Could not read JSON argument";
  delegate->GetWebDialogDelegate()->OnDialogClosed(json_retval);
  delegate->OnDialogCloseFromWebUI();
}

// static
void ConstrainedWebDialogUI::SetConstrainedDelegate(
    content::WebContents* web_contents,
    ConstrainedWebDialogDelegate* delegate) {
  web_contents->SetUserData(&kConstrainedWebDialogDelegateUserDataKey,
                            new ConstrainedWebDialogDelegateUserData(delegate));
}

ConstrainedWebDialogDelegate* ConstrainedWebDialogUI::GetConstrainedDelegate() {
  ConstrainedWebDialogDelegateUserData* user_data =
      static_cast<ConstrainedWebDialogDelegateUserData*>(
          web_ui()->GetWebContents()->
              GetUserData(&kConstrainedWebDialogDelegateUserDataKey));

  return user_data ? user_data->delegate() : NULL;
}
<commit_msg>Fix a DCHECK failure by registering a handler for 'dialogClose' message.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/values.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
#include "ui/web_dialogs/web_dialog_ui.h"

#if defined(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/tab_helper.h"
#endif

using content::RenderViewHost;
using content::WebContents;
using content::WebUIMessageHandler;

namespace {

const char kConstrainedWebDialogDelegateUserDataKey[] =
    "ConstrainedWebDialogDelegateUserData";

class ConstrainedWebDialogDelegateUserData
    : public base::SupportsUserData::Data {
 public:
  explicit ConstrainedWebDialogDelegateUserData(
      ConstrainedWebDialogDelegate* delegate) : delegate_(delegate) {}
  virtual ~ConstrainedWebDialogDelegateUserData() {}

  ConstrainedWebDialogDelegate* delegate() { return delegate_; }

 private:
  ConstrainedWebDialogDelegate* delegate_;  // unowned

  DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateUserData);
};

}  // namespace

ConstrainedWebDialogUI::ConstrainedWebDialogUI(content::WebUI* web_ui)
    : WebUIController(web_ui) {
#if defined(ENABLE_EXTENSIONS)
  extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents());
#endif
}

ConstrainedWebDialogUI::~ConstrainedWebDialogUI() {
}

void ConstrainedWebDialogUI::RenderViewCreated(
    RenderViewHost* render_view_host) {
  // Add a "dialogClose" callback which matches WebDialogUI behavior.
  web_ui()->RegisterMessageCallback("dialogClose",
      base::Bind(&ConstrainedWebDialogUI::OnDialogCloseMessage,
                 base::Unretained(this)));

  ConstrainedWebDialogDelegate* delegate = GetConstrainedDelegate();
  if (!delegate)
    return;

  ui::WebDialogDelegate* dialog_delegate = delegate->GetWebDialogDelegate();
  std::vector<WebUIMessageHandler*> handlers;
  dialog_delegate->GetWebUIMessageHandlers(&handlers);
  render_view_host->SetWebUIProperty("dialogArguments",
                                     dialog_delegate->GetDialogArgs());
  for (std::vector<WebUIMessageHandler*>::iterator it = handlers.begin();
       it != handlers.end(); ++it) {
    web_ui()->AddMessageHandler(*it);
  }

  dialog_delegate->OnDialogShown(web_ui(), render_view_host);
}

void ConstrainedWebDialogUI::OnDialogCloseMessage(const base::ListValue* args) {
  ConstrainedWebDialogDelegate* delegate = GetConstrainedDelegate();
  if (!delegate)
    return;

  std::string json_retval;
  if (!args->empty() && !args->GetString(0, &json_retval))
    NOTREACHED() << "Could not read JSON argument";
  delegate->GetWebDialogDelegate()->OnDialogClosed(json_retval);
  delegate->OnDialogCloseFromWebUI();
}

// static
void ConstrainedWebDialogUI::SetConstrainedDelegate(
    content::WebContents* web_contents,
    ConstrainedWebDialogDelegate* delegate) {
  web_contents->SetUserData(&kConstrainedWebDialogDelegateUserDataKey,
                            new ConstrainedWebDialogDelegateUserData(delegate));
}

ConstrainedWebDialogDelegate* ConstrainedWebDialogUI::GetConstrainedDelegate() {
  ConstrainedWebDialogDelegateUserData* user_data =
      static_cast<ConstrainedWebDialogDelegateUserData*>(
          web_ui()->GetWebContents()->
              GetUserData(&kConstrainedWebDialogDelegateUserDataKey));

  return user_data ? user_data->delegate() : NULL;
}
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/gpu/instruction_fusion.h"

#include "absl/container/flat_hash_set.h"
#include "tensorflow/compiler/xla/service/gpu/gpu_fusible.h"
#include "tensorflow/compiler/xla/service/gpu/ir_emission_utils.h"
#include "tensorflow/compiler/xla/service/hlo_opcode.h"
#include "tensorflow/compiler/xla/service/hlo_query.h"
#include "tensorflow/compiler/xla/service/llvm_ir/fused_ir_emitter.h"
#include "tensorflow/compiler/xla/service/pattern_matcher.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"

namespace xla {
namespace gpu {

namespace {

bool IsIEEEFloatingPointScalarConstant(const HloInstruction* constant) {
  if (constant->opcode() != HloOpcode::kConstant ||
      !ShapeUtil::IsScalar(constant->shape())) {
    return false;
  }
  auto type = constant->shape().element_type();
  return type == F16 || type == F32 || type == F64;
}

}  // namespace

/*static*/ bool GpuInstructionFusion::IsExpensive(
    const HloInstruction& instruction) {
  // We say that floating-point division is cheap on the GPU.
  if (instruction.opcode() == HloOpcode::kDivide &&
      ShapeUtil::ElementIsFloating(instruction.shape())) {
    return false;
  }
  // LLVM optimizes the integer division/remainder by a
  // constant scalar to a few fast operations.
  if ((instruction.opcode() == HloOpcode::kDivide ||
       instruction.opcode() == HloOpcode::kRemainder) &&
      ShapeUtil::ElementIsIntegral(instruction.shape())) {
    auto* operand1 = instruction.operand(1);
    if (hlo_query::IsScalarConstant(operand1)) {
      return false;
    }
    // Broadcasted scalar is also being optimized.
    if (operand1->opcode() == HloOpcode::kBroadcast &&
        hlo_query::IsScalarConstant(operand1->operand(0))) {
      return false;
    }
  }
  return InstructionFusion::IsExpensive(instruction);
}

bool GpuInstructionFusion::ShouldFuseInexpensiveChecks(HloInstruction* consumer,
                                                       int64 operand_index) {
  HloInstruction* producer = consumer->mutable_operand(operand_index);

  // Output fusions are not currently supported on GPUs.
  if (producer->opcode() == HloOpcode::kFusion) {
    return false;
  }
  // Cost condition: not fuse (simple, expensive producers) and (consumers who
  // reuse operand elements).
  if (producer->opcode() != HloOpcode::kFusion &&
      consumer->ReusesOperandElements(operand_index) &&
      is_expensive(*producer)) {
    return false;
  }

  if (!IsProducerConsumerFusible(*producer, *consumer) ||
      !InstructionFusion::ShouldFuse(consumer, operand_index)) {
    return false;
  }
  return true;
}

bool GpuInstructionFusion::ShouldFuse(HloInstruction* consumer,
                                      int64 operand_index) {
  if (!ShouldFuseInexpensiveChecks(consumer, operand_index)) {
    return false;
  }
  auto producer = consumer->operand(operand_index);

  // The following checks are potentially expensive.
  if (FusionWouldBeTooLarge(*consumer, *producer)) {
    return false;
  }
  // Also check that our emitter can handle the fusion node. We currently can
  // have exponential time/memory requirements for emitting certain fusion
  // kernels, in which case we don't want to fuse.
  // TODO(b/119692968): Remove this once we have fixed our fusion emitter.
  return !FusedIrEmitter::IsFusedIrEmitterInefficient(consumer, producer);
}

bool GpuInstructionFusion::ShouldFuseIntoMultiOutput(HloInstruction* consumer,
                                                     int64 operand_index) {
  return false;
}

HloInstruction::FusionKind GpuInstructionFusion::ChooseKind(
    const HloInstruction* producer, const HloInstruction* consumer) {
  return ChooseFusionKind(*producer, *consumer);
}

}  // namespace gpu
}  // namespace xla
<commit_msg>[XLA] Delete dead function.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/gpu/instruction_fusion.h"

#include "absl/container/flat_hash_set.h"
#include "tensorflow/compiler/xla/service/gpu/gpu_fusible.h"
#include "tensorflow/compiler/xla/service/gpu/ir_emission_utils.h"
#include "tensorflow/compiler/xla/service/hlo_opcode.h"
#include "tensorflow/compiler/xla/service/hlo_query.h"
#include "tensorflow/compiler/xla/service/llvm_ir/fused_ir_emitter.h"
#include "tensorflow/compiler/xla/service/pattern_matcher.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"

namespace xla {
namespace gpu {

/*static*/ bool GpuInstructionFusion::IsExpensive(
    const HloInstruction& instruction) {
  // We say that floating-point division is cheap on the GPU.
  if (instruction.opcode() == HloOpcode::kDivide &&
      ShapeUtil::ElementIsFloating(instruction.shape())) {
    return false;
  }
  // LLVM optimizes the integer division/remainder by a
  // constant scalar to a few fast operations.
  if ((instruction.opcode() == HloOpcode::kDivide ||
       instruction.opcode() == HloOpcode::kRemainder) &&
      ShapeUtil::ElementIsIntegral(instruction.shape())) {
    auto* operand1 = instruction.operand(1);
    if (hlo_query::IsScalarConstant(operand1)) {
      return false;
    }
    // Broadcasted scalar is also being optimized.
    if (operand1->opcode() == HloOpcode::kBroadcast &&
        hlo_query::IsScalarConstant(operand1->operand(0))) {
      return false;
    }
  }
  return InstructionFusion::IsExpensive(instruction);
}

bool GpuInstructionFusion::ShouldFuseInexpensiveChecks(HloInstruction* consumer,
                                                       int64 operand_index) {
  HloInstruction* producer = consumer->mutable_operand(operand_index);

  // Output fusions are not currently supported on GPUs.
  if (producer->opcode() == HloOpcode::kFusion) {
    return false;
  }
  // Cost condition: not fuse (simple, expensive producers) and (consumers who
  // reuse operand elements).
  if (producer->opcode() != HloOpcode::kFusion &&
      consumer->ReusesOperandElements(operand_index) &&
      is_expensive(*producer)) {
    return false;
  }

  if (!IsProducerConsumerFusible(*producer, *consumer) ||
      !InstructionFusion::ShouldFuse(consumer, operand_index)) {
    return false;
  }
  return true;
}

bool GpuInstructionFusion::ShouldFuse(HloInstruction* consumer,
                                      int64 operand_index) {
  if (!ShouldFuseInexpensiveChecks(consumer, operand_index)) {
    return false;
  }
  auto producer = consumer->operand(operand_index);

  // The following checks are potentially expensive.
  if (FusionWouldBeTooLarge(*consumer, *producer)) {
    return false;
  }
  // Also check that our emitter can handle the fusion node. We currently can
  // have exponential time/memory requirements for emitting certain fusion
  // kernels, in which case we don't want to fuse.
  // TODO(b/119692968): Remove this once we have fixed our fusion emitter.
  return !FusedIrEmitter::IsFusedIrEmitterInefficient(consumer, producer);
}

bool GpuInstructionFusion::ShouldFuseIntoMultiOutput(HloInstruction* consumer,
                                                     int64 operand_index) {
  return false;
}

HloInstruction::FusionKind GpuInstructionFusion::ChooseKind(
    const HloInstruction* producer, const HloInstruction* consumer) {
  return ChooseFusionKind(*producer, *consumer);
}

}  // namespace gpu
}  // namespace xla
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Morwenn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iterator>
#include <type_traits>
#include <cpp-sort/sorter_facade.h>
#include <cpp-sort/sorter_traits.h>
#include <cpp-sort/utility/as_function.h>
#include <cpp-sort/utility/functional.h>
#include <cpp-sort/utility/size.h>

namespace detail
{
    template<
        typename ForwardIterator,
        typename StrictWeakOrdering,
        typename Projection
    >
    auto bubble_sort(ForwardIterator first, StrictWeakOrdering compare,
                     Projection projection, std::size_t size)
        -> void
    {
        if (size < 2) return;

        auto&& proj = cppsort::utility::as_function(projection);

        while (--size)
        {
            ForwardIterator current = first;
            ForwardIterator next = std::next(current);
            for (std::size_t i = 0 ; i < size ; ++i)
            {
                if (compare(proj(*next), proj(*current)))
                {
                    std::iter_swap(current, next);
                }
                ++next;
                ++current;
            }
        }
    }

    struct bubble_sorter_impl
    {
        // Pair of iterators overload
        template<
            typename ForwardIterator,
            typename StrictWeakOrdering = std::less<>,
            typename Projection = cppsort::utility::identity,
            typename = std::enable_if_t<cppsort::is_projection_iterator<
                Projection, ForwardIterator, StrictWeakOrdering
            >>
        >
        auto operator()(ForwardIterator first, ForwardIterator last,
                        StrictWeakOrdering compare={}, Projection projection={}) const
            -> void
        {
            static_assert(
                std::is_base_of<
                    std::forward_iterator_tag,
                    typename std::iterator_traits<ForwardIterator>::iterator_category
                >::value,
                "bubble_sorter requires at least forward iterators"
            );

            bubble_sort(first,
                        compare, projection,
                        std::distance(first, last));
        }

        // Iterable overload
        template<
            typename ForwardIterable,
            typename StrictWeakOrdering = std::less<>,
            typename Projection = cppsort::utility::identity,
            typename = std::enable_if_t<cppsort::is_projection<
                Projection, ForwardIterable, StrictWeakOrdering
            >>
        >
        auto operator()(ForwardIterable& iterable, StrictWeakOrdering compare={},
                        Projection projection={}) const
            -> void
        {
            static_assert(
                std::is_base_of<
                    std::forward_iterator_tag,
                    typename std::iterator_traits<decltype(std::begin(iterable))>::iterator_category
                >::value,
                "bubble_sorter requires at least forward iterators"
            );

            bubble_sort(std::begin(iterable),
                        compare, projection,
                        cppsort::utility::size(iterable));
        }
    };
}

struct bubble_sorter:
    cppsort::sorter_facade<detail::bubble_sorter_impl>
{};

namespace cppsort
{
    template<>
    struct sorter_traits<::bubble_sorter>
    {
        using iterator_category = std::forward_iterator_tag;
        using is_stable = std::true_type;
    };
}

#include <array>
#include <cassert>
#include <numeric>
#include <cpp-sort/sort.h>

int main()
{
    // Check that the bubble_sorter can sort any permutation
    // of an array of 8 values

    // Fill the collection in sorted order
    std::array<int, 8> collection;
    std::iota(std::begin(collection), std::end(collection), 0);

    // Projection to sort in descending order
    auto projection = [](int n) { return -n; };

    // For each possible permutation of collection
    do
    {
        auto to_sort = collection;
        // Bubble sort the collection
        cppsort::sort(to_sort, bubble_sorter{}, projection);
        // Check that it is indeed sorted
        assert(std::is_sorted(std::begin(to_sort), std::end(to_sort), std::greater<>{}));
    } while (std::next_permutation(std::begin(collection), std::end(collection)));
}
<commit_msg>Simplify sorter traits in bubble_sorter example.<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Morwenn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iterator>
#include <type_traits>
#include <cpp-sort/sorter_facade.h>
#include <cpp-sort/utility/as_function.h>
#include <cpp-sort/utility/functional.h>
#include <cpp-sort/utility/size.h>

namespace detail
{
    template<
        typename ForwardIterator,
        typename StrictWeakOrdering,
        typename Projection
    >
    auto bubble_sort(ForwardIterator first, StrictWeakOrdering compare,
                     Projection projection, std::size_t size)
        -> void
    {
        if (size < 2) return;

        auto&& proj = cppsort::utility::as_function(projection);

        while (--size)
        {
            ForwardIterator current = first;
            ForwardIterator next = std::next(current);
            for (std::size_t i = 0 ; i < size ; ++i)
            {
                if (compare(proj(*next), proj(*current)))
                {
                    std::iter_swap(current, next);
                }
                ++next;
                ++current;
            }
        }
    }

    struct bubble_sorter_impl
    {
        // Pair of iterators overload
        template<
            typename ForwardIterator,
            typename StrictWeakOrdering = std::less<>,
            typename Projection = cppsort::utility::identity,
            typename = std::enable_if_t<cppsort::is_projection_iterator<
                Projection, ForwardIterator, StrictWeakOrdering
            >>
        >
        auto operator()(ForwardIterator first, ForwardIterator last,
                        StrictWeakOrdering compare={}, Projection projection={}) const
            -> void
        {
            static_assert(
                std::is_base_of<
                    std::forward_iterator_tag,
                    typename std::iterator_traits<ForwardIterator>::iterator_category
                >::value,
                "bubble_sorter requires at least forward iterators"
            );

            bubble_sort(first,
                        compare, projection,
                        std::distance(first, last));
        }

        // Iterable overload
        template<
            typename ForwardIterable,
            typename StrictWeakOrdering = std::less<>,
            typename Projection = cppsort::utility::identity,
            typename = std::enable_if_t<cppsort::is_projection<
                Projection, ForwardIterable, StrictWeakOrdering
            >>
        >
        auto operator()(ForwardIterable& iterable, StrictWeakOrdering compare={},
                        Projection projection={}) const
            -> void
        {
            static_assert(
                std::is_base_of<
                    std::forward_iterator_tag,
                    typename std::iterator_traits<decltype(std::begin(iterable))>::iterator_category
                >::value,
                "bubble_sorter requires at least forward iterators"
            );

            bubble_sort(std::begin(iterable),
                        compare, projection,
                        cppsort::utility::size(iterable));
        }

        // Sorter traits
        using iterator_category = std::forward_iterator_tag;
        using is_stable = std::true_type;
    };
}

struct bubble_sorter:
    cppsort::sorter_facade<detail::bubble_sorter_impl>
{};

#include <array>
#include <cassert>
#include <numeric>
#include <cpp-sort/sort.h>

int main()
{
    // Check that the bubble_sorter can sort any permutation
    // of an array of 8 values

    // Fill the collection in sorted order
    std::array<int, 8> collection;
    std::iota(std::begin(collection), std::end(collection), 0);

    // Projection to sort in descending order
    auto projection = [](int n) { return -n; };

    // For each possible permutation of collection
    do
    {
        auto to_sort = collection;
        // Bubble sort the collection
        cppsort::sort(to_sort, bubble_sorter{}, projection);
        // Check that it is indeed sorted
        assert(std::is_sorted(std::begin(to_sort), std::end(to_sort), std::greater<>{}));
    } while (std::next_permutation(std::begin(collection), std::end(collection)));
}
<|endoftext|>


<commit_before><commit_msg>Update Lab_01_Question_04.cpp<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: translatechanges.cxx,v $
 * $Revision: 1.12 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"

#include "translatechanges.hxx"
#include "noderef.hxx"
#include "nodechange.hxx"
#include "nodechangeinfo.hxx"
#include "apifactory.hxx"

namespace configmgr
{
// ---------------------------------------------------------------------------------------------------
    namespace css = ::com::sun::star;
    namespace uno       = css::uno;
    namespace lang      = css::lang;
    namespace util      = css::util;
    namespace beans     = css::beans;
    namespace container = css::container;
// ---------------------------------------------------------------------------------------------------

    namespace configuration
    {
        class NodeChange;
        class NodeChanges;
        class Tree;
        class NodeRef;
        class NodeID;
    }
// ---------------------------------------------------------------------------------------------------

    namespace configapi
    {
        using configuration::Tree;
        using configuration::TreeRef;
        using configuration::Name;
        using configuration::AbsolutePath;
        using configuration::RelativePath;
        using configuration::NodeRef;
        using configuration::NodeID;
        using configuration::NodeChangeInformation;
        using configuration::NodeChangeData;
        using configuration::NodeChangeLocation;
// ---------------------------------------------------------------------------------------------------
    //interpreting NodeChanges
// resolve the relative path from a given base to the changed node
bool resolveChangeLocation(RelativePath& aPath, NodeChangeLocation const& aChange, Tree const& aBaseTree)
{
    return resolveChangeLocation(aPath,aChange,aBaseTree,aBaseTree.getRootNode());
}
bool resolveChangeLocation(RelativePath& aPath, NodeChangeLocation const& aChange, Tree const& aBaseTree, NodeRef const& aBaseNode)
{
    OSL_ENSURE(aChange.isValidLocation(), "Trying to resolve against change location that wasn't set up properly");

    namespace Path = configuration::Path;

    typedef Path::Iterator Iter;

    Tree aChangeBaseTree = aChange.getBaseTree();

    AbsolutePath aOuterBasePath     = aBaseTree.getAbsolutePath(aBaseNode);
    AbsolutePath aChangeBasePath    = aChangeBaseTree.getAbsolutePath(aChange.getBaseNode());

    Iter aChangeIt = aChangeBasePath.begin(),   aChangeEnd = aChangeBasePath.end();
    Iter aOuterIt  = aOuterBasePath.begin(),    aOuterEnd  = aOuterBasePath.end();

    // First by resolve the base node pathes
    while (aOuterIt != aOuterEnd && aChangeIt != aChangeEnd)
    {
        if ( ! Path::matches(*aOuterIt,*aChangeIt) ) return false; // mismatch
        ++aOuterIt;
        ++aChangeIt;
    }

    // Next consider the stored accessor
    if (aChangeIt != aChangeEnd) // stepping outward - prepend
    {
        Path::Rep aRemaining(aChangeIt, aChangeEnd);

        aPath = RelativePath(aRemaining).compose(aChange.getAccessor());
    }
    else if (aOuterIt == aOuterEnd) // exact match outside
    {
        aPath = aChange.getAccessor();
    }
    else //(aChangeIt == aChangeEnd) but outer left
    {
        RelativePath aAccessor = aChange.getAccessor();
        aChangeIt   = aAccessor.begin();
        aChangeEnd  = aAccessor.end();

        // resolve the outer path against the change accessor
        while (aOuterIt != aOuterEnd && aChangeIt != aChangeEnd)
        {
            if ( ! Path::matches(*aOuterIt,*aChangeIt) ) return false; // mismatch
            ++aOuterIt;
            ++aChangeIt;
        }

        if (aOuterIt == aOuterEnd)
        {
            Path::Rep aRemaining(aChangeIt, aChangeEnd);

            aPath = RelativePath( aRemaining );
        }
    }

    return (aOuterIt == aOuterEnd); // resolved completely and assigned ??

}

// ---------------------------------------------------------------------------------------------------
// change path and base settings to start from the given base
bool rebaseChange(NodeChangeLocation& aChange, TreeRef const& _aBaseTreeRef)
{
    return rebaseChange(aChange,_aBaseTreeRef,_aBaseTreeRef.getRootNode());
}
bool rebaseChange(NodeChangeLocation& aChange, TreeRef const& _aBaseTreeRef, NodeRef const& aBaseNode)
{
    OSL_ENSURE(aChange.isValidLocation(), "Trying to rebase change location that wasn't set up properly");

    Tree aBaseTree(_aBaseTreeRef);

    RelativePath aNewPath;
    if (resolveChangeLocation(aNewPath,aChange,aBaseTree,aBaseNode))
    {
        aChange.setBase( aBaseTree, aBaseNode);
        aChange.setAccessor( aNewPath );
        return true;
    }
    else
        return false;
}
// ---------------------------------------------------------------------------------------------------
// resolve non-uno elements to Uno Objects
bool resolveUnoObjects(UnoChange& aUnoChange, NodeChangeData const& aChange,
                       Factory& rFactory)
{
    if (aChange.isSetChange())
    {
        //Check we have ElementTree
        if ((aChange.element.newValue == NULL) &&
            (aChange.element.oldValue == NULL))
        {
            if( ( aChange.unoData.newValue.getValue()!=NULL) ||
               ( aChange.unoData.newValue.getValue()!=NULL))
            {
                return true;
            }
            else return false;
        }

        //Check if complex or simple type
        Tree aTree = aChange.isRemoveSetChange()?
            aChange.getOldElementTree():
            aChange.getNewElementTree();

        NodeRef aNodeRef = aTree.getRootNode();

        if (configuration::isStructuralNode(aTree, aNodeRef))
        {
            uno::Reference<uno::XInterface> aNewUnoObject = rFactory.findUnoElement(aChange.getNewElementNodeID());
            uno::Reference<uno::XInterface> aOldUnoObject = rFactory.findUnoElement(aChange.getOldElementNodeID());

            bool bFound = aNewUnoObject.is() || aOldUnoObject.is();
            aUnoChange.newValue <<= aNewUnoObject;
            aUnoChange.oldValue <<= aOldUnoObject;
            return bFound;
        }
        else
        {
            aUnoChange.newValue = configuration::getSimpleElementValue(aTree, aNodeRef);

            if (aChange.isReplaceSetChange() )
            {
                Tree aOldTree = aChange.getOldElementTree();

                aNodeRef = aOldTree.getRootNode();
                OSL_ENSURE(!configuration::isStructuralNode(aOldTree, aNodeRef), "resolveUnoObject types mismatch");
                aUnoChange.oldValue =  configuration::getSimpleElementValue(aOldTree, aNodeRef);
            }
            bool bFound = aUnoChange.newValue.hasValue() || aUnoChange.oldValue.hasValue();
            return bFound;
        }
    }
    else if (aChange.isValueChange())
    {
        aUnoChange.newValue = aChange.unoData.newValue;
        aUnoChange.oldValue = aChange.unoData.oldValue;
        return true;
    }
    else
    {
        return false;
    }
}
// ---------------------------------------------------------------------------------------------------
// resolve non-uno elements to Uno Objects inplace
bool resolveToUno(NodeChangeData& aChange, Factory& rFactory)
{
    struct UnoChange aUnoChange;
    if (resolveUnoObjects(aUnoChange,aChange, rFactory))
    {
        aChange.unoData.newValue = aUnoChange.newValue;
        aChange.unoData.oldValue = aUnoChange.oldValue;
        return true;
    }
    else
        return false;
}
// ---------------------------------------------------------------------------------------------------

// building events
/// find the sending api object
void fillEventSource(lang::EventObject& rEvent, Tree const& aTree, NodeRef const& aNode, Factory& rFactory)
{
    rEvent.Source = rFactory.findUnoElement( NodeID(aTree,aNode) );
}
// ---------------------------------------------------------------------------------------------------

/// fill a change info from a NodeChangeInfo
void fillChange(util::ElementChange& rChange, NodeChangeInformation const& aInfo, Tree const& aBaseTree, Factory& rFactory)
{
    fillChange(rChange,aInfo,aBaseTree,aBaseTree.getRootNode(),rFactory);
}
/// fill a change info from a NodeChangeInfo
void fillChange(util::ElementChange& rChange, NodeChangeInformation const& aInfo, Tree const& aBaseTree, NodeRef const& aBaseNode, Factory& rFactory)
{
    RelativePath aRelativePath;
    if (!resolveChangeLocation(aRelativePath, aInfo.location, aBaseTree, aBaseNode))
        OSL_ENSURE(false, "WARNING: Change is not part of the given Tree");

    UnoChange aUnoChange;

    if (!resolveUnoObjects(aUnoChange, aInfo.change, rFactory))
        OSL_ENSURE(false, "WARNING: Cannot find out old/new UNO objects involved in change");

    rChange.Accessor        <<= aRelativePath.toString();
    rChange.Element         = aUnoChange.newValue;
    rChange.ReplacedElement = aUnoChange.oldValue;
}
// ---------------------------------------------------------------------------------------------------
/// fill a change info from a NodeChangeInfo (base,path and uno objects are assumed to be resolved already)
void fillChangeFromResolved(util::ElementChange& rChange, NodeChangeInformation const& aInfo)
{
    rChange.Accessor        <<= aInfo.location.getAccessor().toString();
    rChange.Element         = aInfo.change.unoData.newValue;
    rChange.ReplacedElement = aInfo.change.unoData.oldValue;
}
// ---------------------------------------------------------------------------------------------------

/// fill a event from a NodeChangeInfo
bool fillEventData(container::ContainerEvent& rEvent, NodeChangeInformation const& aInfo, Factory& rFactory)
{
    UnoChange aUnoChange;
    if (!resolveUnoObjects(aUnoChange, aInfo.change, rFactory))
    {
        OSL_ENSURE(false, "WARNING: Cannot find out old/new UNO objects involved in change");
        return false;
    }

    rEvent.Accessor     <<= aInfo.location.getAccessor().getLocalName().getName().toString();
    rEvent.Element          = aUnoChange.newValue;
    rEvent.ReplacedElement  = aUnoChange.oldValue;

    return !aInfo.isEmptyChange();
}
// ---------------------------------------------------------------------------------------------------
/// fill a event from a NodeChangeInfo (uno objects are assumed to be resolved already)
bool fillEventDataFromResolved(container::ContainerEvent& rEvent, NodeChangeInformation const& aInfo)
{
    rEvent.Accessor         <<= aInfo.location.getAccessor().getLocalName().getName().toString();
    rEvent.Element          = aInfo.change.unoData.newValue;
    rEvent.ReplacedElement  = aInfo.change.unoData.oldValue;

    return !aInfo.isEmptyChange();
}
// ---------------------------------------------------------------------------------------------------
/// fill a event from a NodeChangeInfo(uno objects are assumed to be resolved already)
bool fillEventData(beans::PropertyChangeEvent& rEvent, NodeChangeInformation const& aInfo, Factory& rFactory, bool bMore)
{
    if (!aInfo.isValueChange())
        return false;

     UnoChange aUnoChange;
    if (!resolveUnoObjects(aUnoChange, aInfo.change, rFactory))
        OSL_ENSURE(false, "WARNING: Cannot find out old/new UNO objects involved in change");

    rEvent.PropertyName     = aInfo.location.getAccessor().getLocalName().getName().toString();

    rEvent.NewValue         = aUnoChange.newValue;
    rEvent.OldValue         = aUnoChange.oldValue;

    rEvent.PropertyHandle   = -1;
     rEvent.Further         = bMore;

    return !aInfo.isEmptyChange();
}
// ---------------------------------------------------------------------------------------------------
/// fill a event from a NodeChangeInfo(uno objects are assumed to be resolved already)
bool fillEventDataFromResolved(beans::PropertyChangeEvent& rEvent, NodeChangeInformation const& aInfo, bool bMore)
{
    if (!aInfo.isValueChange())
        return false;

    rEvent.PropertyName     = aInfo.location.getAccessor().getLocalName().getName().toString();

    rEvent.NewValue         = aInfo.change.unoData.newValue;
    rEvent.OldValue         = aInfo.change.unoData.oldValue;

    rEvent.PropertyHandle   = -1;
     rEvent.Further         = bMore;

    return !aInfo.isEmptyChange();
}
// ---------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------
    }
// ---------------------------------------------------------------------------------------------------
}

<commit_msg>INTEGRATION: CWS sb88 (1.12.10); FILE MERGED 2008/06/03 15:29:46 sb 1.12.10.1: #i89553 applied patch by cmc<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: translatechanges.cxx,v $
 * $Revision: 1.13 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"

#include "translatechanges.hxx"
#include "noderef.hxx"
#include "nodechange.hxx"
#include "nodechangeinfo.hxx"
#include "apifactory.hxx"

namespace configmgr
{
// ---------------------------------------------------------------------------------------------------
    namespace css = ::com::sun::star;
    namespace uno       = css::uno;
    namespace lang      = css::lang;
    namespace util      = css::util;
    namespace beans     = css::beans;
    namespace container = css::container;
// ---------------------------------------------------------------------------------------------------

    namespace configuration
    {
        class NodeChange;
        class NodeChanges;
        class Tree;
        class NodeRef;
        class NodeID;
    }
// ---------------------------------------------------------------------------------------------------

    namespace configapi
    {
        using configuration::Tree;
        using configuration::TreeRef;
        using configuration::Name;
        using configuration::AbsolutePath;
        using configuration::RelativePath;
        using configuration::NodeRef;
        using configuration::NodeID;
        using configuration::NodeChangeInformation;
        using configuration::NodeChangeData;
        using configuration::NodeChangeLocation;
// ---------------------------------------------------------------------------------------------------
    //interpreting NodeChanges
// resolve the relative path from a given base to the changed node
bool resolveChangeLocation(RelativePath& aPath, NodeChangeLocation const& aChange, Tree const& aBaseTree, NodeRef const& aBaseNode)
{
    OSL_ENSURE(aChange.isValidLocation(), "Trying to resolve against change location that wasn't set up properly");

    namespace Path = configuration::Path;

    typedef Path::Iterator Iter;

    Tree aChangeBaseTree = aChange.getBaseTree();

    AbsolutePath aOuterBasePath     = aBaseTree.getAbsolutePath(aBaseNode);
    AbsolutePath aChangeBasePath    = aChangeBaseTree.getAbsolutePath(aChange.getBaseNode());

    Iter aChangeIt = aChangeBasePath.begin(),   aChangeEnd = aChangeBasePath.end();
    Iter aOuterIt  = aOuterBasePath.begin(),    aOuterEnd  = aOuterBasePath.end();

    // First by resolve the base node pathes
    while (aOuterIt != aOuterEnd && aChangeIt != aChangeEnd)
    {
        if ( ! Path::matches(*aOuterIt,*aChangeIt) ) return false; // mismatch
        ++aOuterIt;
        ++aChangeIt;
    }

    // Next consider the stored accessor
    if (aChangeIt != aChangeEnd) // stepping outward - prepend
    {
        Path::Rep aRemaining(aChangeIt, aChangeEnd);

        aPath = RelativePath(aRemaining).compose(aChange.getAccessor());
    }
    else if (aOuterIt == aOuterEnd) // exact match outside
    {
        aPath = aChange.getAccessor();
    }
    else //(aChangeIt == aChangeEnd) but outer left
    {
        RelativePath aAccessor = aChange.getAccessor();
        aChangeIt   = aAccessor.begin();
        aChangeEnd  = aAccessor.end();

        // resolve the outer path against the change accessor
        while (aOuterIt != aOuterEnd && aChangeIt != aChangeEnd)
        {
            if ( ! Path::matches(*aOuterIt,*aChangeIt) ) return false; // mismatch
            ++aOuterIt;
            ++aChangeIt;
        }

        if (aOuterIt == aOuterEnd)
        {
            Path::Rep aRemaining(aChangeIt, aChangeEnd);

            aPath = RelativePath( aRemaining );
        }
    }

    return (aOuterIt == aOuterEnd); // resolved completely and assigned ??

}

// ---------------------------------------------------------------------------------------------------
// change path and base settings to start from the given base
bool rebaseChange(NodeChangeLocation& aChange, TreeRef const& _aBaseTreeRef)
{
    return rebaseChange(aChange,_aBaseTreeRef,_aBaseTreeRef.getRootNode());
}
bool rebaseChange(NodeChangeLocation& aChange, TreeRef const& _aBaseTreeRef, NodeRef const& aBaseNode)
{
    OSL_ENSURE(aChange.isValidLocation(), "Trying to rebase change location that wasn't set up properly");

    Tree aBaseTree(_aBaseTreeRef);

    RelativePath aNewPath;
    if (resolveChangeLocation(aNewPath,aChange,aBaseTree,aBaseNode))
    {
        aChange.setBase( aBaseTree, aBaseNode);
        aChange.setAccessor( aNewPath );
        return true;
    }
    else
        return false;
}
// ---------------------------------------------------------------------------------------------------
// resolve non-uno elements to Uno Objects
bool resolveUnoObjects(UnoChange& aUnoChange, NodeChangeData const& aChange,
                       Factory& rFactory)
{
    if (aChange.isSetChange())
    {
        //Check we have ElementTree
        if ((aChange.element.newValue == NULL) &&
            (aChange.element.oldValue == NULL))
        {
            if( ( aChange.unoData.newValue.getValue()!=NULL) ||
               ( aChange.unoData.newValue.getValue()!=NULL))
            {
                return true;
            }
            else return false;
        }

        //Check if complex or simple type
        Tree aTree = aChange.isRemoveSetChange()?
            aChange.getOldElementTree():
            aChange.getNewElementTree();

        NodeRef aNodeRef = aTree.getRootNode();

        if (configuration::isStructuralNode(aTree, aNodeRef))
        {
            uno::Reference<uno::XInterface> aNewUnoObject = rFactory.findUnoElement(aChange.getNewElementNodeID());
            uno::Reference<uno::XInterface> aOldUnoObject = rFactory.findUnoElement(aChange.getOldElementNodeID());

            bool bFound = aNewUnoObject.is() || aOldUnoObject.is();
            aUnoChange.newValue <<= aNewUnoObject;
            aUnoChange.oldValue <<= aOldUnoObject;
            return bFound;
        }
        else
        {
            aUnoChange.newValue = configuration::getSimpleElementValue(aTree, aNodeRef);

            if (aChange.isReplaceSetChange() )
            {
                Tree aOldTree = aChange.getOldElementTree();

                aNodeRef = aOldTree.getRootNode();
                OSL_ENSURE(!configuration::isStructuralNode(aOldTree, aNodeRef), "resolveUnoObject types mismatch");
                aUnoChange.oldValue =  configuration::getSimpleElementValue(aOldTree, aNodeRef);
            }
            bool bFound = aUnoChange.newValue.hasValue() || aUnoChange.oldValue.hasValue();
            return bFound;
        }
    }
    else if (aChange.isValueChange())
    {
        aUnoChange.newValue = aChange.unoData.newValue;
        aUnoChange.oldValue = aChange.unoData.oldValue;
        return true;
    }
    else
    {
        return false;
    }
}
// ---------------------------------------------------------------------------------------------------
// resolve non-uno elements to Uno Objects inplace
bool resolveToUno(NodeChangeData& aChange, Factory& rFactory)
{
    struct UnoChange aUnoChange;
    if (resolveUnoObjects(aUnoChange,aChange, rFactory))
    {
        aChange.unoData.newValue = aUnoChange.newValue;
        aChange.unoData.oldValue = aUnoChange.oldValue;
        return true;
    }
    else
        return false;
}
// ---------------------------------------------------------------------------------------------------

/// fill a change info from a NodeChangeInfo
void fillChange(util::ElementChange& rChange, NodeChangeInformation const& aInfo, Tree const& aBaseTree, Factory& rFactory)
{
    fillChange(rChange,aInfo,aBaseTree,aBaseTree.getRootNode(),rFactory);
}
/// fill a change info from a NodeChangeInfo
void fillChange(util::ElementChange& rChange, NodeChangeInformation const& aInfo, Tree const& aBaseTree, NodeRef const& aBaseNode, Factory& rFactory)
{
    RelativePath aRelativePath;
    if (!resolveChangeLocation(aRelativePath, aInfo.location, aBaseTree, aBaseNode))
        OSL_ENSURE(false, "WARNING: Change is not part of the given Tree");

    UnoChange aUnoChange;

    if (!resolveUnoObjects(aUnoChange, aInfo.change, rFactory))
        OSL_ENSURE(false, "WARNING: Cannot find out old/new UNO objects involved in change");

    rChange.Accessor        <<= aRelativePath.toString();
    rChange.Element         = aUnoChange.newValue;
    rChange.ReplacedElement = aUnoChange.oldValue;
}
// ---------------------------------------------------------------------------------------------------
/// fill a change info from a NodeChangeInfo (base,path and uno objects are assumed to be resolved already)
void fillChangeFromResolved(util::ElementChange& rChange, NodeChangeInformation const& aInfo)
{
    rChange.Accessor        <<= aInfo.location.getAccessor().toString();
    rChange.Element         = aInfo.change.unoData.newValue;
    rChange.ReplacedElement = aInfo.change.unoData.oldValue;
}
// ---------------------------------------------------------------------------------------------------
/// fill a event from a NodeChangeInfo (uno objects are assumed to be resolved already)
bool fillEventDataFromResolved(container::ContainerEvent& rEvent, NodeChangeInformation const& aInfo)
{
    rEvent.Accessor         <<= aInfo.location.getAccessor().getLocalName().getName().toString();
    rEvent.Element          = aInfo.change.unoData.newValue;
    rEvent.ReplacedElement  = aInfo.change.unoData.oldValue;

    return !aInfo.isEmptyChange();
}
// ---------------------------------------------------------------------------------------------------
/// fill a event from a NodeChangeInfo(uno objects are assumed to be resolved already)
bool fillEventDataFromResolved(beans::PropertyChangeEvent& rEvent, NodeChangeInformation const& aInfo, bool bMore)
{
    if (!aInfo.isValueChange())
        return false;

    rEvent.PropertyName     = aInfo.location.getAccessor().getLocalName().getName().toString();

    rEvent.NewValue         = aInfo.change.unoData.newValue;
    rEvent.OldValue         = aInfo.change.unoData.oldValue;

    rEvent.PropertyHandle   = -1;
     rEvent.Further         = bMore;

    return !aInfo.isEmptyChange();
}
// ---------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------
    }
// ---------------------------------------------------------------------------------------------------
}

<|endoftext|>