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

#include "base/run_loop.h"
#include "chrome/browser/extensions/api/gcm/gcm_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/services/gcm/fake_gcm_profile_service.h"
#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
#include "chrome/test/base/ui_test_utils.h"

namespace {

const char kFunctionsTestExtension[] = "gcm/functions";
const char kEventsExtension[] = "gcm/events";

}  // namespace

namespace extensions {

class GcmApiTest : public ExtensionApiTest {
 public:
  GcmApiTest() : fake_gcm_profile_service_(NULL) {}

 protected:
  virtual void SetUpOnMainThread() OVERRIDE;

  void StartCollecting();

  const Extension* LoadTestExtension(const std::string& extension_path,
                                     const std::string& page_name);

  void WaitUntilIdle();

  gcm::FakeGCMProfileService* service() const;

  gcm::FakeGCMProfileService* fake_gcm_profile_service_;
};

void GcmApiTest::SetUpOnMainThread() {
  gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactory(
      browser()->profile(), &gcm::FakeGCMProfileService::Build);
  fake_gcm_profile_service_ = static_cast<gcm::FakeGCMProfileService*>(
      gcm::GCMProfileServiceFactory::GetInstance()->GetForProfile(
          browser()->profile()));
  gcm::FakeGCMProfileService::EnableGCMForTesting();
}

void GcmApiTest::StartCollecting() {
  service()->set_collect(true);
}

void GcmApiTest::WaitUntilIdle() {
  base::RunLoop run_loop;
  run_loop.RunUntilIdle();
}

gcm::FakeGCMProfileService* GcmApiTest::service() const {
  return fake_gcm_profile_service_;
}

const Extension* GcmApiTest::LoadTestExtension(
    const std::string& extension_path,
    const std::string& page_name) {
  const Extension* extension =
      LoadExtension(test_data_dir_.AppendASCII(extension_path));
  if (extension) {
    ui_test_utils::NavigateToURL(
        browser(), extension->GetResourceURL(page_name));
  }
  return extension;
}

// http://crbug.com/177163 and http://crbug.com/324982
#if defined(OS_WIN)
#define MAYBE_RegisterValidation DISABLED_RegisterValidation
#else
#define MAYBE_RegisterValidation RegisterValidation
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_RegisterValidation) {
  EXPECT_TRUE(RunExtensionSubtest(kFunctionsTestExtension,
                                  "register_validation.html"));
}

// http://crbug.com/177163 and http://crbug.com/324982
#if defined(OS_WIN)
#define MAYBE_Register DISABLED_Register
#else
#define MAYBE_Register Register
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_Register) {
  StartCollecting();
  const extensions::Extension* extension =
      LoadTestExtension(kFunctionsTestExtension, "register.html");
  ASSERT_TRUE(extension);

  WaitUntilIdle();

  EXPECT_EQ(extension->id(), service()->last_registered_app_id());
  // SHA1 of the public key provided in manifest.json.
  EXPECT_EQ("26469186F238EE08FA71C38311C6990F61D40DCA",
            service()->last_registered_cert());
  const std::vector<std::string>& sender_ids =
      service()->last_registered_sender_ids();
  EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender1") !=
                  sender_ids.end());
  EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender2") !=
                  sender_ids.end());
}

// http://crbug.com/177163 and http://crbug.com/324982
#if defined(OS_WIN)
#define MAYBE_SendValidation DISABLED_SendValidation
#else
#define MAYBE_SendValidation SendValidation
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_SendValidation) {
  EXPECT_TRUE(RunExtensionSubtest(kFunctionsTestExtension, "send.html"));
}

// http://crbug.com/177163 and http://crbug.com/324982
#if defined(OS_WIN)
#define MAYBE_SendMessageData DISABLED_SendMessageData
#else
#define MAYBE_SendMessageData SendMessageData
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_SendMessageData) {
  StartCollecting();
  const extensions::Extension* extension =
      LoadTestExtension(kFunctionsTestExtension, "send_message_data.html");
  ASSERT_TRUE(extension);

  WaitUntilIdle();

  EXPECT_EQ("destination-id", service()->last_receiver_id());
  const gcm::GCMClient::OutgoingMessage& message =
      service()->last_sent_message();
  gcm::GCMClient::MessageData::const_iterator iter;

  EXPECT_TRUE((iter = message.data.find("key1")) != message.data.end());
  EXPECT_EQ("value1", iter->second);

  EXPECT_TRUE((iter = message.data.find("key2")) != message.data.end());
  EXPECT_EQ("value2", iter->second);
}

// http://crbug.com/177163 and http://crbug/324982
#if defined(OS_WIN) && !defined(NDEBUG)
#define MAYBE_OnMessagesDeleted DISABLED_OnMessagesDeleted
#else
#define MAYBE_OnMessagesDeleted OnMessagesDeleted
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_OnMessagesDeleted) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(profile());

  const extensions::Extension* extension =
      LoadTestExtension(kEventsExtension, "on_messages_deleted.html");
  ASSERT_TRUE(extension);

  GcmJsEventRouter router(profile());
  router.OnMessagesDeleted(extension->id());
  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// http://crbug.com/177163 and http://crbug/324982
#if defined(OS_WIN) && !defined(NDEBUG)
#define MAYBE_OnMessage DISABLED_OnMessage
#else
#define MAYBE_OnMessage OnMessage
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_OnMessage) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(profile());

  const extensions::Extension* extension =
      LoadTestExtension(kEventsExtension, "on_message.html");
  ASSERT_TRUE(extension);

  GcmJsEventRouter router(profile());

  gcm::GCMClient::IncomingMessage message;
  message.data["property1"] = "value1";
  message.data["property2"] = "value2";
  router.OnMessage(extension->id(), message);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// http://crbug.com/177163 and http://crbug/324982
#if defined(OS_WIN) && !defined(NDEBUG)
#define MAYBE_OnSendError DISABLED_OnSendError
#else
#define MAYBE_OnSendError OnSendError
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_OnSendError) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(profile());

  const extensions::Extension* extension =
      LoadTestExtension(kEventsExtension, "on_send_error.html");
  ASSERT_TRUE(extension);

  GcmJsEventRouter router(profile());
  router.OnSendError(extension->id(), "error_message_1",
      gcm::GCMClient::ASYNC_OPERATION_PENDING);
  router.OnSendError(extension->id(), "error_message_2",
      gcm::GCMClient::SERVER_ERROR);
  router.OnSendError(extension->id(), "error_message_3",
      gcm::GCMClient::NETWORK_ERROR);
  router.OnSendError(extension->id(), "error_message_4",
      gcm::GCMClient::UNKNOWN_ERROR);
  router.OnSendError(extension->id(), "error_message_5",
      gcm::GCMClient::TTL_EXCEEDED);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

}  // namespace extensions
<commit_msg>Enable most of GCM API tests on Windows<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/run_loop.h"
#include "chrome/browser/extensions/api/gcm/gcm_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/services/gcm/fake_gcm_profile_service.h"
#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/test/base/ui_test_utils.h"

namespace {

const char kFunctionsTestExtension[] = "gcm/functions";
const char kEventsExtension[] = "gcm/events";

}  // namespace

namespace extensions {

class GcmApiTest : public ExtensionApiTest {
 public:
  GcmApiTest() : fake_gcm_profile_service_(NULL) {}

 protected:
  virtual void SetUpOnMainThread() OVERRIDE;

  void StartCollecting();

  const Extension* LoadTestExtension(const std::string& extension_path,
                                     const std::string& page_name);

  void WaitUntilIdle();

  gcm::FakeGCMProfileService* service() const;

  gcm::FakeGCMProfileService* fake_gcm_profile_service_;
};

void GcmApiTest::SetUpOnMainThread() {
  gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactory(
      browser()->profile(), &gcm::FakeGCMProfileService::Build);
  fake_gcm_profile_service_ = static_cast<gcm::FakeGCMProfileService*>(
      gcm::GCMProfileServiceFactory::GetInstance()->GetForProfile(
          browser()->profile()));
  gcm::FakeGCMProfileService::EnableGCMForTesting();
}

void GcmApiTest::StartCollecting() {
  service()->set_collect(true);
}

void GcmApiTest::WaitUntilIdle() {
  base::RunLoop run_loop;
  run_loop.RunUntilIdle();
}

gcm::FakeGCMProfileService* GcmApiTest::service() const {
  return fake_gcm_profile_service_;
}

const Extension* GcmApiTest::LoadTestExtension(
    const std::string& extension_path,
    const std::string& page_name) {
  // TODO(jianli): Once the GCM API enters stable, remove |channel|.
  ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_UNKNOWN);
  const Extension* extension =
      LoadExtension(test_data_dir_.AppendASCII(extension_path));
  if (extension) {
    ui_test_utils::NavigateToURL(
        browser(), extension->GetResourceURL(page_name));
  }
  return extension;
}

// http://crbug.com/177163
#if defined(OS_WIN)
#define MAYBE_RegisterValidation DISABLED_RegisterValidation
#else
#define MAYBE_RegisterValidation RegisterValidation
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_RegisterValidation) {
  EXPECT_TRUE(RunExtensionSubtest(kFunctionsTestExtension,
                                  "register_validation.html"));
}

IN_PROC_BROWSER_TEST_F(GcmApiTest, Register) {
  StartCollecting();
  const extensions::Extension* extension =
      LoadTestExtension(kFunctionsTestExtension, "register.html");
  ASSERT_TRUE(extension);

  WaitUntilIdle();

  EXPECT_EQ(extension->id(), service()->last_registered_app_id());
  // SHA1 of the public key provided in manifest.json.
  EXPECT_EQ("26469186F238EE08FA71C38311C6990F61D40DCA",
            service()->last_registered_cert());
  const std::vector<std::string>& sender_ids =
      service()->last_registered_sender_ids();
  EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender1") !=
                  sender_ids.end());
  EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender2") !=
                  sender_ids.end());
}

// http://crbug.com/177163
#if defined(OS_WIN)
#define MAYBE_SendValidation DISABLED_SendValidation
#else
#define MAYBE_SendValidation SendValidation
#endif
IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_SendValidation) {
  EXPECT_TRUE(RunExtensionSubtest(kFunctionsTestExtension, "send.html"));
}

IN_PROC_BROWSER_TEST_F(GcmApiTest, SendMessageData) {
  StartCollecting();
  const extensions::Extension* extension =
      LoadTestExtension(kFunctionsTestExtension, "send_message_data.html");
  ASSERT_TRUE(extension);

  WaitUntilIdle();

  EXPECT_EQ("destination-id", service()->last_receiver_id());
  const gcm::GCMClient::OutgoingMessage& message =
      service()->last_sent_message();
  gcm::GCMClient::MessageData::const_iterator iter;

  EXPECT_TRUE((iter = message.data.find("key1")) != message.data.end());
  EXPECT_EQ("value1", iter->second);

  EXPECT_TRUE((iter = message.data.find("key2")) != message.data.end());
  EXPECT_EQ("value2", iter->second);
}

IN_PROC_BROWSER_TEST_F(GcmApiTest, OnMessagesDeleted) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(profile());

  const extensions::Extension* extension =
      LoadTestExtension(kEventsExtension, "on_messages_deleted.html");
  ASSERT_TRUE(extension);

  GcmJsEventRouter router(profile());
  router.OnMessagesDeleted(extension->id());
  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

IN_PROC_BROWSER_TEST_F(GcmApiTest, OnMessage) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(profile());

  const extensions::Extension* extension =
      LoadTestExtension(kEventsExtension, "on_message.html");
  ASSERT_TRUE(extension);

  GcmJsEventRouter router(profile());

  gcm::GCMClient::IncomingMessage message;
  message.data["property1"] = "value1";
  message.data["property2"] = "value2";
  router.OnMessage(extension->id(), message);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

IN_PROC_BROWSER_TEST_F(GcmApiTest, OnSendError) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(profile());

  const extensions::Extension* extension =
      LoadTestExtension(kEventsExtension, "on_send_error.html");
  ASSERT_TRUE(extension);

  GcmJsEventRouter router(profile());
  router.OnSendError(extension->id(), "error_message_1",
      gcm::GCMClient::ASYNC_OPERATION_PENDING);
  router.OnSendError(extension->id(), "error_message_2",
      gcm::GCMClient::SERVER_ERROR);
  router.OnSendError(extension->id(), "error_message_3",
      gcm::GCMClient::NETWORK_ERROR);
  router.OnSendError(extension->id(), "error_message_4",
      gcm::GCMClient::UNKNOWN_ERROR);
  router.OnSendError(extension->id(), "error_message_5",
      gcm::GCMClient::TTL_EXCEEDED);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

}  // namespace extensions
<|endoftext|>


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

#include "chrome/browser/extensions/extension_file_util.h"

#include "base/file_util.h"
#include "base/logging.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/json_value_serializer.h"
#include "net/base/file_stream.h"

namespace extension_file_util {

const char kInstallDirectoryName[] = "Extensions";
const char kCurrentVersionFileName[] = "Current Version";

bool MoveDirSafely(const FilePath& source_dir, const FilePath& dest_dir) {
  if (file_util::PathExists(dest_dir)) {
    if (!file_util::Delete(dest_dir, true))
      return false;
  } else {
    FilePath parent = dest_dir.DirName();
    if (!file_util::DirectoryExists(parent)) {
      if (!file_util::CreateDirectory(parent))
        return false;
    }
  }

  if (!file_util::Move(source_dir, dest_dir))
    return false;

  return true;
}

bool SetCurrentVersion(const FilePath& dest_dir, const std::string& version,
                       std::string* error) {
  // Write out the new CurrentVersion file.
  // <profile>/Extension/<name>/CurrentVersion
  FilePath current_version = dest_dir.AppendASCII(kCurrentVersionFileName);
  FilePath current_version_old =
    current_version.InsertBeforeExtension(FILE_PATH_LITERAL("_old"));
  if (file_util::PathExists(current_version_old)) {
    if (!file_util::Delete(current_version_old, false)) {
      *error = "Couldn't remove CurrentVersion_old file.";
      return false;
    }
  }

  if (file_util::PathExists(current_version)) {
    if (!file_util::Move(current_version, current_version_old)) {
      *error = "Couldn't move CurrentVersion file.";
      return false;
    }
  }
  net::FileStream stream;
  int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
  if (stream.Open(current_version, flags) != 0)
    return false;
  if (stream.Write(version.c_str(), version.size(), NULL) < 0) {
    // Restore the old CurrentVersion.
    if (file_util::PathExists(current_version_old)) {
      if (!file_util::Move(current_version_old, current_version)) {
        LOG(WARNING) << "couldn't restore " << current_version_old.value() <<
            " to " << current_version.value();

        // TODO(erikkay): This is an ugly state to be in.  Try harder?
      }
    }
    *error = "Couldn't create CurrentVersion file.";
    return false;
  }
  return true;
}

bool ReadCurrentVersion(const FilePath& dir, std::string* version_string) {
  FilePath current_version = dir.AppendASCII(kCurrentVersionFileName);
  if (file_util::PathExists(current_version)) {
    if (file_util::ReadFileToString(current_version, version_string)) {
      TrimWhitespace(*version_string, TRIM_ALL, version_string);
      return true;
    }
  }
  return false;
}

Extension::InstallType CompareToInstalledVersion(
    const FilePath& install_directory, const std::string& id,
    const std::string& new_version_str, std::string *current_version_str) {
  CHECK(current_version_str);
  FilePath dir(install_directory.AppendASCII(id.c_str()));
  if (!ReadCurrentVersion(dir, current_version_str))
    return Extension::NEW_INSTALL;

  scoped_ptr<Version> current_version(
    Version::GetVersionFromString(*current_version_str));
  scoped_ptr<Version> new_version(
    Version::GetVersionFromString(new_version_str));
  int comp = new_version->CompareTo(*current_version);
  if (comp > 0)
    return Extension::UPGRADE;
  else if (comp == 0)
    return Extension::REINSTALL;
  else
    return Extension::DOWNGRADE;
}

bool SanityCheckExtension(const FilePath& dir) {
  // Verify that the directory actually exists.
  // TODO(erikkay): A further step would be to verify that the extension
  // has actually loaded successfully.
  FilePath manifest_file(dir.AppendASCII(Extension::kManifestFilename));
  return file_util::PathExists(dir) && file_util::PathExists(manifest_file);
}

bool InstallExtension(const FilePath& src_dir,
                      const FilePath& extensions_dir,
                      const std::string& extension_id,
                      const std::string& extension_version,
                      FilePath* version_dir,
                      Extension::InstallType* install_type,
                      std::string* error) {
  FilePath dest_dir = extensions_dir.AppendASCII(extension_id);
  *version_dir = dest_dir.AppendASCII(extension_version);

  std::string current_version;
  *install_type = CompareToInstalledVersion(
      extensions_dir, extension_id, extension_version, &current_version);

  // Do not allow downgrade.
  if (*install_type == Extension::DOWNGRADE)
    return true;

  if (*install_type == Extension::REINSTALL) {
    if (!SanityCheckExtension(*version_dir)) {
      // Treat corrupted existing installation as new install case.
      *install_type = Extension::NEW_INSTALL;
    } else {
      return true;
    }
  }

  // If anything fails after this, we want to delete the extension dir.
  ScopedTempDir scoped_version_dir;
  scoped_version_dir.Set(*version_dir);

  if (!MoveDirSafely(src_dir, *version_dir)) {
    *error = "Could not move extension directory into profile.";
    return false;
  }

  if (!SetCurrentVersion(dest_dir, extension_version, error))
    return false;

  scoped_version_dir.Take();
  return true;
}

Extension* LoadExtension(const FilePath& extension_path, bool require_key,
                         std::string* error) {
  FilePath manifest_path =
      extension_path.AppendASCII(Extension::kManifestFilename);
  if (!file_util::PathExists(manifest_path)) {
    *error = extension_manifest_errors::kInvalidManifest;
    return NULL;
  }

  JSONFileValueSerializer serializer(manifest_path);
  scoped_ptr<Value> root(serializer.Deserialize(error));
  if (!root.get())
    return NULL;

  if (!root->IsType(Value::TYPE_DICTIONARY)) {
    *error = extension_manifest_errors::kInvalidManifest;
    return NULL;
  }

  scoped_ptr<Extension> extension(new Extension(extension_path));
  if (!extension->InitFromValue(*static_cast<DictionaryValue*>(root.get()),
                                require_key, error))
    return NULL;

  // Validate icons exist.
  for (std::map<int, std::string>::const_iterator iter =
       extension->icons().begin(); iter != extension->icons().end(); ++iter) {
    if (!file_util::PathExists(extension->GetResourcePath(iter->second))) {
      *error = StringPrintf("Could not load extension icon '%s'.",
                            iter->second.c_str());
      return NULL;
    }
  }

  // Theme resource validation.
  if (extension->IsTheme()) {
    DictionaryValue* images_value = extension->GetThemeImages();
    DictionaryValue::key_iterator iter = images_value->begin_keys();
    if (images_value) {
      while (iter != images_value->end_keys()) {
        std::string val;
        if (images_value->GetString(*iter , &val)) {
          FilePath image_path = extension->path().AppendASCII(val);
          if (!file_util::PathExists(image_path)) {
            *error = StringPrintf(
                "Could not load '%s' for theme.",
                WideToUTF8(image_path.ToWStringHack()).c_str());
            return NULL;
          }
        }
        ++iter;
      }
    }

    // Themes cannot contain other extension types.
    return extension.release();
  }

  // Validate that claimed script resources actually exist.
  for (size_t i = 0; i < extension->content_scripts().size(); ++i) {
    const UserScript& script = extension->content_scripts()[i];

    for (size_t j = 0; j < script.js_scripts().size(); j++) {
      const FilePath& path = script.js_scripts()[j].path();
      if (!file_util::PathExists(path)) {
        *error = StringPrintf("Could not load '%s' for content script.",
                              WideToUTF8(path.ToWStringHack()).c_str());
        return NULL;
      }
    }

    for (size_t j = 0; j < script.css_scripts().size(); j++) {
      const FilePath& path = script.css_scripts()[j].path();
      if (!file_util::PathExists(path)) {
        *error = StringPrintf("Could not load '%s' for content script.",
                              WideToUTF8(path.ToWStringHack()).c_str());
        return NULL;
      }
    }
  }

  for (size_t i = 0; i < extension->plugins().size(); ++i) {
    const Extension::PluginInfo& plugin = extension->plugins()[i];
    if (!file_util::PathExists(plugin.path)) {
      *error = StringPrintf("Could not load '%s' for plugin.",
                            WideToUTF8(plugin.path.ToWStringHack()).c_str());
      return NULL;
    }
  }

  // Validate icon location for page actions.
  const PageActionMap& page_actions = extension->page_actions();
  for (PageActionMap::const_iterator i(page_actions.begin());
       i != page_actions.end(); ++i) {
    PageAction* page_action = i->second;
    const std::vector<FilePath>& icon_paths = page_action->icon_paths();
    for (std::vector<FilePath>::const_iterator iter = icon_paths.begin();
         iter != icon_paths.end(); ++iter) {
      FilePath path = *iter;
      if (!file_util::PathExists(path)) {
        *error = StringPrintf("Could not load icon '%s' for page action.",
                              WideToUTF8(path.ToWStringHack()).c_str());
        return NULL;
      }
    }
  }

  return extension.release();
}

void UninstallExtension(const std::string& id, const FilePath& extensions_dir) {
  // First, delete the Current Version file. If the directory delete fails, then
  // at least the extension won't be loaded again.
  FilePath extension_root = extensions_dir.AppendASCII(id);

  if (!file_util::PathExists(extension_root)) {
    LOG(WARNING) << "Asked to remove a non-existent extension " << id;
    return;
  }

  FilePath current_version_file = extension_root.AppendASCII(
      kCurrentVersionFileName);
  if (!file_util::PathExists(current_version_file)) {
    LOG(WARNING) << "Extension " << id
                 << " does not have a Current Version file.";
  } else {
    if (!file_util::Delete(current_version_file, false)) {
      LOG(WARNING) << "Could not delete Current Version file for extension "
                   << id;
      return;
    }
  }

  // OK, now try and delete the entire rest of the directory. One major place
  // this can fail is if the extension contains a plugin (stupid plugins). It's
  // not a big deal though, because we'll notice next time we startup that the
  // Current Version file is gone and finish the delete then.
  if (!file_util::Delete(extension_root, true))
    LOG(WARNING) << "Could not delete directory for extension " << id;
}

void GarbageCollectExtensions(const FilePath& install_directory) {
  // Nothing to clean up if it doesn't exist.
  if (!file_util::DirectoryExists(install_directory))
    return;

  LOG(INFO) << "Loading installed extensions...";
  file_util::FileEnumerator enumerator(install_directory,
                                       false,  // Not recursive.
                                       file_util::FileEnumerator::DIRECTORIES);
  FilePath extension_path;
  for (extension_path = enumerator.Next(); !extension_path.value().empty();
       extension_path = enumerator.Next()) {
    std::string extension_id = WideToASCII(
        extension_path.BaseName().ToWStringHack());

    // If there is no Current Version file, just delete the directory and move
    // on. This can legitimately happen when an uninstall does not complete, for
    // example, when a plugin is in use at uninstall time.
    FilePath current_version_path = extension_path.AppendASCII(
        kCurrentVersionFileName);
    if (!file_util::PathExists(current_version_path)) {
      LOG(INFO) << "Deleting incomplete install for directory "
                << WideToASCII(extension_path.ToWStringHack()) << ".";
      file_util::Delete(extension_path, true);  // Recursive.
      continue;
    }

    // Ignore directories that aren't valid IDs.
    if (!Extension::IdIsValid(extension_id)) {
      LOG(WARNING) << "Invalid extension ID encountered in extensions "
                      "directory: " << extension_id;
      LOG(INFO) << "Deleting invalid extension directory "
                << WideToASCII(extension_path.ToWStringHack()) << ".";
      file_util::Delete(extension_path, true);  // Recursive.
      continue;
    }
  }
}

}  // extensionfile_util
<commit_msg>Put the null pointer check for theme images before we use the pointer.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_file_util.h"

#include "base/file_util.h"
#include "base/logging.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/json_value_serializer.h"
#include "net/base/file_stream.h"

namespace extension_file_util {

const char kInstallDirectoryName[] = "Extensions";
const char kCurrentVersionFileName[] = "Current Version";

bool MoveDirSafely(const FilePath& source_dir, const FilePath& dest_dir) {
  if (file_util::PathExists(dest_dir)) {
    if (!file_util::Delete(dest_dir, true))
      return false;
  } else {
    FilePath parent = dest_dir.DirName();
    if (!file_util::DirectoryExists(parent)) {
      if (!file_util::CreateDirectory(parent))
        return false;
    }
  }

  if (!file_util::Move(source_dir, dest_dir))
    return false;

  return true;
}

bool SetCurrentVersion(const FilePath& dest_dir, const std::string& version,
                       std::string* error) {
  // Write out the new CurrentVersion file.
  // <profile>/Extension/<name>/CurrentVersion
  FilePath current_version = dest_dir.AppendASCII(kCurrentVersionFileName);
  FilePath current_version_old =
    current_version.InsertBeforeExtension(FILE_PATH_LITERAL("_old"));
  if (file_util::PathExists(current_version_old)) {
    if (!file_util::Delete(current_version_old, false)) {
      *error = "Couldn't remove CurrentVersion_old file.";
      return false;
    }
  }

  if (file_util::PathExists(current_version)) {
    if (!file_util::Move(current_version, current_version_old)) {
      *error = "Couldn't move CurrentVersion file.";
      return false;
    }
  }
  net::FileStream stream;
  int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
  if (stream.Open(current_version, flags) != 0)
    return false;
  if (stream.Write(version.c_str(), version.size(), NULL) < 0) {
    // Restore the old CurrentVersion.
    if (file_util::PathExists(current_version_old)) {
      if (!file_util::Move(current_version_old, current_version)) {
        LOG(WARNING) << "couldn't restore " << current_version_old.value() <<
            " to " << current_version.value();

        // TODO(erikkay): This is an ugly state to be in.  Try harder?
      }
    }
    *error = "Couldn't create CurrentVersion file.";
    return false;
  }
  return true;
}

bool ReadCurrentVersion(const FilePath& dir, std::string* version_string) {
  FilePath current_version = dir.AppendASCII(kCurrentVersionFileName);
  if (file_util::PathExists(current_version)) {
    if (file_util::ReadFileToString(current_version, version_string)) {
      TrimWhitespace(*version_string, TRIM_ALL, version_string);
      return true;
    }
  }
  return false;
}

Extension::InstallType CompareToInstalledVersion(
    const FilePath& install_directory, const std::string& id,
    const std::string& new_version_str, std::string *current_version_str) {
  CHECK(current_version_str);
  FilePath dir(install_directory.AppendASCII(id.c_str()));
  if (!ReadCurrentVersion(dir, current_version_str))
    return Extension::NEW_INSTALL;

  scoped_ptr<Version> current_version(
    Version::GetVersionFromString(*current_version_str));
  scoped_ptr<Version> new_version(
    Version::GetVersionFromString(new_version_str));
  int comp = new_version->CompareTo(*current_version);
  if (comp > 0)
    return Extension::UPGRADE;
  else if (comp == 0)
    return Extension::REINSTALL;
  else
    return Extension::DOWNGRADE;
}

bool SanityCheckExtension(const FilePath& dir) {
  // Verify that the directory actually exists.
  // TODO(erikkay): A further step would be to verify that the extension
  // has actually loaded successfully.
  FilePath manifest_file(dir.AppendASCII(Extension::kManifestFilename));
  return file_util::PathExists(dir) && file_util::PathExists(manifest_file);
}

bool InstallExtension(const FilePath& src_dir,
                      const FilePath& extensions_dir,
                      const std::string& extension_id,
                      const std::string& extension_version,
                      FilePath* version_dir,
                      Extension::InstallType* install_type,
                      std::string* error) {
  FilePath dest_dir = extensions_dir.AppendASCII(extension_id);
  *version_dir = dest_dir.AppendASCII(extension_version);

  std::string current_version;
  *install_type = CompareToInstalledVersion(
      extensions_dir, extension_id, extension_version, &current_version);

  // Do not allow downgrade.
  if (*install_type == Extension::DOWNGRADE)
    return true;

  if (*install_type == Extension::REINSTALL) {
    if (!SanityCheckExtension(*version_dir)) {
      // Treat corrupted existing installation as new install case.
      *install_type = Extension::NEW_INSTALL;
    } else {
      return true;
    }
  }

  // If anything fails after this, we want to delete the extension dir.
  ScopedTempDir scoped_version_dir;
  scoped_version_dir.Set(*version_dir);

  if (!MoveDirSafely(src_dir, *version_dir)) {
    *error = "Could not move extension directory into profile.";
    return false;
  }

  if (!SetCurrentVersion(dest_dir, extension_version, error))
    return false;

  scoped_version_dir.Take();
  return true;
}

Extension* LoadExtension(const FilePath& extension_path, bool require_key,
                         std::string* error) {
  FilePath manifest_path =
      extension_path.AppendASCII(Extension::kManifestFilename);
  if (!file_util::PathExists(manifest_path)) {
    *error = extension_manifest_errors::kInvalidManifest;
    return NULL;
  }

  JSONFileValueSerializer serializer(manifest_path);
  scoped_ptr<Value> root(serializer.Deserialize(error));
  if (!root.get())
    return NULL;

  if (!root->IsType(Value::TYPE_DICTIONARY)) {
    *error = extension_manifest_errors::kInvalidManifest;
    return NULL;
  }

  scoped_ptr<Extension> extension(new Extension(extension_path));
  if (!extension->InitFromValue(*static_cast<DictionaryValue*>(root.get()),
                                require_key, error))
    return NULL;

  // Validate icons exist.
  for (std::map<int, std::string>::const_iterator iter =
       extension->icons().begin(); iter != extension->icons().end(); ++iter) {
    if (!file_util::PathExists(extension->GetResourcePath(iter->second))) {
      *error = StringPrintf("Could not load extension icon '%s'.",
                            iter->second.c_str());
      return NULL;
    }
  }

  // Theme resource validation.
  if (extension->IsTheme()) {
    DictionaryValue* images_value = extension->GetThemeImages();
    if (images_value) {
      DictionaryValue::key_iterator iter = images_value->begin_keys();
      while (iter != images_value->end_keys()) {
        std::string val;
        if (images_value->GetString(*iter , &val)) {
          FilePath image_path = extension->path().AppendASCII(val);
          if (!file_util::PathExists(image_path)) {
            *error = StringPrintf(
                "Could not load '%s' for theme.",
                WideToUTF8(image_path.ToWStringHack()).c_str());
            return NULL;
          }
        }
        ++iter;
      }
    }

    // Themes cannot contain other extension types.
    return extension.release();
  }

  // Validate that claimed script resources actually exist.
  for (size_t i = 0; i < extension->content_scripts().size(); ++i) {
    const UserScript& script = extension->content_scripts()[i];

    for (size_t j = 0; j < script.js_scripts().size(); j++) {
      const FilePath& path = script.js_scripts()[j].path();
      if (!file_util::PathExists(path)) {
        *error = StringPrintf("Could not load '%s' for content script.",
                              WideToUTF8(path.ToWStringHack()).c_str());
        return NULL;
      }
    }

    for (size_t j = 0; j < script.css_scripts().size(); j++) {
      const FilePath& path = script.css_scripts()[j].path();
      if (!file_util::PathExists(path)) {
        *error = StringPrintf("Could not load '%s' for content script.",
                              WideToUTF8(path.ToWStringHack()).c_str());
        return NULL;
      }
    }
  }

  for (size_t i = 0; i < extension->plugins().size(); ++i) {
    const Extension::PluginInfo& plugin = extension->plugins()[i];
    if (!file_util::PathExists(plugin.path)) {
      *error = StringPrintf("Could not load '%s' for plugin.",
                            WideToUTF8(plugin.path.ToWStringHack()).c_str());
      return NULL;
    }
  }

  // Validate icon location for page actions.
  const PageActionMap& page_actions = extension->page_actions();
  for (PageActionMap::const_iterator i(page_actions.begin());
       i != page_actions.end(); ++i) {
    PageAction* page_action = i->second;
    const std::vector<FilePath>& icon_paths = page_action->icon_paths();
    for (std::vector<FilePath>::const_iterator iter = icon_paths.begin();
         iter != icon_paths.end(); ++iter) {
      FilePath path = *iter;
      if (!file_util::PathExists(path)) {
        *error = StringPrintf("Could not load icon '%s' for page action.",
                              WideToUTF8(path.ToWStringHack()).c_str());
        return NULL;
      }
    }
  }

  return extension.release();
}

void UninstallExtension(const std::string& id, const FilePath& extensions_dir) {
  // First, delete the Current Version file. If the directory delete fails, then
  // at least the extension won't be loaded again.
  FilePath extension_root = extensions_dir.AppendASCII(id);

  if (!file_util::PathExists(extension_root)) {
    LOG(WARNING) << "Asked to remove a non-existent extension " << id;
    return;
  }

  FilePath current_version_file = extension_root.AppendASCII(
      kCurrentVersionFileName);
  if (!file_util::PathExists(current_version_file)) {
    LOG(WARNING) << "Extension " << id
                 << " does not have a Current Version file.";
  } else {
    if (!file_util::Delete(current_version_file, false)) {
      LOG(WARNING) << "Could not delete Current Version file for extension "
                   << id;
      return;
    }
  }

  // OK, now try and delete the entire rest of the directory. One major place
  // this can fail is if the extension contains a plugin (stupid plugins). It's
  // not a big deal though, because we'll notice next time we startup that the
  // Current Version file is gone and finish the delete then.
  if (!file_util::Delete(extension_root, true))
    LOG(WARNING) << "Could not delete directory for extension " << id;
}

void GarbageCollectExtensions(const FilePath& install_directory) {
  // Nothing to clean up if it doesn't exist.
  if (!file_util::DirectoryExists(install_directory))
    return;

  LOG(INFO) << "Loading installed extensions...";
  file_util::FileEnumerator enumerator(install_directory,
                                       false,  // Not recursive.
                                       file_util::FileEnumerator::DIRECTORIES);
  FilePath extension_path;
  for (extension_path = enumerator.Next(); !extension_path.value().empty();
       extension_path = enumerator.Next()) {
    std::string extension_id = WideToASCII(
        extension_path.BaseName().ToWStringHack());

    // If there is no Current Version file, just delete the directory and move
    // on. This can legitimately happen when an uninstall does not complete, for
    // example, when a plugin is in use at uninstall time.
    FilePath current_version_path = extension_path.AppendASCII(
        kCurrentVersionFileName);
    if (!file_util::PathExists(current_version_path)) {
      LOG(INFO) << "Deleting incomplete install for directory "
                << WideToASCII(extension_path.ToWStringHack()) << ".";
      file_util::Delete(extension_path, true);  // Recursive.
      continue;
    }

    // Ignore directories that aren't valid IDs.
    if (!Extension::IdIsValid(extension_id)) {
      LOG(WARNING) << "Invalid extension ID encountered in extensions "
                      "directory: " << extension_id;
      LOG(INFO) << "Deleting invalid extension directory "
                << WideToASCII(extension_path.ToWStringHack()) << ".";
      file_util::Delete(extension_path, true);  // Recursive.
      continue;
    }
  }
}

}  // extensionfile_util
<|endoftext|>


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

