Rebuild aura::Window's property system on top of mojo::View.
BUG=431047
R=sky@chromium.org
Review URL: https://codereview.chromium.org/732223002
diff --git a/mojo/services/public/cpp/view_manager/BUILD.gn b/mojo/services/public/cpp/view_manager/BUILD.gn
index 7192ef7..2c7c607 100644
--- a/mojo/services/public/cpp/view_manager/BUILD.gn
+++ b/mojo/services/public/cpp/view_manager/BUILD.gn
@@ -18,6 +18,7 @@
"view_manager_context.h",
"view_manager_delegate.h",
"view_observer.h",
+ "view_property.h",
"view_tracker.cc",
"view_tracker.h",
"window_manager_delegate.h",
diff --git a/mojo/services/public/cpp/view_manager/lib/view.cc b/mojo/services/public/cpp/view_manager/lib/view.cc
index 7de1861..bedac6b 100644
--- a/mojo/services/public/cpp/view_manager/lib/view.cc
+++ b/mojo/services/public/cpp/view_manager/lib/view.cc
@@ -228,8 +228,8 @@
FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanged(this));
}
-void View::SetProperty(const std::string& name,
- const std::vector<uint8_t>* value) {
+void View::SetSharedProperty(const std::string& name,
+ const std::vector<uint8_t>* value) {
std::vector<uint8_t> old_value;
std::vector<uint8_t>* old_value_ptr = nullptr;
auto it = properties_.find(name);
@@ -251,8 +251,9 @@
properties_.erase(it);
}
- FOR_EACH_OBSERVER(ViewObserver, observers_,
- OnViewPropertyChanged(this, name, old_value_ptr, value));
+ FOR_EACH_OBSERVER(
+ ViewObserver, observers_,
+ OnViewSharedPropertyChanged(this, name, old_value_ptr, value));
}
bool View::IsDrawn() const {
@@ -389,6 +390,14 @@
// ViewManagerClientImpl.
if (manager_)
static_cast<ViewManagerClientImpl*>(manager_)->RemoveView(id_);
+
+ // Clear properties.
+ for (auto& pair : prop_map_) {
+ if (pair.second.deallocator)
+ (*pair.second.deallocator)(pair.second.value);
+ }
+ prop_map_.clear();
+
FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDestroyed(this));
}
@@ -403,6 +412,34 @@
drawn_(false) {
}
+int64 View::SetLocalPropertyInternal(const void* key,
+ const char* name,
+ PropertyDeallocator deallocator,
+ int64 value,
+ int64 default_value) {
+ int64 old = GetLocalPropertyInternal(key, default_value);
+ if (value == default_value) {
+ prop_map_.erase(key);
+ } else {
+ Value prop_value;
+ prop_value.name = name;
+ prop_value.value = value;
+ prop_value.deallocator = deallocator;
+ prop_map_[key] = prop_value;
+ }
+ FOR_EACH_OBSERVER(ViewObserver, observers_,
+ OnViewLocalPropertyChanged(this, key, old));
+ return old;
+}
+
+int64 View::GetLocalPropertyInternal(const void* key,
+ int64 default_value) const {
+ std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
+ if (iter == prop_map_.end())
+ return default_value;
+ return iter->second.value;
+}
+
void View::LocalDestroy() {
delete this;
}
diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc b/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc
index 9421e18..e70ec2b 100644
--- a/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc
+++ b/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc
@@ -341,7 +341,7 @@
ViewPrivate(view).LocalSetDrawn(drawn);
}
-void ViewManagerClientImpl::OnViewPropertyChanged(
+void ViewManagerClientImpl::OnViewSharedPropertyChanged(
Id view_id,
const String& name,
Array<uint8_t> new_data) {
@@ -354,7 +354,7 @@
data_ptr = &data;
}
- view->SetProperty(name, data_ptr);
+ view->SetSharedProperty(name, data_ptr);
}
}
diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h b/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h
index 2c941da..2707ad6 100644
--- a/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h
+++ b/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h
@@ -108,9 +108,9 @@
void OnViewDeleted(Id view_id) override;
void OnViewVisibilityChanged(Id view_id, bool visible) override;
void OnViewDrawnStateChanged(Id view_id, bool drawn) override;
- void OnViewPropertyChanged(Id view_id,
- const String& name,
- Array<uint8_t> new_data) override;
+ void OnViewSharedPropertyChanged(Id view_id,
+ const String& name,
+ Array<uint8_t> new_data) override;
void OnViewInputEvent(Id view_id,
EventPtr event,
const Callback<void()>& callback) override;
diff --git a/mojo/services/public/cpp/view_manager/tests/view_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_unittest.cc
index eb7276c..b0bd08b 100644
--- a/mojo/services/public/cpp/view_manager/tests/view_unittest.cc
+++ b/mojo/services/public/cpp/view_manager/tests/view_unittest.cc
@@ -9,6 +9,7 @@
#include "mojo/services/public/cpp/view_manager/lib/view_private.h"
#include "mojo/services/public/cpp/view_manager/util.h"
#include "mojo/services/public/cpp/view_manager/view_observer.h"
+#include "mojo/services/public/cpp/view_manager/view_property.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
@@ -102,6 +103,88 @@
EXPECT_FALSE(v11.IsDrawn());
}
+namespace {
+DEFINE_VIEW_PROPERTY_KEY(int, kIntKey, -2);
+DEFINE_VIEW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
+}
+
+TEST_F(ViewTest, Property) {
+ TestView v;
+
+ // Non-existent properties should return the default values.
+ EXPECT_EQ(-2, v.GetLocalProperty(kIntKey));
+ EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey));
+
+ // A set property value should be returned again (even if it's the default
+ // value).
+ v.SetLocalProperty(kIntKey, INT_MAX);
+ EXPECT_EQ(INT_MAX, v.GetLocalProperty(kIntKey));
+ v.SetLocalProperty(kIntKey, -2);
+ EXPECT_EQ(-2, v.GetLocalProperty(kIntKey));
+ v.SetLocalProperty(kIntKey, INT_MIN);
+ EXPECT_EQ(INT_MIN, v.GetLocalProperty(kIntKey));
+
+ v.SetLocalProperty(kStringKey, static_cast<const char*>(NULL));
+ EXPECT_EQ(NULL, v.GetLocalProperty(kStringKey));
+ v.SetLocalProperty(kStringKey, "squeamish");
+ EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey));
+ v.SetLocalProperty(kStringKey, "ossifrage");
+ EXPECT_EQ(std::string("ossifrage"), v.GetLocalProperty(kStringKey));
+
+ // ClearProperty should restore the default value.
+ v.ClearLocalProperty(kIntKey);
+ EXPECT_EQ(-2, v.GetLocalProperty(kIntKey));
+ v.ClearLocalProperty(kStringKey);
+ EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey));
+}
+
+namespace {
+
+class TestProperty {
+ public:
+ TestProperty() {}
+ virtual ~TestProperty() { last_deleted_ = this; }
+ static TestProperty* last_deleted() { return last_deleted_; }
+
+ private:
+ static TestProperty* last_deleted_;
+ DISALLOW_COPY_AND_ASSIGN(TestProperty);
+};
+
+TestProperty* TestProperty::last_deleted_ = NULL;
+
+DEFINE_OWNED_VIEW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
+
+} // namespace
+
+TEST_F(ViewTest, OwnedProperty) {
+ TestProperty* p3 = NULL;
+ {
+ TestView v;
+ EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey));
+ TestProperty* p1 = new TestProperty();
+ v.SetLocalProperty(kOwnedKey, p1);
+ EXPECT_EQ(p1, v.GetLocalProperty(kOwnedKey));
+ EXPECT_EQ(NULL, TestProperty::last_deleted());
+
+ TestProperty* p2 = new TestProperty();
+ v.SetLocalProperty(kOwnedKey, p2);
+ EXPECT_EQ(p2, v.GetLocalProperty(kOwnedKey));
+ EXPECT_EQ(p1, TestProperty::last_deleted());
+
+ v.ClearLocalProperty(kOwnedKey);
+ EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey));
+ EXPECT_EQ(p2, TestProperty::last_deleted());
+
+ p3 = new TestProperty();
+ v.SetLocalProperty(kOwnedKey, p3);
+ EXPECT_EQ(p3, v.GetLocalProperty(kOwnedKey));
+ EXPECT_EQ(p2, TestProperty::last_deleted());
+ }
+
+ EXPECT_EQ(p3, TestProperty::last_deleted());
+}
+
// ViewObserver --------------------------------------------------------
typedef testing::Test ViewObserverTest;
@@ -614,12 +697,12 @@
namespace {
-class PropertyChangeObserver : public ViewObserver {
+class SharedPropertyChangeObserver : public ViewObserver {
public:
- explicit PropertyChangeObserver(View* view) : view_(view) {
+ explicit SharedPropertyChangeObserver(View* view) : view_(view) {
view_->AddObserver(this);
}
- virtual ~PropertyChangeObserver() { view_->RemoveObserver(this); }
+ virtual ~SharedPropertyChangeObserver() { view_->RemoveObserver(this); }
Changes GetAndClearChanges() {
Changes changes;
@@ -629,16 +712,15 @@
private:
// Overridden from ViewObserver:
- void OnViewPropertyChanged(View* view,
- const std::string& name,
- const std::vector<uint8_t>* old_data,
- const std::vector<uint8_t>* new_data) override {
+ void OnViewSharedPropertyChanged(
+ View* view,
+ const std::string& name,
+ const std::vector<uint8_t>* old_data,
+ const std::vector<uint8_t>* new_data) override {
changes_.push_back(base::StringPrintf(
- "view=%s property changed key=%s old_value=%s new_value=%s",
- ViewIdToString(view->id()).c_str(),
- name.c_str(),
- VectorToString(old_data).c_str(),
- VectorToString(new_data).c_str()));
+ "view=%s shared property changed key=%s old_value=%s new_value=%s",
+ ViewIdToString(view->id()).c_str(), name.c_str(),
+ VectorToString(old_data).c_str(), VectorToString(new_data).c_str()));
}
std::string VectorToString(const std::vector<uint8_t>* data) {
@@ -653,50 +735,110 @@
View* view_;
Changes changes_;
- DISALLOW_COPY_AND_ASSIGN(PropertyChangeObserver);
+ DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver);
};
} // namespace
-TEST_F(ViewObserverTest, SetProperty) {
+TEST_F(ViewObserverTest, SetLocalProperty) {
TestView v1;
std::vector<uint8_t> one(1, '1');
{
// Change visibility from true to false and make sure we get notifications.
- PropertyChangeObserver observer(&v1);
- v1.SetProperty("one", &one);
+ SharedPropertyChangeObserver observer(&v1);
+ v1.SetSharedProperty("one", &one);
Changes changes = observer.GetAndClearChanges();
ASSERT_EQ(1U, changes.size());
- EXPECT_EQ("view=0,1 property changed key=one old_value=NULL new_value=1",
- changes[0]);
- EXPECT_EQ(1U, v1.properties().size());
+ EXPECT_EQ(
+ "view=0,1 shared property changed key=one old_value=NULL new_value=1",
+ changes[0]);
+ EXPECT_EQ(1U, v1.shared_properties().size());
}
{
// Set visible to existing value and verify no notifications.
- PropertyChangeObserver observer(&v1);
- v1.SetProperty("one", &one);
+ SharedPropertyChangeObserver observer(&v1);
+ v1.SetSharedProperty("one", &one);
EXPECT_TRUE(observer.GetAndClearChanges().empty());
- EXPECT_EQ(1U, v1.properties().size());
+ EXPECT_EQ(1U, v1.shared_properties().size());
}
{
// Set the value to NULL to delete it.
// Change visibility from true to false and make sure we get notifications.
- PropertyChangeObserver observer(&v1);
- v1.SetProperty("one", NULL);
+ SharedPropertyChangeObserver observer(&v1);
+ v1.SetSharedProperty("one", NULL);
Changes changes = observer.GetAndClearChanges();
ASSERT_EQ(1U, changes.size());
- EXPECT_EQ("view=0,1 property changed key=one old_value=1 new_value=NULL",
- changes[0]);
- EXPECT_EQ(0U, v1.properties().size());
+ EXPECT_EQ(
+ "view=0,1 shared property changed key=one old_value=1 new_value=NULL",
+ changes[0]);
+ EXPECT_EQ(0U, v1.shared_properties().size());
}
{
// Setting a null property to null shouldn't update us.
- PropertyChangeObserver observer(&v1);
- v1.SetProperty("one", NULL);
+ SharedPropertyChangeObserver observer(&v1);
+ v1.SetSharedProperty("one", NULL);
EXPECT_TRUE(observer.GetAndClearChanges().empty());
- EXPECT_EQ(0U, v1.properties().size());
+ EXPECT_EQ(0U, v1.shared_properties().size());
}
}
+namespace {
+
+typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
+
+class LocalPropertyChangeObserver : public ViewObserver {
+ public:
+ explicit LocalPropertyChangeObserver(View* view)
+ : view_(view),
+ property_key_(nullptr),
+ old_property_value_(-1) {
+ view_->AddObserver(this);
+ }
+ virtual ~LocalPropertyChangeObserver() { view_->RemoveObserver(this); }
+
+ PropertyChangeInfo PropertyChangeInfoAndClear() {
+ PropertyChangeInfo result(property_key_, old_property_value_);
+ property_key_ = NULL;
+ old_property_value_ = -3;
+ return result;
+ }
+
+ private:
+ void OnViewLocalPropertyChanged(View* window,
+ const void* key,
+ intptr_t old) override {
+ property_key_ = key;
+ old_property_value_ = old;
+ }
+
+ View* view_;
+ const void* property_key_;
+ intptr_t old_property_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver);
+};
+
+} // namespace
+
+TEST_F(ViewObserverTest, LocalPropertyChanged) {
+ TestView v1;
+ LocalPropertyChangeObserver o(&v1);
+
+ static const ViewProperty<int> prop = {-2};
+
+ v1.SetLocalProperty(&prop, 1);
+ EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear());
+ v1.SetLocalProperty(&prop, -2);
+ EXPECT_EQ(PropertyChangeInfo(&prop, 1), o.PropertyChangeInfoAndClear());
+ v1.SetLocalProperty(&prop, 3);
+ EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear());
+ v1.ClearLocalProperty(&prop);
+ EXPECT_EQ(PropertyChangeInfo(&prop, 3), o.PropertyChangeInfoAndClear());
+
+ // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
+ EXPECT_EQ(PropertyChangeInfo(
+ reinterpret_cast<const void*>(NULL), -3), o.PropertyChangeInfoAndClear());
+}
+
} // namespace mojo
diff --git a/mojo/services/public/cpp/view_manager/view.h b/mojo/services/public/cpp/view_manager/view.h
index 72f044c..85011ba 100644
--- a/mojo/services/public/cpp/view_manager/view.h
+++ b/mojo/services/public/cpp/view_manager/view.h
@@ -23,6 +23,10 @@
class ViewManager;
class ViewObserver;
+// Defined in view_property.h (which we do not include)
+template <typename T>
+struct ViewProperty;
+
// Views are owned by the ViewManager.
// TODO(beng): Right now, you'll have to implement a ViewObserver to track
// destruction and NULL any pointers you have.
@@ -49,11 +53,41 @@
bool visible() const { return visible_; }
void SetVisible(bool value);
- const std::map<std::string, std::vector<uint8_t>>& properties() const {
+ // Returns the set of string to bag of byte properties. These properties are
+ // shared with the view manager.
+ const std::map<std::string, std::vector<uint8_t>>& shared_properties() const {
return properties_;
}
// Sets a property. If |data| is null, this property is deleted.
- void SetProperty(const std::string& name, const std::vector<uint8_t>* data);
+ void SetSharedProperty(const std::string& name,
+ const std::vector<uint8_t>* data);
+
+ // Sets the |value| of the given window |property|. Setting to the default
+ // value (e.g., NULL) removes the property. The caller is responsible for the
+ // lifetime of any object set as a property on the View.
+ //
+ // These properties are not visible to the view manager.
+ template <typename T>
+ void SetLocalProperty(const ViewProperty<T>* property, T value);
+
+ // Returns the value of the given window |property|. Returns the
+ // property-specific default value if the property was not previously set.
+ //
+ // These properties are only visible in the current process and are not
+ // shared with other mojo services.
+ template <typename T>
+ T GetLocalProperty(const ViewProperty<T>* property) const;
+
+ // Sets the |property| to its default value. Useful for avoiding a cast when
+ // setting to NULL.
+ //
+ // These properties are only visible in the current process and are not
+ // shared with other mojo services.
+ template <typename T>
+ void ClearLocalProperty(const ViewProperty<T>* property);
+
+ // Type of a function to delete a property that this view owns.
+ typedef void (*PropertyDeallocator)(int64 value);
// A View is drawn if the View and all its ancestors are visible and the
// View is attached to the root.
@@ -101,6 +135,14 @@
explicit View(ViewManager* manager);
+ // Called by the public {Set,Get,Clear}Property functions.
+ int64 SetLocalPropertyInternal(const void* key,
+ const char* name,
+ PropertyDeallocator deallocator,
+ int64 value,
+ int64 default_value);
+ int64 GetLocalPropertyInternal(const void* key, int64 default_value) const;
+
void LocalDestroy();
void LocalAddChild(View* child);
void LocalRemoveChild(View* child);
@@ -126,6 +168,17 @@
// state. This field is only used if the view has no parent (eg it's a root).
bool drawn_;
+ // Value struct to keep the name and deallocator for this property.
+ // Key cannot be used for this purpose because it can be char* or
+ // WindowProperty<>.
+ struct Value {
+ const char* name;
+ int64 value;
+ PropertyDeallocator deallocator;
+ };
+
+ std::map<const void*, Value> prop_map_;
+
DISALLOW_COPY_AND_ASSIGN(View);
};
diff --git a/mojo/services/public/cpp/view_manager/view_observer.h b/mojo/services/public/cpp/view_manager/view_observer.h
index 480f660..fd31c97 100644
--- a/mojo/services/public/cpp/view_manager/view_observer.h
+++ b/mojo/services/public/cpp/view_manager/view_observer.h
@@ -63,10 +63,26 @@
virtual void OnViewVisibilityChanging(View* view) {}
virtual void OnViewVisibilityChanged(View* view) {}
- virtual void OnViewPropertyChanged(View* view,
- const std::string& name,
- const std::vector<uint8_t>* old_data,
- const std::vector<uint8_t>* new_data) {}
+ // Invoked when this View's shared properties have changed. This can either
+ // be caused by SetSharedProperty() being called locally, or by us receiving
+ // a mojo message that this property has changed. If this property has been
+ // added, |old_data| is null. If this property was removed, |new_data| is
+ // null.
+ virtual void OnViewSharedPropertyChanged(
+ View* view,
+ const std::string& name,
+ const std::vector<uint8_t>* old_data,
+ const std::vector<uint8_t>* new_data) {}
+
+ // Invoked when SetProperty() or ClearProperty() is called on the window.
+ // |key| is either a WindowProperty<T>* (SetProperty, ClearProperty). Either
+ // way, it can simply be compared for equality with the property
+ // constant. |old| is the old property value, which must be cast to the
+ // appropriate type before use.
+ virtual void OnViewLocalPropertyChanged(
+ View* view,
+ const void* key,
+ intptr_t old) {}
virtual void OnViewEmbeddedAppDisconnected(View* view) {}
diff --git a/mojo/services/public/cpp/view_manager/view_property.h b/mojo/services/public/cpp/view_manager/view_property.h
new file mode 100644
index 0000000..11e5e49
--- /dev/null
+++ b/mojo/services/public/cpp/view_manager/view_property.h
@@ -0,0 +1,140 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_PROPERTY_H_
+#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_PROPERTY_H_
+
+#include "base/basictypes.h"
+
+// This header should be included by code that defines ViewProperties. It
+// should not be included by code that only gets and sets ViewProperties.
+//
+// To define a new ViewProperty:
+//
+// #include "mojo/services/public/cpp/view_manager/view_property.h"
+//
+// DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(FOO_EXPORT, MyType);
+// namespace foo {
+// // Use this to define an exported property that is premitive,
+// // or a pointer you don't want automatically deleted.
+// DEFINE_VIEW_PROPERTY_KEY(MyType, kMyKey, MyDefault);
+//
+// // Use this to define an exported property whose value is a heap
+// // allocated object, and has to be owned and freed by the view.
+// DEFINE_OWNED_VIEW_PROPERTY_KEY(gfx::Rect, kRestoreBoundsKey, nullptr);
+//
+// // Use this to define a non exported property that is primitive,
+// // or a pointer you don't want to automatically deleted, and is used
+// // only in a specific file. This will define the property in an unnamed
+// // namespace which cannot be accessed from another file.
+// DEFINE_LOCAL_VIEW_PROPERTY_KEY(MyType, kMyKey, MyDefault);
+//
+// } // foo namespace
+//
+// To define a new type used for ViewProperty.
+//
+// // outside all namespaces:
+// DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(FOO_EXPORT, MyType)
+//
+// If a property type is not exported, use DECLARE_VIEW_PROPERTY_TYPE(MyType)
+// which is a shorthand for DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(, MyType).
+
+namespace mojo {
+namespace {
+
+// No single new-style cast works for every conversion to/from int64, so we
+// need this helper class. A third specialization is needed for bool because
+// MSVC warning C4800 (forcing value to bool) is not suppressed by an explicit
+// cast (!).
+template <typename T>
+class ViewPropertyCaster {
+ public:
+ static int64 ToInt64(T x) { return static_cast<int64>(x); }
+ static T FromInt64(int64 x) { return static_cast<T>(x); }
+};
+template <typename T>
+class ViewPropertyCaster<T*> {
+ public:
+ static int64 ToInt64(T* x) { return reinterpret_cast<int64>(x); }
+ static T* FromInt64(int64 x) { return reinterpret_cast<T*>(x); }
+};
+template <>
+class ViewPropertyCaster<bool> {
+ public:
+ static int64 ToInt64(bool x) { return static_cast<int64>(x); }
+ static bool FromInt64(int64 x) { return x != 0; }
+};
+
+} // namespace
+
+template <typename T>
+struct ViewProperty {
+ T default_value;
+ const char* name;
+ View::PropertyDeallocator deallocator;
+};
+
+template <typename T>
+void View::SetLocalProperty(const ViewProperty<T>* property, T value) {
+ int64 old = SetLocalPropertyInternal(
+ property, property->name,
+ value == property->default_value ? nullptr : property->deallocator,
+ ViewPropertyCaster<T>::ToInt64(value),
+ ViewPropertyCaster<T>::ToInt64(property->default_value));
+ if (property->deallocator &&
+ old != ViewPropertyCaster<T>::ToInt64(property->default_value)) {
+ (*property->deallocator)(old);
+ }
+}
+
+template <typename T>
+T View::GetLocalProperty(const ViewProperty<T>* property) const {
+ return ViewPropertyCaster<T>::FromInt64(GetLocalPropertyInternal(
+ property, ViewPropertyCaster<T>::ToInt64(property->default_value)));
+}
+
+template <typename T>
+void View::ClearLocalProperty(const ViewProperty<T>* property) {
+ SetLocalProperty(property, property->default_value);
+}
+
+} // namespace mojo
+
+// Macros to instantiate the property getter/setter template functions.
+#define DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(EXPORT, T) \
+ template EXPORT void mojo::View::SetLocalProperty( \
+ const mojo::ViewProperty<T>*, T); \
+ template EXPORT T mojo::View::GetLocalProperty(const mojo::ViewProperty<T>*) \
+ const; \
+ template EXPORT void mojo::View::ClearLocalProperty( \
+ const mojo::ViewProperty<T>*);
+#define DECLARE_VIEW_PROPERTY_TYPE(T) DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(, T)
+
+#define DEFINE_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
+ COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64), property_type_too_large); \
+ namespace { \
+ const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \
+ } \
+ const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value;
+
+#define DEFINE_LOCAL_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
+ COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64), property_type_too_large); \
+ namespace { \
+ const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \
+ const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value; \
+ }
+
+#define DEFINE_OWNED_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
+ namespace { \
+ void Deallocator##NAME(int64 p) { \
+ enum { type_must_be_complete = sizeof(TYPE) }; \
+ delete mojo::ViewPropertyCaster<TYPE*>::FromInt64(p); \
+ } \
+ const mojo::ViewProperty<TYPE*> NAME##_Value = {DEFAULT, \
+ #NAME, \
+ &Deallocator##NAME}; \
+ } \
+ const mojo::ViewProperty<TYPE*>* const NAME = &NAME##_Value;
+
+#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_PROPERTY_H_
diff --git a/mojo/services/public/interfaces/view_manager/view_manager.mojom b/mojo/services/public/interfaces/view_manager/view_manager.mojom
index 25e1f06..a79d4c6 100644
--- a/mojo/services/public/interfaces/view_manager/view_manager.mojom
+++ b/mojo/services/public/interfaces/view_manager/view_manager.mojom
@@ -191,7 +191,7 @@
// Invoked when a view property is changed. If this change is a removal,
// |new_data| is null.
- OnViewPropertyChanged(uint32 view, string name, array<uint8>? new_data);
+ OnViewSharedPropertyChanged(uint32 view, string name, array<uint8>? new_data);
// Invoked when an event is targeted at the specified view.
OnViewInputEvent(uint32 view, mojo.Event event) => ();
diff --git a/mojo/services/view_manager/connection_manager.cc b/mojo/services/view_manager/connection_manager.cc
index b671b97..c80c1a3 100644
--- a/mojo/services/view_manager/connection_manager.cc
+++ b/mojo/services/view_manager/connection_manager.cc
@@ -273,7 +273,7 @@
}
}
-void ConnectionManager::OnViewPropertyChanged(
+void ConnectionManager::OnViewSharedPropertyChanged(
const ServerView* view,
const std::string& name,
const std::vector<uint8_t>* new_data) {
diff --git a/mojo/services/view_manager/connection_manager.h b/mojo/services/view_manager/connection_manager.h
index 44e1b76..9f0e9b1 100644
--- a/mojo/services/view_manager/connection_manager.h
+++ b/mojo/services/view_manager/connection_manager.h
@@ -172,9 +172,10 @@
const ServerView* relative,
OrderDirection direction) override;
void OnWillChangeViewVisibility(const ServerView* view) override;
- void OnViewPropertyChanged(const ServerView* view,
- const std::string& name,
- const std::vector<uint8_t>* new_data) override;
+ void OnViewSharedPropertyChanged(
+ const ServerView* view,
+ const std::string& name,
+ const std::vector<uint8_t>* new_data) override;
// WindowManagerInternalClient:
void DispatchInputEventToView(Id transport_view_id,
diff --git a/mojo/services/view_manager/server_view.cc b/mojo/services/view_manager/server_view.cc
index 3bb9e64..937f437 100644
--- a/mojo/services/view_manager/server_view.cc
+++ b/mojo/services/view_manager/server_view.cc
@@ -139,7 +139,7 @@
properties_.erase(it);
}
- delegate_->OnViewPropertyChanged(this, name, value);
+ delegate_->OnViewSharedPropertyChanged(this, name, value);
}
bool ServerView::IsDrawn(const ServerView* root) const {
diff --git a/mojo/services/view_manager/server_view_delegate.h b/mojo/services/view_manager/server_view_delegate.h
index 14f456a..2fbe0c0 100644
--- a/mojo/services/view_manager/server_view_delegate.h
+++ b/mojo/services/view_manager/server_view_delegate.h
@@ -40,9 +40,10 @@
virtual void OnWillChangeViewVisibility(const ServerView* view) = 0;
- virtual void OnViewPropertyChanged(const ServerView* view,
- const std::string& name,
- const std::vector<uint8_t>* new_data) = 0;
+ virtual void OnViewSharedPropertyChanged(
+ const ServerView* view,
+ const std::string& name,
+ const std::vector<uint8_t>* new_data) = 0;
protected:
virtual ~ServerViewDelegate() {}
diff --git a/mojo/services/view_manager/test_change_tracker.cc b/mojo/services/view_manager/test_change_tracker.cc
index 0a3a0c1..4241ecb 100644
--- a/mojo/services/view_manager/test_change_tracker.cc
+++ b/mojo/services/view_manager/test_change_tracker.cc
@@ -249,9 +249,9 @@
AddChange(change);
}
-void TestChangeTracker::OnViewPropertyChanged(Id view_id,
- String name,
- Array<uint8_t> data) {
+void TestChangeTracker::OnViewSharedPropertyChanged(Id view_id,
+ String name,
+ Array<uint8_t> data) {
Change change;
change.type = CHANGE_TYPE_PROPERTY_CHANGED;
change.view_id = view_id;
diff --git a/mojo/services/view_manager/test_change_tracker.h b/mojo/services/view_manager/test_change_tracker.h
index 261c106..368c2ad 100644
--- a/mojo/services/view_manager/test_change_tracker.h
+++ b/mojo/services/view_manager/test_change_tracker.h
@@ -133,9 +133,9 @@
void OnViewVisibilityChanged(Id view_id, bool visible);
void OnViewDrawnStateChanged(Id view_id, bool drawn);
void OnViewInputEvent(Id view_id, EventPtr event);
- void OnViewPropertyChanged(Id view_id,
- String name,
- Array<uint8_t> data);
+ void OnViewSharedPropertyChanged(Id view_id,
+ String name,
+ Array<uint8_t> data);
void DelegateEmbed(const String& url);
private:
diff --git a/mojo/services/view_manager/view_manager_service_apptest.cc b/mojo/services/view_manager/view_manager_service_apptest.cc
index 231aece..b49221b 100644
--- a/mojo/services/view_manager/view_manager_service_apptest.cc
+++ b/mojo/services/view_manager/view_manager_service_apptest.cc
@@ -265,10 +265,10 @@
const Callback<void()>& callback) override {
tracker()->OnViewInputEvent(view_id, event.Pass());
}
- void OnViewPropertyChanged(uint32_t view,
- const String& name,
- Array<uint8_t> new_data) override {
- tracker_.OnViewPropertyChanged(view, name, new_data.Pass());
+ void OnViewSharedPropertyChanged(uint32_t view,
+ const String& name,
+ Array<uint8_t> new_data) override {
+ tracker_.OnViewSharedPropertyChanged(view, name, new_data.Pass());
}
TestChangeTracker tracker_;
diff --git a/mojo/services/view_manager/view_manager_service_impl.cc b/mojo/services/view_manager/view_manager_service_impl.cc
index f7842ad..e205fee 100644
--- a/mojo/services/view_manager/view_manager_service_impl.cc
+++ b/mojo/services/view_manager/view_manager_service_impl.cc
@@ -133,10 +133,8 @@
if (new_data)
data = Array<uint8_t>::From(*new_data);
- client()->OnViewPropertyChanged(
- ViewIdToTransportId(view->id()),
- String(name),
- data.Pass());
+ client()->OnViewSharedPropertyChanged(ViewIdToTransportId(view->id()),
+ String(name), data.Pass());
}
void ViewManagerServiceImpl::ProcessViewHierarchyChanged(
diff --git a/mojo/services/view_manager/view_manager_service_unittest.cc b/mojo/services/view_manager/view_manager_service_unittest.cc
index 92363f1..1079c93 100644
--- a/mojo/services/view_manager/view_manager_service_unittest.cc
+++ b/mojo/services/view_manager/view_manager_service_unittest.cc
@@ -73,10 +73,10 @@
void OnViewDrawnStateChanged(uint32_t view, bool drawn) override {
tracker_.OnViewDrawnStateChanged(view, drawn);
}
- void OnViewPropertyChanged(uint32_t view,
- const String& name,
- Array<uint8_t> new_data) override {
- tracker_.OnViewPropertyChanged(view, name, new_data.Pass());
+ void OnViewSharedPropertyChanged(uint32_t view,
+ const String& name,
+ Array<uint8_t> new_data) override {
+ tracker_.OnViewSharedPropertyChanged(view, name, new_data.Pass());
}
void OnViewInputEvent(uint32_t view,
EventPtr event,
diff --git a/mojo/services/view_manager/view_manager_unittest.cc b/mojo/services/view_manager/view_manager_unittest.cc
index 1deeb22..5aa3715 100644
--- a/mojo/services/view_manager/view_manager_unittest.cc
+++ b/mojo/services/view_manager/view_manager_unittest.cc
@@ -397,10 +397,10 @@
const Callback<void()>& callback) override {
tracker()->OnViewInputEvent(view_id, event.Pass());
}
- void OnViewPropertyChanged(uint32_t view,
- const String& name,
- Array<uint8_t> new_data) override {
- tracker_.OnViewPropertyChanged(view, name, new_data.Pass());
+ void OnViewSharedPropertyChanged(uint32_t view,
+ const String& name,
+ Array<uint8_t> new_data) override {
+ tracker_.OnViewSharedPropertyChanged(view, name, new_data.Pass());
}
private: