Add locale information to the links in the chrome://extensions page.

BUG= 28624
TEST= links from the chrome://extensions page should include locale information.

Review URL: http://codereview.chromium.org/467019

git-svn-id: http://src.chromium.org/svn/trunk/src@33857 4ff67af0-8c30-449e-8e8b-ad334ec8d88c

Former-commit-id: dbe8296fc46ac8e5180b1a01ee649824a9fb235a

--- chrome/browser/extensions/extensions_ui.cc
+++ chrome/browser/extensions/extensions_ui.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/extensions/extension_message_service.h"
 #include "chrome/browser/extensions/extensions_service.h"
 #include "chrome/browser/extensions/extension_updater.h"
+#include "chrome/browser/google_util.h"
 #include "chrome/browser/profile.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
@@ -74,13 +75,13 @@
   localized_strings.SetString(L"suggestGallery",
       l10n_util::GetStringF(IDS_EXTENSIONS_NONE_INSTALLED_SUGGEST_GALLERY,
           std::wstring(L"",
+          ASCIIToWide(google_util::AppendGoogleLocaleParam(
+              GURL(extension_urls::kGalleryBrowsePrefix)).spec()) + L"'>",
           L""));
   localized_strings.SetString(L"getMoreExtensions",
       std::wstring(L"" +
+          ASCIIToWide(google_util::AppendGoogleLocaleParam(
+              GURL(extension_urls::kGalleryBrowsePrefix)).spec()) + L"'>" +
           l10n_util::GetString(IDS_GET_MORE_EXTENSIONS) +
           L"");
   localized_strings.SetString(L"extensionDisabled",


linux build fixes

linux build fixes

git-svn-id: de016e52bd170d2d4f2344f9bf92d50478b649e0@17882 0039d316-1c4b-4281-b951-d872f2087c98

--- chrome/browser/gtk/bookmark_manager_gtk.cc
+++ chrome/browser/gtk/bookmark_manager_gtk.cc
@@ -86,7 +86,7 @@
 BookmarkManagerGtk::BookmarkManagerGtk(Profile* profile)
     : profile_(profile),
       model_(profile->GetBookmarkModel()),
-      updates_suppressions_(0) {
+      update_suppressions_(0) {
   InitWidgets();
   g_signal_connect(window_, "destroy",
                    G_CALLBACK(OnWindowDestroy), this);
@@ -421,14 +421,14 @@
         gtk_tree_path_get_indices(path)[gtk_tree_path_get_depth(path) - 1];
   }

-  br->SuppressUpdatesToRightStore();
+  bm->SuppressUpdatesToRightStore();
   for (std::vector<BookmarkNode*>::iterator it = nodes.begin();
        it != nodes.end(); ++it) {
     // Don't try to drop a node into one of its descendants.
     if (!parent->HasAncestor(*it))
       bm->model_->Move(*it, parent, idx++);
   }
-  bookmark_manager->AllowUpdatesToRightStore();
+  bm->AllowUpdatesToRightStore();

   gtk_tree_path_free(path);
   gtk_drag_finish(context, dnd_success, delete_selection_data, time);
@@ -462,7 +462,7 @@
   gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(tree_view), x, y,
                                     &path, &pos);

-  BookmarkNode* parent = bm->GetSelectedNode(bm->left_selection());
+  BookmarkNode* parent = bm->GetFolder();
   if (path) {
     int idx =
         gtk_tree_path_get_indices(path)[gtk_tree_path_get_depth(path) - 1];


The test was failing in chromeos build.

The test was failing in chromeos build.

TBR=evan@chromium.org
BUG=none
TEST=PageMenuModelTest.Basics shoud pass .

Review URL: http://codereview.chromium.org/542100

git-svn-id: dd90618784b6a4b323ea0c23a071cb1c9e6f2ac7@36532 4ff67af0-8c30-449e-8e8b-ad334ec8d88c

--- chrome/browser/page_menu_model_unittest.cc
+++ chrome/browser/page_menu_model_unittest.cc
@@ -27,8 +27,9 @@
   // delegate is internal, it doesn't use the one we pass in.
   model.ActivatedAt(0);
   EXPECT_TRUE(model.IsEnabledAt(0));
-  model.ActivatedAt(3);
-  EXPECT_TRUE(model.IsEnabledAt(3));
+  // Make sure to use the index that is not separator in all configurations.
+  model.ActivatedAt(2);
+  EXPECT_TRUE(model.IsEnabledAt(2));
   EXPECT_EQ(delegate_.execute_count_, 2);
   EXPECT_EQ(delegate_.enable_count_, 2);


Refactored the win policy loader to iterate over all registry keys and show policy names with typos in about:policy.

Also refactored the code to have more reuse between chrome policy and 3rd party policy loading; chrome policies can now be converted from more registry types to value types (e.g. REG_SZ to decoded JSON list).

BUG=155341

Review URL: https://chromiumcodereview.appspot.com/11145022

git-svn-id: de016e52bd170d2d4f2344f9bf92d50478b649e0@163258 0039d316-1c4b-4281-b951-d872f2087c98

--- chrome/browser/policy/policy_loader_win.cc
+++ chrome/browser/policy/policy_loader_win.cc
@@ -56,51 +56,6 @@
   { HKEY_CURRENT_USER,    POLICY_SCOPE_USER     },
 };

-// Determines the registry key with the highest priority that contains
-// the |key_path| key with a |value_name| value inside.
-// |key_path| is a suffix to the Chrome mandatory or recommended registry key,
-// and can be empty to lookup values directly at that key.
-// |value_name| is the name of a value that should exist at that path. If it
-// is empty, then only the existence of the path is verified.
-// Returns true if |key| was updated to point to a key with a |key_path| suffix
-// and optional |value_name| value inside. In that case, |level| and |scope|
-// will contain the appropriate values for the key found.
-// Returns false otherwise.
-bool LoadHighestPriorityKey(const string16& key_path,
-                            const string16& value_name,
-                            RegKey* key,
-                            PolicyLevel* level,
-                            PolicyScope* scope) {
-  // |kKeyPaths| is in decreasing order of priority.
-  static const struct {
-    const wchar_t* path;
-    PolicyLevel level;
-  } kKeyPaths[] = {
-    { kRegistryMandatorySubKey,   POLICY_LEVEL_MANDATORY    },
-    { kRegistryRecommendedSubKey, POLICY_LEVEL_RECOMMENDED  },
-  };
-
-  // Lookup at the mandatory path for both user and machine policies first, and
-  // then at the recommended path.
-  for (size_t k = 0; k < arraysize(kKeyPaths); ++k) {
-    for (size_t h = 0; h < arraysize(kHives); ++h) {
-      string16 path(kKeyPaths[k].path);
-      if (!key_path.empty())
-        path += kPathSep + key_path;
-      if (key->Open(kHives[h].hive, path.c_str(), KEY_READ) != ERROR_SUCCESS ||
-          !key->Valid()) {
-        continue;
-      }
-      if (value_name.empty() || key->HasValue(value_name.c_str())) {
-        *level = kKeyPaths[k].level;
-        *scope = kHives[h].scope;
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
 // Reads a REG_SZ string at |key| named |name| into |result|. Returns false if
 // the string could not be read.
 bool ReadRegistryString(RegKey* key,
@@ -136,91 +91,6 @@
     return false;
   *result = dword;
   return true;
-}
-
-// Returns the Value for a Chrome string policy named |name|, or NULL if
-// it wasn't found. The caller owns the returned value.
-base::Value* ReadChromeStringValue(const string16& name,
-                                   PolicyLevel* level,
-                                   PolicyScope* scope) {
-  RegKey key;
-  if (!LoadHighestPriorityKey(string16(), name, &key, level, scope))
-    return NULL;
-  string16 value;
-  if (!ReadRegistryString(&key, name, &value))
-    return NULL;
-  return base::Value::CreateStringValue(value);
-}
-
-// Returns the Value for a Chrome string list policy named |name|,
-// or NULL if it wasn't found. The caller owns the returned value.
-base::Value* ReadChromeStringListValue(const string16& name,
-                                       PolicyLevel* level,
-                                       PolicyScope* scope) {
-  RegKey key;
-  if (!LoadHighestPriorityKey(name, string16(), &key, level, scope))
-    return NULL;
-  base::ListValue* result = new base::ListValue();
-  string16 value;
-  int index = 0;
-  while (ReadRegistryString(&key, base::IntToString16(++index), &value))
-    result->Append(base::Value::CreateStringValue(value));
-  return result;
-}
-
-// Returns the Value for a Chrome boolean policy named |name|,
-// or NULL if it wasn't found. The caller owns the returned value.
-base::Value* ReadChromeBooleanValue(const string16& name,
-                                    PolicyLevel* level,
-                                    PolicyScope* scope) {
-  RegKey key;
-  if (!LoadHighestPriorityKey(string16(), name, &key, level, scope))
-    return NULL;
-  uint32 value;
-  if (!ReadRegistryInteger(&key, name, &value))
-    return NULL;
-  return base::Value::CreateBooleanValue(value != 0u);
-}
-
-// Returns the Value for a Chrome integer policy named |name|,
-// or NULL if it wasn't found. The caller owns the returned value.
-base::Value* ReadChromeIntegerValue(const string16& name,
-                                    PolicyLevel* level,
-                                    PolicyScope* scope) {
-  RegKey key;
-  if (!LoadHighestPriorityKey(string16(), name, &key, level, scope))
-    return NULL;
-  uint32 value;
-  if (!ReadRegistryInteger(&key, name, &value))
-    return NULL;
-  return base::Value::CreateIntegerValue(value);
-}
-
-// Returns the Value for a Chrome dictionary policy named |name|,
-// or NULL if it wasn't found. The caller owns the returned value.
-base::Value* ReadChromeDictionaryValue(const string16& name,
-                                       PolicyLevel* level,
-                                       PolicyScope* scope) {
-  // Dictionaries are encoded as JSON strings on Windows.
-  //
-  // A dictionary could be stored as a subkey, with each of its entries
-  // within that subkey. However, it would be impossible to recover the
-  // type for some of those entries:
-  //  - Booleans are stored as DWORDS and are indistinguishable from
-  //    integers;
-  //  - Lists are stored as a subkey, with entries mapping 0 to N-1 to
-  //    their value. This is indistinguishable from a Dictionary with
-  //    integer keys.
-  //
-  // The GPO policy editor also has a limited data entry form that doesn't
-  // support dictionaries.
-  RegKey key;
-  if (!LoadHighestPriorityKey(string16(), name, &key, level, scope))
-    return NULL;
-  string16 value;
-  if (!ReadRegistryString(&key, name, &value))
-    return NULL;
-  return base::JSONReader::Read(UTF16ToUTF8(value));
 }

 // Returns the Value type described in |schema|, or |default_type| if not found.
@@ -263,7 +133,7 @@

 // Returns the entry with key |name| in |dictionary| (can be NULL), or NULL.
 const base::DictionaryValue* GetEntry(const base::DictionaryValue* dictionary,
-                                const std::string& name) {
+                                      const std::string& name) {
   if (!dictionary)
     return NULL;
   const base::DictionaryValue* entry = NULL;
@@ -286,8 +156,7 @@
 }

 // Converts string |value| to another |type|, if possible.
-base::Value* ConvertComponentStringValue(const string16& value,
-                                         base::Value::Type type) {
+base::Value* ConvertStringValue(const string16& value, base::Value::Type type) {
   switch (type) {
     case base::Value::TYPE_NULL:
       return base::Value::CreateNullValue();
@@ -330,8 +199,7 @@
 }

 // Converts an integer |value| to another |type|, if possible.
-base::Value* ConvertComponentIntegerValue(uint32 value,
-                                          base::Value::Type type) {
+base::Value* ConvertIntegerValue(uint32 value, base::Value::Type type) {
   switch (type) {
     case base::Value::TYPE_BOOLEAN:
       return base::Value::CreateBooleanValue(value != 0);
@@ -354,25 +222,25 @@
   return NULL;
 }

-// Reads a simple (non-Dictionary, non-Array) value from the registry |key|
-// named |name| with registry type |reg_type| as a value of type |type|.
+// Reads a value from the registry |key| named |name| with registry type
+// |registry_type| as a value of type |type|.
 // Returns NULL if the value could not be loaded or converted.
-base::Value* ReadComponentSimpleValue(RegKey* key,
-                                      const string16& name,
-                                      DWORD reg_type,
-                                      base::Value::Type type) {
-  switch (reg_type) {
+base::Value* ReadPolicyValue(RegKey* key,
+                             const string16& name,
+                             DWORD registry_type,
+                             base::Value::Type type) {
+  switch (registry_type) {
     case REG_SZ: {
       string16 value;
       if (ReadRegistryString(key, name, &value))
-        return ConvertComponentStringValue(value, type);
+        return ConvertStringValue(value, type);
       break;
     }

     case REG_DWORD: {
       uint32 value;
       if (ReadRegistryInteger(key, name, &value))
-        return ConvertComponentIntegerValue(value, type);
+        return ConvertIntegerValue(value, type);
       break;
     }

@@ -380,7 +248,6 @@
       DLOG(WARNING) << "Registry type not supported for key " << name;
       break;
   }
-  NOTREACHED();
   return NULL;
 }

@@ -420,7 +287,7 @@
       DWORD reg_type;
       key.ReadValue(name.c_str(), NULL, NULL, &reg_type);
       if (reg_type != REG_NONE)
-        value = ReadComponentSimpleValue(&key, name, reg_type, type);
+        value = ReadPolicyValue(&key, name, reg_type, type);
     }
     if (value)
       list->Append(value);
@@ -457,8 +324,7 @@
     std::string name(UTF16ToUTF8(name16));
     const base::DictionaryValue* sub_schema = GetSchemaFor(schema, name);
     base::Value::Type type = GetType(sub_schema, GetDefaultFor(it.Type()));
-    base::Value* value =
-        ReadComponentSimpleValue(&key, name16, it.Type(), type);
+    base::Value* value = ReadPolicyValue(&key, name16, it.Type(), type);
     if (value)
       dict->Set(name, value);
   }
@@ -561,40 +427,72 @@
   if (is_initialized_)
     SetupWatches();

-  const PolicyDefinitionList::Entry* current;
-  for (current = policy_list_->begin; current != policy_list_->end; ++current) {
-    const string16 name(ASCIIToUTF16(current->name));
-    PolicyLevel level = POLICY_LEVEL_MANDATORY;
-    PolicyScope scope = POLICY_SCOPE_MACHINE;
-    base::Value* value = NULL;
-
-    switch (current->value_type) {
-      case base::Value::TYPE_STRING:
-        value = ReadChromeStringValue(name, &level, &scope);
-        break;
-
-      case base::Value::TYPE_LIST:
-        value = ReadChromeStringListValue(name, &level, &scope);
-        break;
-
-      case base::Value::TYPE_BOOLEAN:
-        value = ReadChromeBooleanValue(name, &level, &scope);
-        break;
-
-      case base::Value::TYPE_INTEGER:
-        value = ReadChromeIntegerValue(name, &level, &scope);
-        break;
-
-      case base::Value::TYPE_DICTIONARY:
-        value = ReadChromeDictionaryValue(name, &level, &scope);
-        break;
-
-      default:
-        NOTREACHED();
-    }
-
-    if (value)
-      chrome_policies->Set(current->name, level, scope, value);
+  // |kKeyPaths| is in decreasing order of priority.
+  static const struct {
+    const wchar_t* path;
+    PolicyLevel level;
+  } kKeyPaths[] = {
+    { kRegistryMandatorySubKey,   POLICY_LEVEL_MANDATORY    },
+    { kRegistryRecommendedSubKey, POLICY_LEVEL_RECOMMENDED  },
+  };
+
+  // Lookup at the mandatory path for both user and machine policies first, and
+  // then at the recommended path.
+  for (size_t k = 0; k < arraysize(kKeyPaths); ++k) {
+    for (size_t h = 0; h < arraysize(kHives); ++h) {
+      // Iterate over keys and values at this hive and path.
+      HKEY hive = kHives[h].hive;
+      string16 path(kKeyPaths[k].path);
+      RegKey key;
+      if (key.Open(hive, path.c_str(), KEY_READ) != ERROR_SUCCESS ||
+          !key.Valid()) {
+        continue;
+      }
+
+      // Iterate over values for most policies.
+      for (RegistryValueIterator it(hive, path.c_str()); it.Valid(); ++it) {
+        std::string name(UTF16ToUTF8(it.Name()));
+        // Skip if a higher-priority policy value was already inserted, or
+        // if this is the default value (empty string).
+        if (chrome_policies->Get(name) || name.empty())
+          continue;
+        // Get the expected policy type, if this is a known policy.
+        base::Value::Type type = GetDefaultFor(it.Type());
+        for (const PolicyDefinitionList::Entry* e = policy_list_->begin;
+             e != policy_list_->end; ++e) {
+          if (name == e->name) {
+            type = e->value_type;
+            break;
+          }
+        }
+        base::Value* value = ReadPolicyValue(&key, it.Name(), it.Type(), type);
+        if (!value)
+          value = base::Value::CreateNullValue();
+        chrome_policies->Set(name, kKeyPaths[k].level, kHives[h].scope, value);
+      }
+
+      // Iterate over keys for policies of type string-list.
+      for (RegistryKeyIterator it(hive, path.c_str()); it.Valid(); ++it) {
+        std::string name(UTF16ToUTF8(it.Name()));
+        // Skip if a higher-priority policy value was already inserted, or
+        // if this is the 3rd party policy subkey.
+        const string16 kThirdParty16(kThirdParty);
+        if (chrome_policies->Get(name) || it.Name() == kThirdParty16)
+          continue;
+        string16 list_path = path + kPathSep + it.Name();
+        RegKey key;
+        if (key.Open(hive, list_path.c_str(), KEY_READ) != ERROR_SUCCESS ||
+            !key.Valid()) {
+          continue;
+        }
+        base::ListValue* result = new base::ListValue();
+        string16 value;
+        int index = 0;
+        while (ReadRegistryString(&key, base::IntToString16(++index), &value))
+          result->Append(base::Value::CreateStringValue(value));
+        chrome_policies->Set(name, kKeyPaths[k].level, kHives[h].scope, result);
+      }
+    }
   }
 }


Implemented support for clustering_parameters struct.

`kmeans_lloyd` now uses a `clustering_parameters` struct instance for
configuration information which affects the operation of the algorithm.

--- include/dkm.hpp
+++ include/dkm.hpp
@@ -228,14 +228,14 @@
 		_has_rand_seed = true;
 	}

-	bool has_max_iteration() { return _has_max_iter; }
-	bool has_min_delta() { return _has_min_delta; }
-	bool has_random_seed() { return _has_rand_seed; }
-
-	uint32_t get_k() { return _k; };
-	uint64_t get_max_iteration() { return _max_iter; }
-	T get_min_delta() { return _min_delta; }
-	uint64_t get_random_seed() { return _has_rand_seed; }
+	bool has_max_iteration() const { return _has_max_iter; }
+	bool has_min_delta() const { return _has_min_delta; }
+	bool has_random_seed() const { return _has_rand_seed; }
+
+	uint32_t get_k() const { return _k; };
+	uint64_t get_max_iteration() const { return _max_iter; }
+	T get_min_delta() const { return _min_delta; }
+	uint64_t get_random_seed() const { return _has_rand_seed; }

 private:
 	uint32_t _k;
@@ -245,19 +245,18 @@
 	T _min_delta;
 	bool _has_rand_seed;
 	uint64_t _rand_seed;
-}
+};

 /*
 Implementation of k-means generic across the data type and the dimension of each data item. Expects
 the data to be a vector of fixed-size arrays. Generic parameters are the type of the base data (T)
 and the dimensionality of each data point (N). All points must have the same dimensionality.

-Optional parameters are a maximum iteration count and a minimum delta. If the maximum iteration
-count is greater than 0, then the algorithm will terminate when that number of iterations is reached.
-If a minimum delta greater than 0 is specified then the algorithm will terminate when none of the
-means change by more than the specified amount.
-
 e.g. points of the form (X, Y, Z) would be N = 3.
+
+Takes a `clustering_parameters` struct for algorithm configuration. See the comments for the
+`clustering_parameters` struct for more information about the configuration values and how they
+affect the algorithm.

 Returns a std::tuple containing:
   0: A vector holding the means for each cluster from 0 to k-1.
@@ -268,16 +267,17 @@
 This implementation of k-means uses [Lloyd's Algorithm](https://en.wikipedia.org/wiki/Lloyd%27s_algorithm)
 with the [kmeans++](https://en.wikipedia.org/wiki/K-means%2B%2B)
 used for initializing the means.
+
+TODO: Need to implement clustering_parameters support in parallel implementation.
 */
 template <typename T, size_t N>
 std::tuple<std::vector<std::array<T, N>>, std::vector<uint32_t>> kmeans_lloyd(
-	const std::vector<std::array<T, N>>& data, uint32_t k,
-	uint64_t max_iter = 0, T min_delta = -1.0) {
+	const std::vector<std::array<T, N>>& data, const clustering_parameters<T>& parameters) {
 	static_assert(std::is_arithmetic<T>::value && std::is_signed<T>::value,
 		"kmeans_lloyd requires the template parameter T to be a signed arithmetic type (e.g. float, double, int)");
-	assert(k > 0); // k must be greater than zero
-	assert(data.size() >= k); // there must be at least k data points
-	std::vector<std::array<T, N>> means = details::random_plusplus(data, k);
+	assert(parameters.get_k() > 0); // k must be greater than zero
+	assert(data.size() >= parameters.get_k()); // there must be at least k data points
+	std::vector<std::array<T, N>> means = details::random_plusplus(data, parameters.get_k());

 	std::vector<std::array<T, N>> old_means;
 	std::vector<std::array<T, N>> old_old_means;
@@ -288,15 +288,34 @@
 		clusters = details::calculate_clusters(data, means);
 		old_old_means = old_means;
 		old_means = means;
-		means = details::calculate_means(data, clusters, old_means, k);
+		means = details::calculate_means(data, clusters, old_means, parameters.get_k());
 		++count;
 	} while ((means != old_means && means != old_old_means)
-		|| (max_iter != 0 && count == max_iter)
-		|| (min_delta > 0 && !details::deltas_below_limit(details::deltas(old_means, means), min_delta)));
+		|| (parameters.has_max_iteration() && count == parameters.get_max_iteration())
+		|| (parameters.has_min_delta() && !details::deltas_below_limit(details::deltas(old_means, means), parameters.get_min_delta())));

 	return std::tuple<std::vector<std::array<T, N>>, std::vector<uint32_t>>(means, clusters);
 }

+/*
+This overload exists to support legacy code which uses this signature of the kmeans_lloyd function.
+Any code still using this signature should move to the version of this function that uses a
+`clustering_parameters` struct for configuration.
+*/
+template <typename T, size_t N>
+std::tuple<std::vector<std::array<T, N>>, std::vector<uint32_t>> kmeans_lloyd(
+	const std::vector<std::array<T, N>>& data, uint32_t k,
+	uint64_t max_iter = 0, T min_delta = -1.0) {
+	clustering_parameters<T> parameters(k);
+	if (max_iter != 0) {
+		parameters.set_max_iteration(max_iter);
+	}
+	if (min_delta != 0) {
+		parameters.set_min_delta(min_delta);
+	}
+	kmeans_lloyd(data, parameters);
+}
+
 } // namespace dkm

 #endif /* DKM_KMEANS_H */


CodeMod: Prefer ADD_FAILURE() over EXPECT_TRUE(false), et cetera

Summary:
CodeMod: Prefer `ADD_FAILURE()` over `EXPECT_TRUE(false)`, et cetera.

The tautologically-conditioned and tautologically-contradicted boolean expectations/assertions have better alternatives: unconditional passes and failures.

Reviewed By: Orvid

Differential Revision:
D5432398

Tags: codemod, codemod-opensource

fbshipit-source-id: d16b447e8696a6feaa94b41199f5052226ef6914

--- caffe2/core/logging_test.cc
+++ caffe2/core/logging_test.cc
@@ -16,7 +16,7 @@
   try {
     CAFFE_ENFORCE(false, "This throws.");
     // This should never be triggered.
-    EXPECT_FALSE(true);
+    ADD_FAILURE();
   } catch (const EnforceNotMet& err) {
   }
   std::swap(FLAGS_caffe2_use_fatal_for_enforce, kFalse);
@@ -28,7 +28,7 @@
   try {
     CAFFE_ENFORCE_THAT(Equals(++x, ++y));
     // This should never be triggered.
-    EXPECT_FALSE(true);
+    ADD_FAILURE();
   } catch (const EnforceNotMet& err) {
     EXPECT_NE(err.msg().find("5 vs 6"), string::npos);
   }


[http] HttpServer: properly handle large log messages in log(...)

--- lib/http/HttpServer.cpp
+++ lib/http/HttpServer.cpp
@@ -516,13 +516,30 @@
 void HttpServer::log(Severity s, const char *msg, ...)
 {
 	va_list va;
-	va_start(va, msg);
-	char buf[512];
-	int buflen = vsnprintf(buf, sizeof(buf), msg, va);
-	va_end(va);
-
-	if (colored_log_)
-	{
+	Buffer buf(512);
+
+	while (buf.capacity()) {
+		va_start(va, msg);
+		ssize_t buflen = vsnprintf(const_cast<char*>(buf.data()), buf.capacity(), msg, va);
+		va_end(va);
+
+		if (buflen >= -1 && buflen < static_cast<ssize_t>(buf.capacity())) {
+			buf.resize(buflen);
+			break;
+		}
+
+		buflen = buflen > -1
+			? buflen + 1           // glibc >= 2.1
+			: buf.capacity() * 2;  // glibc <= 2.0
+
+		if (!buf.setCapacity(buflen)) {
+			// increasing capacity faileD
+			buf[buf.capacity() - 1] = '\0';
+			break;
+		}
+	}
+
+	if (colored_log_) {
 		static AnsiColor::Type colors[] = {
 			AnsiColor::Red | AnsiColor::Bold, // error
 			AnsiColor::Yellow | AnsiColor::Bold, // warn
@@ -533,20 +550,17 @@

 		Buffer sb;
 		sb.push_back(AnsiColor::make(colors[s + 3]));
-		sb.push_back(buf, buflen);
+		sb.push_back(buf);
 		sb.push_back(AnsiColor::make(AnsiColor::Clear));

 		if (logger_)
 			logger_->write(s, sb.str());
 		else
 			std::fprintf(stderr, "%s\n", sb.c_str());
-	}
-	else
-	{
-		if (logger_)
-			logger_->write(s, buf);
-		else
-			std::fprintf(stderr, "%s\n", buf);
+	} else if (logger_) {
+		logger_->write(s, buf.data());
+	} else {
+		std::fprintf(stderr, "%s\n", buf.data());
 	}
 }


appleseed: multiple camera support  for new version.

--- src/GafferAppleseed/IECoreAppleseedPreview/Renderer.cpp
+++ src/GafferAppleseed/IECoreAppleseedPreview/Renderer.cpp
@@ -148,6 +148,7 @@
 MutexType g_texturesMutex;
 MutexType g_textureInstancesMutex;
 MutexType g_colorsMutex;
+MutexType g_camerasMutex;

 /// Base class for all appleseed object handles.
 class AppleseedEntity : public IECoreScenePreview::Renderer::ObjectInterface
@@ -191,16 +192,16 @@
 			m_mainAssembly->bump_version_id();
 		}

-		void setCamera( asf::auto_release_ptr<asr::Camera> camera, const CompoundData *cameraParams )
-		{
-			m_project.get_scene()->set_camera( camera );
-			resetFrame( cameraParams );
-		}
-
-		void removeCamera()
-		{
-			m_project.get_scene()->set_camera( asf::auto_release_ptr<asr::Camera>() );
-			resetFrame( NULL );
+		void insertCamera( asf::auto_release_ptr<asr::Camera> camera )
+		{
+			LockGuardType lock( g_camerasMutex );
+			m_project.get_scene()->cameras().insert( camera );
+		}
+
+		void removeCamera( asr::Camera *camera )
+		{
+			LockGuardType lock( g_camerasMutex );
+			m_project.get_scene()->cameras().remove( camera );
 		}

 		void insertEnvironmentEDF( asf::auto_release_ptr<asr::EnvironmentEDF> environment )
@@ -372,49 +373,53 @@
 			doRemoveEntities( m_colors, m_mainAssembly->colors() );
 		}

-	private :
-
-		void resetFrame( const CompoundData *cameraParams )
-		{
+		void resetFrame( const string &cameraName, const CompoundData *cameraParams )
+		{
+			assert( cameraParams );
 			asr::ParamArray &params = m_project.get_frame()->get_parameters();

-			if( cameraParams )
-			{
-				// Resolution
-				const V2iData *resolution = cameraParams->member<V2iData>( "resolution" );
-				asf::Vector2i res( resolution->readable().x, resolution->readable().y );
-				params.insert( "resolution", res );
-
-				// Render region.
-				if( const Box2iData *renderRegion = cameraParams->member<Box2iData>( "renderRegion" ) )
-				{
-					// For now, we don't do overscan.
-					// We keep only the crop part of the render region.
-					asf::AABB2u crop;
-					crop.min[0] = asf::clamp( (int) renderRegion->readable().min.x, 0, res[0] - 1 );
-					crop.min[1] = asf::clamp( (int) renderRegion->readable().min.y, 0, res[1] - 1 );
-					crop.max[0] = asf::clamp( (int) renderRegion->readable().max.x, 0, res[0] - 1 );
-					crop.max[1] = asf::clamp( (int) renderRegion->readable().max.y, 0, res[1] - 1 );
-					params.insert( "crop_window", crop );
-				}
-				else
-				{
-					params.remove_path( "crop_window" );
-				}
-
-				const asr::Camera *camera = scene().get_camera();
-				params.insert( "camera", camera->get_name() );
+			// Resolution
+			const V2iData *resolution = cameraParams->member<V2iData>( "resolution" );
+			asf::Vector2i res( resolution->readable().x, resolution->readable().y );
+			params.insert( "resolution", res );
+
+			// Render region.
+			if( const Box2iData *renderRegion = cameraParams->member<Box2iData>( "renderRegion" ) )
+			{
+				// For now, we don't do overscan.
+				// We keep only the crop part of the render region.
+				asf::AABB2u crop;
+				crop.min[0] = asf::clamp( (int) renderRegion->readable().min.x, 0, res[0] - 1 );
+				crop.min[1] = asf::clamp( (int) renderRegion->readable().min.y, 0, res[1] - 1 );
+				crop.max[0] = asf::clamp( (int) renderRegion->readable().max.x, 0, res[0] - 1 );
+				crop.max[1] = asf::clamp( (int) renderRegion->readable().max.y, 0, res[1] - 1 );
+				params.insert( "crop_window", crop );
 			}
 			else
 			{
-				params.remove_path( "camera" );
-				params.insert( "resolution", "640 480" );
 				params.remove_path( "crop_window" );
 			}
+
+			// Choose the active camera.
+			params.insert( "camera", cameraName.c_str() );

 			// Replace the frame.
 			m_project.set_frame( asr::FrameFactory().create( "beauty", params ) );
 		}
+
+		void resetFrame()
+		{
+			// Reset the frame to default values.
+			asr::ParamArray &params = m_project.get_frame()->get_parameters();
+			params.remove_path( "camera" );
+			params.insert( "resolution", "640 480" );
+			params.remove_path( "crop_window" );
+
+			// Replace the frame.
+			m_project.set_frame( asr::FrameFactory().create( "beauty", params ) );
+		}
+
+	private :

 		template <typename EntityType, typename EntityContainer>
 		void doRemoveEntities( vector<EntityType*> &entities, EntityContainer &container )
@@ -763,20 +768,30 @@

 	public :

-		AppleseedCamera( asr::Project &project, const string &name, Camera *camera, const IECoreScenePreview::Renderer::AttributesInterface *attributes, bool interactive )
-			:	AppleseedEntity( project, name, interactive )
+		AppleseedCamera( asr::Project &project, const string &name, Camera *camera, const IECoreScenePreview::Renderer::AttributesInterface *attributes, bool activeCamera, bool interactive )
+			:	AppleseedEntity( project, name, interactive ), m_activeCamera( activeCamera )
 		{
 			asf::auto_release_ptr<asr::Camera> appleseedCamera( CameraAlgo::convert( camera ) );
 			appleseedCamera->set_name( name.c_str() );
 			m_camera = appleseedCamera.get();
-			setCamera( appleseedCamera, camera->parametersData() );
+			insertCamera( appleseedCamera );
+
+			if( m_activeCamera )
+			{
+				resetFrame( name, camera->parametersData() );
+			}
 		}

 		virtual ~AppleseedCamera()
 		{
 			if( isInteractiveRender() )
 			{
-				removeCamera();
+				removeCamera( m_camera );
+
+				if( m_activeCamera )
+				{
+					resetFrame();
+				}
 			}
 		}

@@ -799,6 +814,7 @@
 	private :

 		asr::Camera *m_camera;
+		bool m_activeCamera;
 };

 } // namespace
@@ -1880,21 +1896,22 @@

 		virtual ObjectInterfacePtr camera( const string &name, const Camera *camera, const AttributesInterface *attributes )
 		{
+			CameraPtr cameraCopy = camera->copy();
+			cameraCopy->addStandardParameters();
+			bool activeCamera = false;
+
+			// Check if this is the active camera.
 			if( name == m_cameraName )
 			{
-				CameraPtr cameraCopy = camera->copy();
-				cameraCopy->addStandardParameters();
-
 				// Save the shutter times for later use.
 				const V2f &shutter = cameraCopy->parametersData()->member<V2fData>( "shutter", true )->readable();
 				m_shutterOpenTime = shutter.x;
 				m_shutterCloseTime = shutter.y;

-				return new AppleseedCamera( *m_project, name, cameraCopy.get(), attributes, isInteractiveRender() );
-			}
-
-			// appleseed supports only one camera. Ignore any extra cameras.
-			return new AppleseedNullObject( *m_project, name, isInteractiveRender() );
+				activeCamera = true;
+			}
+
+			return new AppleseedCamera( *m_project, name, cameraCopy.get(), attributes, activeCamera, isInteractiveRender() );
 		}

 		virtual ObjectInterfacePtr light( const string &name, const Object *object, const AttributesInterface *attributes )
@@ -1957,11 +1974,11 @@
 		virtual void render()
 		{
 			// Create a default camera if needed.
-			if( m_project->get_scene()->get_camera() == NULL )
-			{
-				asf::auto_release_ptr<asr::Camera> camera = asr::PinholeCameraFactory().create( "camera", asr::ParamArray() );
-				m_project->get_scene()->set_camera( camera );
-				m_project->get_frame()->get_parameters().insert( "camera", "camera" );
+			if( m_project->get_uncached_active_camera() == NULL )
+			{
+				asf::auto_release_ptr<asr::Camera> camera = asr::PinholeCameraFactory().create( "__default_camera", asr::ParamArray() );
+				m_project->get_scene()->cameras().insert( camera );
+				m_project->get_frame()->get_parameters().insert( "camera", "__default_camera" );
 			}

 			// Setup the environment.