#include "chrome/browser/options_window.h"

#include <gtk/gtk.h>

#include "app/l10n_util.h"
#include "base/message_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/gtk/options/advanced_page_gtk.h"
#include "chrome/browser/gtk/options/content_page_gtk.h"
#include "chrome/browser/gtk/options/general_page_gtk.h"
#include "chrome/browser/profile.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/pref_member.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/settings_page_view.h"
#endif

///////////////////////////////////////////////////////////////////////////////
// OptionsWindowGtk
//
// The contents of the Options dialog window.

class OptionsWindowGtk {
 public:
  explicit OptionsWindowGtk(Profile* profile);
  ~OptionsWindowGtk();

  // Shows the Tab corresponding to the specified OptionsPage.
  void ShowOptionsPage(OptionsPage page, OptionsGroup highlight_group);

 private:
  static void OnSwitchPage(GtkNotebook* notebook, GtkNotebookPage* page,
                           guint page_num, OptionsWindowGtk* window);

  static void OnWindowDestroy(GtkWidget* widget, OptionsWindowGtk* window);

  // The options dialog.
  GtkWidget* dialog_;

  // The container of the option pages.
  GtkWidget* notebook_;

  // The Profile associated with these options.
  Profile* profile_;

  // The general page.
  GeneralPageGtk general_page_;

  // The content page.
  ContentPageGtk content_page_;

  // The advanced (user data) page.
  AdvancedPageGtk advanced_page_;

  // The last page the user was on when they opened the Options window.
  IntegerPrefMember last_selected_page_;

  DISALLOW_COPY_AND_ASSIGN(OptionsWindowGtk);
};

// The singleton options window object.
static OptionsWindowGtk* options_window = NULL;

///////////////////////////////////////////////////////////////////////////////
// OptionsWindowGtk, public:

OptionsWindowGtk::OptionsWindowGtk(Profile* profile)
      // Always show preferences for the original profile. Most state when off
      // the record comes from the original profile, but we explicitly use
      // the original profile to avoid potential problems.
    : profile_(profile->GetOriginalProfile()),
      general_page_(profile_),
      content_page_(profile_),
      advanced_page_(profile_) {
  // We don't need to observe changes in this value.
  last_selected_page_.Init(prefs::kOptionsWindowLastTabIndex,
                           g_browser_process->local_state(), NULL);

  dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringFUTF8(IDS_OPTIONS_DIALOG_TITLE,
          WideToUTF16(l10n_util::GetString(IDS_PRODUCT_NAME))).c_str(),
      // Prefs window is shared between all browser windows.
      NULL,
      // Non-modal.
      GTK_DIALOG_NO_SEPARATOR,
      GTK_STOCK_CLOSE,
      GTK_RESPONSE_CLOSE,
      NULL);
  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
  // Allow browser windows to go in front of the options dialog in metacity.
  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
                      gtk_util::kContentAreaSpacing);

  notebook_ = gtk_notebook_new();

#if defined(OS_CHROMEOS)
  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      (new chromeos::SettingsPageView(profile_))->WrapInGtkWidget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_PRODUCT_OS_NAME).c_str()));
#endif

  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      general_page_.get_page_widget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_OPTIONS_GENERAL_TAB_LABEL).c_str()));

  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      content_page_.get_page_widget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_OPTIONS_CONTENT_TAB_LABEL).c_str()));

  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      advanced_page_.get_page_widget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_TAB_LABEL).c_str()));

  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);

  DCHECK_EQ(
      gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)), OPTIONS_PAGE_COUNT);

  // Need to show the notebook before connecting switch-page signal, otherwise
  // we'll immediately get a signal switching to page 0 and overwrite our
  // last_selected_page_ value.
  gtk_widget_show_all(dialog_);

  g_signal_connect(notebook_, "switch-page", G_CALLBACK(OnSwitchPage), this);

  // We only have one button and don't do any special handling, so just hook it
  // directly to gtk_widget_destroy.
  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);

  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
}

OptionsWindowGtk::~OptionsWindowGtk() {
}

void OptionsWindowGtk::ShowOptionsPage(OptionsPage page,
                                       OptionsGroup highlight_group) {
  // Bring options window to front if it already existed and isn't already
  // in front
  gtk_window_present_with_time(GTK_WINDOW(dialog_),
                               gtk_get_current_event_time());

  if (page == OPTIONS_PAGE_DEFAULT) {
    // Remember the last visited page from local state.
    page = static_cast<OptionsPage>(last_selected_page_.GetValue());
    if (page == OPTIONS_PAGE_DEFAULT)
      page = OPTIONS_PAGE_GENERAL;
  }
  // If the page number is out of bounds, reset to the first tab.
  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
    page = OPTIONS_PAGE_GENERAL;

  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page);

  // TODO(mattm): set highlight_group
}

///////////////////////////////////////////////////////////////////////////////
// OptionsWindowGtk, private:

// static
void OptionsWindowGtk::OnSwitchPage(GtkNotebook* notebook,
                                    GtkNotebookPage* page,
                                    guint page_num,
                                    OptionsWindowGtk* window) {
  int index = page_num;
  DCHECK(index > OPTIONS_PAGE_DEFAULT && index < OPTIONS_PAGE_COUNT);
  window->last_selected_page_.SetValue(index);
}

// static
void OptionsWindowGtk::OnWindowDestroy(GtkWidget* widget,
                                       OptionsWindowGtk* window) {
  options_window = NULL;
  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
}

///////////////////////////////////////////////////////////////////////////////
// Factory/finder method:

void ShowOptionsWindow(OptionsPage page,
                       OptionsGroup highlight_group,
                       Profile* profile) {
  DCHECK(profile);
  // If there's already an existing options window, activate it and switch to
  // the specified page.
  if (!options_window) {
    options_window = new OptionsWindowGtk(profile);
  }
  options_window->ShowOptionsPage(page, highlight_group);
}
<commit_msg>Fix GTK version of options dialog to place it to the center of last active browser window.<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/options_window.h"

#include <gtk/gtk.h>

#include "app/l10n_util.h"
#include "base/message_loop.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/gtk/options/advanced_page_gtk.h"
#include "chrome/browser/gtk/options/content_page_gtk.h"
#include "chrome/browser/gtk/options/general_page_gtk.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/pref_member.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/settings_page_view.h"
#endif

///////////////////////////////////////////////////////////////////////////////
// OptionsWindowGtk
//
// The contents of the Options dialog window.

class OptionsWindowGtk {
 public:
  explicit OptionsWindowGtk(Profile* profile);
  ~OptionsWindowGtk();

  // Shows the Tab corresponding to the specified OptionsPage.
  void ShowOptionsPage(OptionsPage page, OptionsGroup highlight_group);

 private:
  static void OnSwitchPage(GtkNotebook* notebook, GtkNotebookPage* page,
                           guint page_num, OptionsWindowGtk* window);

  static void OnWindowDestroy(GtkWidget* widget, OptionsWindowGtk* window);

  // The options dialog.
  GtkWidget* dialog_;

  // The container of the option pages.
  GtkWidget* notebook_;

  // The Profile associated with these options.
  Profile* profile_;

  // The general page.
  GeneralPageGtk general_page_;

  // The content page.
  ContentPageGtk content_page_;

  // The advanced (user data) page.
  AdvancedPageGtk advanced_page_;

  // The last page the user was on when they opened the Options window.
  IntegerPrefMember last_selected_page_;

  DISALLOW_COPY_AND_ASSIGN(OptionsWindowGtk);
};

// The singleton options window object.
static OptionsWindowGtk* options_window = NULL;

///////////////////////////////////////////////////////////////////////////////
// OptionsWindowGtk, public:

OptionsWindowGtk::OptionsWindowGtk(Profile* profile)
      // Always show preferences for the original profile. Most state when off
      // the record comes from the original profile, but we explicitly use
      // the original profile to avoid potential problems.
    : profile_(profile->GetOriginalProfile()),
      general_page_(profile_),
      content_page_(profile_),
      advanced_page_(profile_) {
  // We don't need to observe changes in this value.
  last_selected_page_.Init(prefs::kOptionsWindowLastTabIndex,
                           g_browser_process->local_state(), NULL);

  dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringFUTF8(IDS_OPTIONS_DIALOG_TITLE,
          WideToUTF16(l10n_util::GetString(IDS_PRODUCT_NAME))).c_str(),
      // Prefs window is shared between all browser windows.
      NULL,
      // Non-modal.
      GTK_DIALOG_NO_SEPARATOR,
      GTK_STOCK_CLOSE,
      GTK_RESPONSE_CLOSE,
      NULL);
  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
  // Allow browser windows to go in front of the options dialog in metacity.
  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
                      gtk_util::kContentAreaSpacing);

  notebook_ = gtk_notebook_new();

#if defined(OS_CHROMEOS)
  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      (new chromeos::SettingsPageView(profile_))->WrapInGtkWidget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_PRODUCT_OS_NAME).c_str()));
#endif

  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      general_page_.get_page_widget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_OPTIONS_GENERAL_TAB_LABEL).c_str()));

  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      content_page_.get_page_widget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_OPTIONS_CONTENT_TAB_LABEL).c_str()));

  gtk_notebook_append_page(
      GTK_NOTEBOOK(notebook_),
      advanced_page_.get_page_widget(),
      gtk_label_new(
          l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_TAB_LABEL).c_str()));

  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);

  DCHECK_EQ(
      gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)), OPTIONS_PAGE_COUNT);

  if (Browser* b = BrowserList::GetLastActive()) {
    // Set temporary transient parent to align the windows before showing it.
    // gtk_widget_show_all below shows options dialog before ShowOptionsPage
    // is able to move the window to desired position. Therefor without
    // gtk_window_set_transient_for(), the window initially appears at 0,0
    // and then moves to the center. This trick eliminates blinking.
    gtk_window_set_transient_for(GTK_WINDOW(dialog_),
                                 b->window()->GetNativeHandle());
    gtk_window_set_position(GTK_WINDOW(dialog_), GTK_WIN_POS_CENTER_ON_PARENT);
  }

  // Need to show the notebook before connecting switch-page signal, otherwise
  // we'll immediately get a signal switching to page 0 and overwrite our
  // last_selected_page_ value.
  gtk_widget_show_all(dialog_);

  g_signal_connect(notebook_, "switch-page", G_CALLBACK(OnSwitchPage), this);

  // We only have one button and don't do any special handling, so just hook it
  // directly to gtk_widget_destroy.
  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);

  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
}

OptionsWindowGtk::~OptionsWindowGtk() {
}

static gfx::Rect GetWindowBounds(GtkWindow* window) {
  gint x, y, width, height;
  gtk_window_get_position(window, &x, &y);
  gtk_window_get_size(window, &width, &height);
  return gfx::Rect(x, y, width, height);
}

static gfx::Size GetWindowSize(GtkWindow* window) {
  gint width, height;
  gtk_window_get_size(window, &width, &height);
  return gfx::Size(width, height);
}

void OptionsWindowGtk::ShowOptionsPage(OptionsPage page,
                                       OptionsGroup highlight_group) {
  // Remove transient parent to detach window since it doesn't belong to
  // any particular browser instance.
  gtk_window_set_transient_for(GTK_WINDOW(dialog_), NULL);
  if (Browser* b = BrowserList::GetLastActive()) {
    // Move dialog to user expected position.
    gfx::Rect frame_bounds = GetWindowBounds(b->window()->GetNativeHandle());
    gfx::Point origin = frame_bounds.origin();
    gfx::Size size = GetWindowSize(GTK_WINDOW(dialog_));
    origin.Offset(
        (frame_bounds.width() - size.width()) / 2,
        (frame_bounds.height() - size.height()) / 2);
    gtk_window_move(GTK_WINDOW(dialog_), origin.x(), origin.y());
  }

  // Bring options window to front if it already existed and isn't already
  // in front
  gtk_window_present_with_time(GTK_WINDOW(dialog_),
                               gtk_get_current_event_time());

  if (page == OPTIONS_PAGE_DEFAULT) {
    // Remember the last visited page from local state.
    page = static_cast<OptionsPage>(last_selected_page_.GetValue());
    if (page == OPTIONS_PAGE_DEFAULT)
      page = OPTIONS_PAGE_GENERAL;
  }
  // If the page number is out of bounds, reset to the first tab.
  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
    page = OPTIONS_PAGE_GENERAL;

  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page);

  // TODO(mattm): set highlight_group
}

///////////////////////////////////////////////////////////////////////////////
// OptionsWindowGtk, private:

// static
void OptionsWindowGtk::OnSwitchPage(GtkNotebook* notebook,
                                    GtkNotebookPage* page,
                                    guint page_num,
                                    OptionsWindowGtk* window) {
  int index = page_num;
  DCHECK(index > OPTIONS_PAGE_DEFAULT && index < OPTIONS_PAGE_COUNT);
  window->last_selected_page_.SetValue(index);
}

// static
void OptionsWindowGtk::OnWindowDestroy(GtkWidget* widget,
                                       OptionsWindowGtk* window) {
  options_window = NULL;
  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
}

///////////////////////////////////////////////////////////////////////////////
// Factory/finder method:

void ShowOptionsWindow(OptionsPage page,
                       OptionsGroup highlight_group,
                       Profile* profile) {
  DCHECK(profile);
  // If there's already an existing options window, activate it and switch to
  // the specified page.
  if (!options_window) {
    options_window = new OptionsWindowGtk(profile);
  }
  options_window->ShowOptionsPage(page, highlight_group);
}
<|endoftext|>


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

#include "chrome/browser/tab_contents/web_drag_dest_gtk.h"

#include "app/gtk_dnd_util.h"
#include "base/file_path.h"
#include "base/string_util.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/gtk_util.h"
#include "net/base/net_util.h"

using WebKit::WebDragOperation;
using WebKit::WebDragOperationCopy;
using WebKit::WebDragOperationNone;

WebDragDestGtk::WebDragDestGtk(TabContents* tab_contents, GtkWidget* widget)
    : tab_contents_(tab_contents),
      widget_(widget),
      context_(NULL),
      method_factory_(this) {
  gtk_drag_dest_set(widget, static_cast<GtkDestDefaults>(0),
                    NULL, 0, GDK_ACTION_COPY);
  g_signal_connect(widget, "drag-motion",
                   G_CALLBACK(OnDragMotionThunk), this);
  g_signal_connect(widget, "drag-leave",
                   G_CALLBACK(OnDragLeaveThunk), this);
  g_signal_connect(widget, "drag-drop",
                   G_CALLBACK(OnDragDropThunk), this);
  g_signal_connect(widget, "drag-data-received",
                   G_CALLBACK(OnDragDataReceivedThunk), this);

  destroy_handler_ = g_signal_connect(
      widget, "destroy", G_CALLBACK(gtk_widget_destroyed), &widget_);
}

WebDragDestGtk::~WebDragDestGtk() {
  if (widget_) {
    gtk_drag_dest_unset(widget_);
    g_signal_handler_disconnect(widget_, destroy_handler_);
  }
}

void WebDragDestGtk::UpdateDragStatus(WebDragOperation operation) {
  if (context_) {
    // TODO(estade): we might want to support other actions besides copy,
    // but that would increase the cost of getting our drag success guess
    // wrong.
    is_drop_target_ = operation != WebDragOperationNone;
    // TODO(snej): Pass appropriate GDK action instead of hardcoding COPY
    gdk_drag_status(context_, is_drop_target_ ? GDK_ACTION_COPY :
                    static_cast<GdkDragAction>(0),
                    drag_over_time_);
  }
}

void WebDragDestGtk::DragLeave() {
  tab_contents_->render_view_host()->DragTargetDragLeave();
}

gboolean WebDragDestGtk::OnDragMotion(GdkDragContext* context, gint x, gint y,
                                      guint time) {
  if (context_ != context) {
    context_ = context;
    drop_data_.reset(new WebDropData);
    is_drop_target_ = false;

    static int supported_targets[] = {
      GtkDndUtil::TEXT_PLAIN,
      GtkDndUtil::TEXT_URI_LIST,
      GtkDndUtil::TEXT_HTML,
      // TODO(estade): support image drags?
    };

    data_requests_ = arraysize(supported_targets);
    for (size_t i = 0; i < arraysize(supported_targets); ++i) {
      gtk_drag_get_data(widget_, context,
                        GtkDndUtil::GetAtomForTarget(supported_targets[i]),
                        time);
    }
  } else if (data_requests_ == 0) {
    tab_contents_->render_view_host()->
        DragTargetDragOver(gtk_util::ClientPoint(widget_),
                           gtk_util::ScreenPoint(widget_),
                           WebDragOperationCopy);
    // TODO(snej): Pass appropriate DragOperation instead of hardcoding
    drag_over_time_ = time;
  }

  // Pretend we are a drag destination because we don't want to wait for
  // the renderer to tell us if we really are or not.
  return TRUE;
}

void WebDragDestGtk::OnDragDataReceived(
    GdkDragContext* context, gint x, gint y, GtkSelectionData* data,
    guint info, guint time) {
  // We might get the data from an old get_data() request that we no longer
  // care about.
  if (context != context_)
    return;

  data_requests_--;

  // Decode the data.
  if (data->data) {
    // If the source can't provide us with valid data for a requested target,
    // data->data will be NULL.
    if (data->target ==
        GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_PLAIN)) {
      guchar* text = gtk_selection_data_get_text(data);
      if (text) {
        drop_data_->plain_text =
            UTF8ToUTF16(std::string(reinterpret_cast<char*>(text),
                                    data->length));
        g_free(text);
      }
    } else if (data->target ==
               GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_URI_LIST)) {
      gchar** uris = gtk_selection_data_get_uris(data);
      if (uris) {
        for (gchar** uri_iter = uris; *uri_iter; uri_iter++) {
          // TODO(estade): Can the filenames have a non-UTF8 encoding?
          FilePath file_path;
          if (net::FileURLToFilePath(GURL(*uri_iter), &file_path))
            drop_data_->filenames.push_back(UTF8ToUTF16(file_path.value()));
        }
        // Also, write the first URI as the URL.
        if (uris[0])
          drop_data_->url = GURL(uris[0]);
        g_strfreev(uris);
      }
    } else if (data->target ==
               GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_HTML)) {
      // TODO(estade): Can the html have a non-UTF8 encoding?
      drop_data_->text_html =
          UTF8ToUTF16(std::string(reinterpret_cast<char*>(data->data),
                                  data->length));
      // We leave the base URL empty.
    }
  }

  if (data_requests_ == 0) {
    // Tell the renderer about the drag.
    // |x| and |y| are seemingly arbitrary at this point.
    tab_contents_->render_view_host()->
        DragTargetDragEnter(*drop_data_.get(),
                            gtk_util::ClientPoint(widget_),
                            gtk_util::ScreenPoint(widget_),
                            WebDragOperationCopy);
    // TODO(snej): Pass appropriate DragOperation instead of hardcoding
    drag_over_time_ = time;
  }
}

// The drag has left our widget; forward this information to the renderer.
void WebDragDestGtk::OnDragLeave(GdkDragContext* context, guint time) {
  // Set |context_| to NULL to make sure we will recognize the next DragMotion
  // as an enter.
  context_ = NULL;
  drop_data_.reset();
  // When GTK sends us a drag-drop signal, it is shortly (and synchronously)
  // preceded by a drag-leave. The renderer doesn't like getting the signals
  // in this order so delay telling it about the drag-leave till we are sure
  // we are not getting a drop as well.
  MessageLoop::current()->PostTask(FROM_HERE,
      method_factory_.NewRunnableMethod(&WebDragDestGtk::DragLeave));
}

// Called by GTK when the user releases the mouse, executing a drop.
gboolean WebDragDestGtk::OnDragDrop(GdkDragContext* context, gint x, gint y,
                                    guint time) {
  // Cancel that drag leave!
  method_factory_.RevokeAll();

  tab_contents_->render_view_host()->
      DragTargetDrop(gtk_util::ClientPoint(widget_),
                     gtk_util::ScreenPoint(widget_));

  // The second parameter is just an educated guess, but at least we will
  // get the drag-end animation right sometimes.
  gtk_drag_finish(context, is_drop_target_, FALSE, time);
  return TRUE;
}
<commit_msg>Linux: tell webkit to permit WebDragOperationMove drags.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/tab_contents/web_drag_dest_gtk.h"

#include "app/gtk_dnd_util.h"
#include "base/file_path.h"
#include "base/string_util.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/gtk_util.h"
#include "net/base/net_util.h"

using WebKit::WebDragOperation;
using WebKit::WebDragOperationCopy;
using WebKit::WebDragOperationMove;
using WebKit::WebDragOperationNone;

WebDragDestGtk::WebDragDestGtk(TabContents* tab_contents, GtkWidget* widget)
    : tab_contents_(tab_contents),
      widget_(widget),
      context_(NULL),
      method_factory_(this) {
  gtk_drag_dest_set(widget, static_cast<GtkDestDefaults>(0),
                    NULL, 0, GDK_ACTION_COPY);
  g_signal_connect(widget, "drag-motion",
                   G_CALLBACK(OnDragMotionThunk), this);
  g_signal_connect(widget, "drag-leave",
                   G_CALLBACK(OnDragLeaveThunk), this);
  g_signal_connect(widget, "drag-drop",
                   G_CALLBACK(OnDragDropThunk), this);
  g_signal_connect(widget, "drag-data-received",
                   G_CALLBACK(OnDragDataReceivedThunk), this);

  destroy_handler_ = g_signal_connect(
      widget, "destroy", G_CALLBACK(gtk_widget_destroyed), &widget_);
}

WebDragDestGtk::~WebDragDestGtk() {
  if (widget_) {
    gtk_drag_dest_unset(widget_);
    g_signal_handler_disconnect(widget_, destroy_handler_);
  }
}

void WebDragDestGtk::UpdateDragStatus(WebDragOperation operation) {
  if (context_) {
    // TODO(estade): we might want to support other actions besides copy,
    // but that would increase the cost of getting our drag success guess
    // wrong.
    is_drop_target_ = operation != WebDragOperationNone;
    gdk_drag_status(context_, is_drop_target_ ? GDK_ACTION_COPY :
                    static_cast<GdkDragAction>(0),
                    drag_over_time_);
  }
}

void WebDragDestGtk::DragLeave() {
  tab_contents_->render_view_host()->DragTargetDragLeave();
}

gboolean WebDragDestGtk::OnDragMotion(GdkDragContext* context, gint x, gint y,
                                      guint time) {
  if (context_ != context) {
    context_ = context;
    drop_data_.reset(new WebDropData);
    is_drop_target_ = false;

    static int supported_targets[] = {
      GtkDndUtil::TEXT_PLAIN,
      GtkDndUtil::TEXT_URI_LIST,
      GtkDndUtil::TEXT_HTML,
      // TODO(estade): support image drags?
    };

    data_requests_ = arraysize(supported_targets);
    for (size_t i = 0; i < arraysize(supported_targets); ++i) {
      gtk_drag_get_data(widget_, context,
                        GtkDndUtil::GetAtomForTarget(supported_targets[i]),
                        time);
    }
  } else if (data_requests_ == 0) {
    tab_contents_->render_view_host()->
        DragTargetDragOver(gtk_util::ClientPoint(widget_),
                           gtk_util::ScreenPoint(widget_),
                           static_cast<WebDragOperation>(
                               WebDragOperationCopy | WebDragOperationMove));
    // TODO(snej): Pass appropriate DragOperation instead of hardcoding
    drag_over_time_ = time;
  }

  // Pretend we are a drag destination because we don't want to wait for
  // the renderer to tell us if we really are or not.
  return TRUE;
}

void WebDragDestGtk::OnDragDataReceived(
    GdkDragContext* context, gint x, gint y, GtkSelectionData* data,
    guint info, guint time) {
  // We might get the data from an old get_data() request that we no longer
  // care about.
  if (context != context_)
    return;

  data_requests_--;

  // Decode the data.
  if (data->data) {
    // If the source can't provide us with valid data for a requested target,
    // data->data will be NULL.
    if (data->target ==
        GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_PLAIN)) {
      guchar* text = gtk_selection_data_get_text(data);
      if (text) {
        drop_data_->plain_text =
            UTF8ToUTF16(std::string(reinterpret_cast<char*>(text),
                                    data->length));
        g_free(text);
      }
    } else if (data->target ==
               GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_URI_LIST)) {
      gchar** uris = gtk_selection_data_get_uris(data);
      if (uris) {
        for (gchar** uri_iter = uris; *uri_iter; uri_iter++) {
          // TODO(estade): Can the filenames have a non-UTF8 encoding?
          FilePath file_path;
          if (net::FileURLToFilePath(GURL(*uri_iter), &file_path))
            drop_data_->filenames.push_back(UTF8ToUTF16(file_path.value()));
        }
        // Also, write the first URI as the URL.
        if (uris[0])
          drop_data_->url = GURL(uris[0]);
        g_strfreev(uris);
      }
    } else if (data->target ==
               GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_HTML)) {
      // TODO(estade): Can the html have a non-UTF8 encoding?
      drop_data_->text_html =
          UTF8ToUTF16(std::string(reinterpret_cast<char*>(data->data),
                                  data->length));
      // We leave the base URL empty.
    }
  }

  if (data_requests_ == 0) {
    // Tell the renderer about the drag.
    // |x| and |y| are seemingly arbitrary at this point.
    tab_contents_->render_view_host()->
        DragTargetDragEnter(*drop_data_.get(),
                            gtk_util::ClientPoint(widget_),
                            gtk_util::ScreenPoint(widget_),
                            static_cast<WebDragOperation>(
                                WebDragOperationCopy | WebDragOperationMove));
    // TODO(snej): Pass appropriate DragOperation instead of hardcoding
    drag_over_time_ = time;
  }
}

// The drag has left our widget; forward this information to the renderer.
void WebDragDestGtk::OnDragLeave(GdkDragContext* context, guint time) {
  // Set |context_| to NULL to make sure we will recognize the next DragMotion
  // as an enter.
  context_ = NULL;
  drop_data_.reset();
  // When GTK sends us a drag-drop signal, it is shortly (and synchronously)
  // preceded by a drag-leave. The renderer doesn't like getting the signals
  // in this order so delay telling it about the drag-leave till we are sure
  // we are not getting a drop as well.
  MessageLoop::current()->PostTask(FROM_HERE,
      method_factory_.NewRunnableMethod(&WebDragDestGtk::DragLeave));
}

// Called by GTK when the user releases the mouse, executing a drop.
gboolean WebDragDestGtk::OnDragDrop(GdkDragContext* context, gint x, gint y,
                                    guint time) {
  // Cancel that drag leave!
  method_factory_.RevokeAll();

  tab_contents_->render_view_host()->
      DragTargetDrop(gtk_util::ClientPoint(widget_),
                     gtk_util::ScreenPoint(widget_));

  // The second parameter is just an educated guess, but at least we will
  // get the drag-end animation right sometimes.
  gtk_drag_finish(context, is_drop_target_, FALSE, time);
  return TRUE;
}
<|endoftext|>


<commit_before><commit_msg>cppcheck reduce scope of var in registry/...regimpl.cxx<commit_after><|endoftext|>


<commit_before>/***********************************************************************
    filename:   TreeView.cpp
    created:    Fri Jun 06 2014
    author:     Timotei Dolean <timotei21@gmail.com>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/WindowRendererSets/Core/TreeView.h"
#include "CEGUI/falagard/WidgetLookManager.h"
#include "CEGUI/falagard/WidgetLookFeel.h"
#include "CEGUI/Image.h"

namespace CEGUI
{

//----------------------------------------------------------------------------//
const String FalagardTreeView::TypeName("Core/TreeView");

//----------------------------------------------------------------------------//
FalagardTreeView::FalagardTreeView(const String& type) :
    TreeViewWindowRenderer(type),
    d_subtreeExpanderImagery(0),
    d_subtreeCollapserImagery(0),
    d_subtreeExpanderImagerySize(0, 0)
{
}

//----------------------------------------------------------------------------//
void FalagardTreeView::render()
{
    const WidgetLookFeel& wlf = getLookNFeel();
    TreeView* tree_view = static_cast<TreeView*>(d_window);

    tree_view->prepareForRender();

    const StateImagery* imagery = &wlf.getStateImagery(
        tree_view->isEffectiveDisabled() ? "Disabled" : "Enabled");
    imagery->render(*tree_view);

    Rectf items_area(getViewRenderArea());
    Vector2f item_pos(getItemRenderStartPosition(tree_view, items_area));
    renderTreeItem(tree_view, items_area, item_pos, tree_view->getRootItemState());
}

//----------------------------------------------------------------------------//
void FalagardTreeView::renderTreeItem(TreeView* tree_view, const Rectf& items_area,
    Vector2f& item_pos, const TreeViewItemRenderingState& item_to_render)
{
    const float SUBTREE_IDENT = d_subtreeExpanderImagerySize.d_width;
    const float OPEN_CLOSE_BUTTON_MARGIN = 5.0f;
    for (size_t i = 0; i < item_to_render.d_renderedChildren.size(); ++i)
    {
        TreeViewItemRenderingState item = item_to_render.d_renderedChildren.at(i);
        RenderedString& rendered_string = item.d_string;
        Sizef size(item.d_size);

        size.d_width = ceguimax(items_area.getWidth(), size.d_width);
        if (item.d_totalChildCount > 0)
        {
            const ImagerySection* section = item.d_subtreeIsExpanded
                ? d_subtreeExpanderImagery : d_subtreeCollapserImagery;

            Rectf button_rect;
            button_rect.left(item_pos.d_x + OPEN_CLOSE_BUTTON_MARGIN);
            button_rect.top(item_pos.d_y + OPEN_CLOSE_BUTTON_MARGIN);
            button_rect.setSize(d_subtreeExpanderImagerySize);

            Rectf button_clipper(button_rect.getIntersection(items_area));
            section->render(*tree_view, button_rect, 0, &button_clipper);
        }

        Rectf item_rect;
        item_rect.left(item_pos.d_x + d_subtreeExpanderImagerySize.d_width + 2 * OPEN_CLOSE_BUTTON_MARGIN);
        item_rect.top(item_pos.d_y);
        item_rect.setSize(size);

        Rectf item_clipper(item_rect.getIntersection(items_area));
        renderString(tree_view, rendered_string, item_rect,
            tree_view->getFont(), &item_clipper, item.d_isSelected);

        item_pos.d_y += size.d_height;

        if (item.d_renderedChildren.empty())
            continue;

        item_pos.d_x += SUBTREE_IDENT;

        if (item.d_subtreeIsExpanded)
        {
            renderTreeItem(tree_view, items_area, item_pos, item);
        }

        item_pos.d_x -= SUBTREE_IDENT;
    }
}

static Sizef getImagerySize(const ImagerySection* section)
{
    ImageryComponent& component = section->getImageryComponentIterator().getCurrentValue();
    const Image* img = component.getImage();
    return img->getRenderedSize();
}

//----------------------------------------------------------------------------//
void FalagardTreeView::onLookNFeelAssigned()
{
    const WidgetLookFeel& wlf = getLookNFeel();
    d_subtreeExpanderImagery = &wlf.getImagerySection("SubtreeExpander");
    d_subtreeCollapserImagery = &wlf.getImagerySection("SubtreeCollapser");

    Sizef open_size = getImagerySize(d_subtreeExpanderImagery);
    Sizef close_size = getImagerySize(d_subtreeCollapserImagery);
    d_subtreeExpanderImagerySize = Sizef(
        ceguimax(open_size.d_width, close_size.d_width),
        ceguimax(open_size.d_height, close_size.d_height));

}

//----------------------------------------------------------------------------//
Sizef FalagardTreeView::getSubtreeExpanderSize(void) const
{
    return d_subtreeExpanderImagerySize;
}

//----------------------------------------------------------------------------//
Rectf FalagardTreeView::getViewRenderArea(void) const
{
    return ItemViewRenderer::getViewRenderArea(this);
}
}
<commit_msg>Fix compilation on MinGW<commit_after>/***********************************************************************
    filename:   TreeView.cpp
    created:    Fri Jun 06 2014
    author:     Timotei Dolean <timotei21@gmail.com>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/WindowRendererSets/Core/TreeView.h"
#include "CEGUI/falagard/WidgetLookManager.h"
#include "CEGUI/falagard/WidgetLookFeel.h"
#include "CEGUI/Image.h"

namespace CEGUI
{

//----------------------------------------------------------------------------//
const String FalagardTreeView::TypeName("Core/TreeView");

//----------------------------------------------------------------------------//
FalagardTreeView::FalagardTreeView(const String& type) :
    TreeViewWindowRenderer(type),
    d_subtreeExpanderImagery(0),
    d_subtreeCollapserImagery(0),
    d_subtreeExpanderImagerySize(0, 0)
{
}

//----------------------------------------------------------------------------//
void FalagardTreeView::render()
{
    const WidgetLookFeel& wlf = getLookNFeel();
    TreeView* tree_view = static_cast<TreeView*>(d_window);

    tree_view->prepareForRender();

    const StateImagery* imagery = &wlf.getStateImagery(
        tree_view->isEffectiveDisabled() ? "Disabled" : "Enabled");
    imagery->render(*tree_view);

    Rectf items_area(getViewRenderArea());
    Vector2f item_pos(getItemRenderStartPosition(tree_view, items_area));
    renderTreeItem(tree_view, items_area, item_pos, tree_view->getRootItemState());
}

//----------------------------------------------------------------------------//
void FalagardTreeView::renderTreeItem(TreeView* tree_view, const Rectf& items_area,
    Vector2f& item_pos, const TreeViewItemRenderingState& item_to_render)
{
    const float SUBTREE_IDENT = d_subtreeExpanderImagerySize.d_width;
    const float OPEN_CLOSE_BUTTON_MARGIN = 5.0f;
    for (size_t i = 0; i < item_to_render.d_renderedChildren.size(); ++i)
    {
        TreeViewItemRenderingState item = item_to_render.d_renderedChildren.at(i);
        RenderedString& rendered_string = item.d_string;
        Sizef size(item.d_size);

        size.d_width = ceguimax(items_area.getWidth(), size.d_width);
        if (item.d_totalChildCount > 0)
        {
            const ImagerySection* section = item.d_subtreeIsExpanded
                ? d_subtreeExpanderImagery : d_subtreeCollapserImagery;

            Rectf button_rect;
            button_rect.left(item_pos.d_x + OPEN_CLOSE_BUTTON_MARGIN);
            button_rect.top(item_pos.d_y + OPEN_CLOSE_BUTTON_MARGIN);
            button_rect.setSize(d_subtreeExpanderImagerySize);

            Rectf button_clipper(button_rect.getIntersection(items_area));
            section->render(*tree_view, button_rect, 0, &button_clipper);
        }

        Rectf item_rect;
        item_rect.left(item_pos.d_x + d_subtreeExpanderImagerySize.d_width + 2 * OPEN_CLOSE_BUTTON_MARGIN);
        item_rect.top(item_pos.d_y);
        item_rect.setSize(size);

        Rectf item_clipper(item_rect.getIntersection(items_area));
        renderString(tree_view, rendered_string, item_rect,
            tree_view->getFont(), &item_clipper, item.d_isSelected);

        item_pos.d_y += size.d_height;

        if (item.d_renderedChildren.empty())
            continue;

        item_pos.d_x += SUBTREE_IDENT;

        if (item.d_subtreeIsExpanded)
        {
            renderTreeItem(tree_view, items_area, item_pos, item);
        }

        item_pos.d_x -= SUBTREE_IDENT;
    }
}

static Sizef getImagerySize(const ImagerySection* section)
{
    const ImageryComponent& component = section->getImageryComponentIterator().getCurrentValue();
    const Image* img = component.getImage();
    return img->getRenderedSize();
}

//----------------------------------------------------------------------------//
void FalagardTreeView::onLookNFeelAssigned()
{
    const WidgetLookFeel& wlf = getLookNFeel();
    d_subtreeExpanderImagery = &wlf.getImagerySection("SubtreeExpander");
    d_subtreeCollapserImagery = &wlf.getImagerySection("SubtreeCollapser");

    Sizef open_size = getImagerySize(d_subtreeExpanderImagery);
    Sizef close_size = getImagerySize(d_subtreeCollapserImagery);
    d_subtreeExpanderImagerySize = Sizef(
        ceguimax(open_size.d_width, close_size.d_width),
        ceguimax(open_size.d_height, close_size.d_height));

}

//----------------------------------------------------------------------------//
Sizef FalagardTreeView::getSubtreeExpanderSize(void) const
{
    return d_subtreeExpanderImagerySize;
}

//----------------------------------------------------------------------------//
Rectf FalagardTreeView::getViewRenderArea(void) const
{
    return ItemViewRenderer::getViewRenderArea(this);
}
}
<|endoftext|>


<commit_before>/* Autogenerated with kurento-module-creator */

#include "TelmateFrameGrabberOpenCVImpl.hpp"
#include <gst/gst.h>
#include <KurentoException.hpp>
#include <vector>
#include <string>

#define GST_CAT_DEFAULT kurento_telmate_frame_grabber_opencv_impl
GST_DEBUG_CATEGORY_STATIC(GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoTelmateFrameGrabberOpenCVImpl"

namespace kurento {

TelmateFrameGrabberOpenCVImpl::TelmateFrameGrabberOpenCVImpl() {

    GST_DEBUG_CATEGORY_INIT(GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                            GST_DEFAULT_NAME);

    this->thrLoop = true;
    this->snapInterval = 1000;
    this->epName = "EP_NAME_UNINITIALIZED";
    this->storagePath = "/tmp/";
    this->prevStoragePath = this->storagePath;
    this->framesCounter = 0;
    this->outputFormat = FGFMT_JPEG;
    this->lastQueueTimeStamp = 0;
    this->queueLength = 0;
    this->frameQueue = new avis_blocking_queue<VideoFrame*>;

    this->thr = new boost::thread(boost::bind(
            &TelmateFrameGrabberOpenCVImpl::queueHandler, this));
    this->thr->detach();

    GST_INFO("Constructor was called for %s", this->epName.c_str());
}

TelmateFrameGrabberOpenCVImpl::~TelmateFrameGrabberOpenCVImpl() {

    GST_INFO("Destructor was called for %s", this->epName.c_str());

}

void TelmateFrameGrabberOpenCVImpl::cleanup() {

    VideoFrame *ptrVf;

    while(!this->frameQueue->empty()) {
        this->frameQueue->pop(ptrVf); // blocks
        --this->queueLength;
        delete ptrVf;
        ptrVf = NULL;

    }

    this->thrLoop = false;
    boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); /* Give the processing thread some time to exit() */
    GST_INFO("Called release() for %s :: Dequeue completed.", this->epName.c_str());

    delete this->frameQueue;
    this->frameQueue = NULL;

    return;
}

/*
 * This function will be called with each new frame. mat variable
 * contains the current frame. You should insert your image processing code
 * here. Any changes in mat, will be sent through the Media Pipeline.
 */
void TelmateFrameGrabberOpenCVImpl::process(cv::Mat &mat) {
        if ((this->getCurrentTimestampLong() - this->lastQueueTimeStamp) >= this->snapInterval) {

            if(this->thrLoop) { // do not push into the queue if the destructor was called.
                this->lastQueueTimeStamp = this->getCurrentTimestampLong();
                VideoFrame *ptrVf = new VideoFrame();
                ptrVf->mat = mat.clone();
                ptrVf->ts = std::to_string(this->lastQueueTimeStamp);

                this->frameQueue->push(ptrVf);
                ++this->queueLength;
                ++this->framesCounter;
            }
        }
}
/*
 * This function is executed inside the queueHandler thread as a main() function.
 * It pops a VideoFrame from the framequeue and saves it to disk.
 * a boost scoped_lock is implemented to ensure the queue is emptied to disk before
 * the destructor is executed. a 1 second sleep is implemented inside the while() loop
 * to ensure the cpu isn't exhausted while the queue is empty.
 */
void TelmateFrameGrabberOpenCVImpl::queueHandler() {
        VideoFrame *ptrVf;
        cv::Mat image;
        std::vector<int> params;
        std::string image_extension;

        while (this->thrLoop) {

            this->frameQueue->pop(ptrVf); // blocks
            params.clear();     // clear the vector since the last iteration.
            this->lastQueueTimeStamp = this->getCurrentTimestampLong();
            --this->queueLength;

            switch (this->outputFormat) {
                case FGFMT_JPEG:
                    /* Set jpeg params */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
                case FGFMT_PNG:
                    /* Set PNG parameters, compression etc. */
                    params.push_back(CV_IMWRITE_PNG_COMPRESSION);
                    params.push_back(FG_PNG_QUALITY);
                    image_extension = ".png";
                    break;
                default:
                    /* Defaults to jpeg */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
            }

            std::string filename =
                    std::to_string((long) this->framesCounter) + "_" + ptrVf->ts + image_extension;

            if (this->storagePathSubdir.empty() || !this->storagePath.compare(this->prevStoragePath)) {

                GST_INFO("Storage path has changed. old storage path: %s. new storage path: %s",this->prevStoragePath.c_str(), this->storagePathSubdir.c_str());
                this->prevStoragePath = this->storagePath;
                this->storagePathSubdir = this->storagePath + "/frames_" + this->getCurrentTimestampString();
                boost::filesystem::path dir(this->storagePathSubdir.c_str());
                GST_INFO("going to create a directory in %s", this->storagePathSubdir.c_str());
                if (!boost::filesystem::create_directories(dir)) {
                GST_INFO("%s create_directories() failed for: %s", this->epName.c_str(),
                          this->storagePathSubdir.c_str());
                }

            }

            std::string fullpath = this->storagePathSubdir + "/" + filename;

            try {
                cv::imwrite(fullpath.c_str(), ptrVf->mat, params);
            }
            catch (...) {
                GST_ERROR("::queueHandler() imgwrite() failed.");
                throw KurentoException(NOT_IMPLEMENTED,
                                       "TelmateFrameGrabberOpenCVImpl::queueHandler() imgwrite() failed. \n");
            }

            ptrVf->mat.release();   // release internal memory allocations

            delete ptrVf;
            ptrVf = NULL;

        }

}

std::string TelmateFrameGrabberOpenCVImpl::getCurrentTimestampString() {
    struct timeval tp;
    long int ms;
    std::stringstream sstr_ts;

    gettimeofday(&tp, NULL);
    ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;
    sstr_ts << ms;
    return sstr_ts.str();
}

long TelmateFrameGrabberOpenCVImpl::getCurrentTimestampLong() {
    struct timeval tp;

    gettimeofday(&tp, NULL);
    return (tp.tv_sec * 1000 + tp.tv_usec / 1000);
}

}   // namespace kurento
<commit_msg>Testing Storage Set<commit_after>/* Autogenerated with kurento-module-creator */

#include "TelmateFrameGrabberOpenCVImpl.hpp"
#include <gst/gst.h>
#include <KurentoException.hpp>
#include <vector>
#include <string>

#define GST_CAT_DEFAULT kurento_telmate_frame_grabber_opencv_impl
GST_DEBUG_CATEGORY_STATIC(GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoTelmateFrameGrabberOpenCVImpl"

namespace kurento {

TelmateFrameGrabberOpenCVImpl::TelmateFrameGrabberOpenCVImpl() {

    GST_DEBUG_CATEGORY_INIT(GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                            GST_DEFAULT_NAME);

    this->thrLoop = true;
    this->snapInterval = 1000;
    this->epName = "EP_NAME_UNINITIALIZED";
    this->storagePath = "/tmp/";
    this->prevStoragePath = this->storagePath;
    this->framesCounter = 0;
    this->outputFormat = FGFMT_JPEG;
    this->lastQueueTimeStamp = 0;
    this->queueLength = 0;
    this->frameQueue = new avis_blocking_queue<VideoFrame*>;

    this->thr = new boost::thread(boost::bind(
            &TelmateFrameGrabberOpenCVImpl::queueHandler, this));
    this->thr->detach();

    GST_INFO("Constructor was called for %s", this->epName.c_str());
}

TelmateFrameGrabberOpenCVImpl::~TelmateFrameGrabberOpenCVImpl() {

    GST_INFO("Destructor was called for %s", this->epName.c_str());

}

void TelmateFrameGrabberOpenCVImpl::cleanup() {

    VideoFrame *ptrVf;

    while(!this->frameQueue->empty()) {
        this->frameQueue->pop(ptrVf); // blocks
        --this->queueLength;
        delete ptrVf;
        ptrVf = NULL;

    }

    this->thrLoop = false;
    boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); /* Give the processing thread some time to exit() */
    GST_INFO("Called release() for %s :: Dequeue completed.", this->epName.c_str());

    delete this->frameQueue;
    this->frameQueue = NULL;

    return;
}

/*
 * This function will be called with each new frame. mat variable
 * contains the current frame. You should insert your image processing code
 * here. Any changes in mat, will be sent through the Media Pipeline.
 */
void TelmateFrameGrabberOpenCVImpl::process(cv::Mat &mat) {
        if ((this->getCurrentTimestampLong() - this->lastQueueTimeStamp) >= this->snapInterval) {

            if(this->thrLoop) { // do not push into the queue if the destructor was called.
                this->lastQueueTimeStamp = this->getCurrentTimestampLong();
                VideoFrame *ptrVf = new VideoFrame();
                ptrVf->mat = mat.clone();
                ptrVf->ts = std::to_string(this->lastQueueTimeStamp);

                this->frameQueue->push(ptrVf);
                ++this->queueLength;
                ++this->framesCounter;
            }
        }
}
/*
 * This function is executed inside the queueHandler thread as a main() function.
 * It pops a VideoFrame from the framequeue and saves it to disk.
 * a boost scoped_lock is implemented to ensure the queue is emptied to disk before
 * the destructor is executed. a 1 second sleep is implemented inside the while() loop
 * to ensure the cpu isn't exhausted while the queue is empty.
 */
void TelmateFrameGrabberOpenCVImpl::queueHandler() {
        VideoFrame *ptrVf;
        cv::Mat image;
        std::vector<int> params;
        std::string image_extension;

        while (this->thrLoop) {

            this->frameQueue->pop(ptrVf); // blocks
            params.clear();     // clear the vector since the last iteration.
            this->lastQueueTimeStamp = this->getCurrentTimestampLong();
            --this->queueLength;

            switch (this->outputFormat) {
                case FGFMT_JPEG:
                    /* Set jpeg params */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
                case FGFMT_PNG:
                    /* Set PNG parameters, compression etc. */
                    params.push_back(CV_IMWRITE_PNG_COMPRESSION);
                    params.push_back(FG_PNG_QUALITY);
                    image_extension = ".png";
                    break;
                default:
                    /* Defaults to jpeg */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
            }

            std::string filename =
                    std::to_string((long) this->framesCounter) + "_" + ptrVf->ts + image_extension;

            if(this->storagePath.compare(this->prevStoragePath)) {
                this->storagePathSubdir.clear();
                GST_INFO("Storage path has changed. old storage path: %s. new storage path: %s",this->prevStoragePath.c_str(), this->storagePathSubdir.c_str());

            }

            if (this->storagePathSubdir.empty()) {

                this->prevStoragePath = this->storagePath;
                this->storagePathSubdir = this->storagePath + "/frames_" + this->getCurrentTimestampString();
                boost::filesystem::path dir(this->storagePathSubdir.c_str());
                GST_INFO("going to create a directory in %s", this->storagePathSubdir.c_str());
                if (!boost::filesystem::create_directories(dir)) {
                GST_ERROR("%s create_directories() failed for: %s", this->epName.c_str(),
                          this->storagePathSubdir.c_str());
                }

            }

            std::string fullpath = this->storagePathSubdir + "/" + filename;

            try {
                cv::imwrite(fullpath.c_str(), ptrVf->mat, params);
            }
            catch (...) {
                GST_ERROR("::queueHandler() imgwrite() failed.");
                throw KurentoException(NOT_IMPLEMENTED,
                                       "TelmateFrameGrabberOpenCVImpl::queueHandler() imgwrite() failed. \n");
            }

            ptrVf->mat.release();   // release internal memory allocations

            delete ptrVf;
            ptrVf = NULL;

        }

}

std::string TelmateFrameGrabberOpenCVImpl::getCurrentTimestampString() {
    struct timeval tp;
    long int ms;
    std::stringstream sstr_ts;

    gettimeofday(&tp, NULL);
    ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;
    sstr_ts << ms;
    return sstr_ts.str();
}

long TelmateFrameGrabberOpenCVImpl::getCurrentTimestampLong() {
    struct timeval tp;

    gettimeofday(&tp, NULL);
    return (tp.tv_sec * 1000 + tp.tv_usec / 1000);
}

}   // namespace kurento
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015, Youssef Kashef
// Copyright (c) 2015, ELM Library Project
// 3-clause BSD License
//
//M*/
#include "elm/core/boost/serialization/ser_cvtermcriteria.h"

#include "elm/core/boost/translators/transl_str_cvtermcriteria.h"

#include "elm/ts/serialization_assertions.h"

namespace {

static CvTermCriteria CreateExampleCvTermCriteria()
{
    CvTermCriteria c;

    c.epsilon = 0.01;
    c.max_iter = 100;
    c.type = CV_TERMCRIT_EPS;

    return c;
}

template<> CvTermCriteria SerializationTypeAttr_<CvTermCriteria>::example = CreateExampleCvTermCriteria();

INSTANTIATE_TYPED_TEST_CASE_P(SerializationTypedTest_CvTermCriteria_Test, SerializationTypedTest, CvTermCriteria);

} // annonymous namespace for unit tests
<commit_msg>omit unnused include<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015, Youssef Kashef
// Copyright (c) 2015, ELM Library Project
// 3-clause BSD License
//
//M*/
#include "elm/core/boost/serialization/ser_cvtermcriteria.h"

#include "elm/ts/serialization_assertions.h"

namespace {

static CvTermCriteria CreateExampleCvTermCriteria()
{
    CvTermCriteria c;

    c.epsilon = 0.01;
    c.max_iter = 100;
    c.type = CV_TERMCRIT_EPS;

    return c;
}

template<> CvTermCriteria SerializationTypeAttr_<CvTermCriteria>::example = CreateExampleCvTermCriteria();

INSTANTIATE_TYPED_TEST_CASE_P(SerializationTypedTest_CvTermCriteria_Test, SerializationTypedTest, CvTermCriteria);

} // annonymous namespace for unit tests
<|endoftext|>