GitHub PullRequestReviewCommentEvent at 2014-12-10 10:01:18
Repository: crosswalk
Actor: pozdnyakov
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/comments/21593711","id":21593711,"diff_hunk":"@@ -0,0 +1,882 @@\n+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved\n+// Use of this source code is governed by a BSD-style license that can be\n+// found in the LICENSE file.\n+\n+#include <map>\n+#include <string>\n+#include <vector>\n+#include \"base/memory/ref_counted.h\"\n+#include \"base/strings/string_number_conversions.h\"\n+#include \"base/strings/string_split.h\"\n+#include \"base/values.h\"\n+#include \"testing/gtest/include/gtest/gtest.h\"\n+#include \"xwalk/application/common/application_manifest_constants.h\"\n+#include \"xwalk/application/common/manifest.h\"\n+#include \"xwalk/application/common/manifest_handlers/tizen_appwidget_handler.h\"\n+#include \"xwalk/application/common/manifest_handlers/unittest_util.h\"\n+\n+namespace xwalk {\n+\n+namespace keys = application_widget_keys;\n+\n+namespace application {\n+\n+namespace {\n+\n+// Extracts app-widget info object from application data object.\n+const TizenAppWidgetInfo* GetInfo(scoped_refptr<ApplicationData> application) {\n+  const TizenAppWidgetInfo* info = static_cast<TizenAppWidgetInfo*>(\n+      application->GetManifestData(keys::kTizenAppWidgetFullKey));\n+  return info;\n+}\n+\n+// In specified dictionary sets a specified value under a specified key.\n+// The value is set only if it is not empty. If key is empty or dictionary\n+// is null, it does nothing.\n+void SetString(const std::string& key, const std::string& value,\n+    base::DictionaryValue* dictionary) {\n+  if (dictionary && !key.empty() && !value.empty())\n+    dictionary->SetString(key, value);\n+}\n+\n+// Creates a dictionary with namespace set to tizen.\n+scoped_ptr<base::DictionaryValue> CreateTizenElement() {\n+  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);\n+  SetString(keys::kNamespaceKey, keys::kTizenNamespacePrefix, result.get());\n+  return result.Pass();\n+}\n+\n+// Creates a dictionary representing an app-widget element.\n+scoped_ptr<base::DictionaryValue> CreateAppWidget(\n+    const std::string& id, const std::string& primary,\n+    const std::string& update_peroid = \"\",\n+    const std::string& auto_launch = \"\") {\n+  scoped_ptr<base::DictionaryValue> result = CreateTizenElement();\n+  SetString(keys::kTizenAppWidgetIdKey, id, result.get());\n+  SetString(keys::kTizenAppWidgetPrimaryKey, primary, result.get());\n+  SetString(keys::kTizenAppWidgetUpdatePeriodKey, update_peroid, result.get());\n+  SetString(keys::kTizenAppWidgetAutoLaunchKey, auto_launch, result.get());\n+  return result.Pass();\n+}\n+\n+// Creates a dictionary representing a box-label element.\n+scoped_ptr<base::DictionaryValue> CreateBoxLabel(\n+    const std::string& label, const std::string& lang = \"\") {\n+  scoped_ptr<base::DictionaryValue> result = CreateTizenElement();\n+  SetString(keys::kTizenAppWidgetBoxLabelTextKey, label, result.get());\n+  SetString(keys::kTizenAppWidgetBoxLabelLangKey, lang, result.get());\n+  return result.Pass();\n+}\n+\n+// Creates a dictionary representing a box-icon element.\n+scoped_ptr<base::DictionaryValue> CreateBoxIcon(\n+    const std::string& src) {\n+  scoped_ptr<base::DictionaryValue> result = CreateTizenElement();\n+  SetString(keys::kTizenAppWidgetBoxIconSrcKey, src, result.get());\n+  return result.Pass();\n+}\n+\n+// Creates a dictionary representing a box-content element.\n+scoped_ptr<base::DictionaryValue> CreateBoxContent(\n+    const std::string& src, const std::string& mouse_event = \"\",\n+    const std::string& touch_effect = \"\") {\n+  scoped_ptr<base::DictionaryValue> result = CreateTizenElement();\n+  SetString(keys::kTizenAppWidgetBoxContentSrcKey, src,\n+            result.get());\n+  SetString(keys::kTizenAppWidgetBoxContentMouseEventKey, mouse_event,\n+            result.get());\n+  SetString(keys::kTizenAppWidgetBoxContentTouchEffectKey, touch_effect,\n+            result.get());\n+  return result.Pass();\n+}\n+\n+// Creates a dictionary representing a box-size element.\n+scoped_ptr<base::DictionaryValue> CreateBoxSize(\n+    const std::string& type, const std::string& preview = \"\",\n+    const std::string& use_decoration = \"\") {\n+  scoped_ptr<base::DictionaryValue> result = CreateTizenElement();\n+  SetString(keys::kTizenAppWidgetBoxContentSizeTextKey, type,\n+            result.get());\n+  SetString(keys::kTizenAppWidgetBoxContentSizePreviewKey, preview,\n+            result.get());\n+  SetString(keys::kTizenAppWidgetBoxContentSizeUseDecorationKey, use_decoration,\n+            result.get());\n+  return result.Pass();\n+}\n+\n+// Creates a dictionary representing a pd element.\n+scoped_ptr<base::DictionaryValue> CreateBoxDropView(\n+    const std::string& src, const std::string& width,\n+    const std::string& height) {\n+  scoped_ptr<base::DictionaryValue> result = CreateTizenElement();\n+  SetString(keys::kTizenAppWidgetBoxContentDropViewSrcKey, src,\n+            result.get());\n+  SetString(keys::kTizenAppWidgetBoxContentDropViewWidthKey, width,\n+            result.get());\n+  SetString(keys::kTizenAppWidgetBoxContentDropViewHeightKey, height,\n+            result.get());\n+  return result.Pass();\n+}\n+\n+// Creates an app-widget element id basing on values of default package id\n+// and default application name.\n+std::string CreateAppWidgetId(const std::string& name) {\n+  std::vector<std::string> parts;\n+  parts.push_back(kDefaultWidgetPackageId);\n+  parts.push_back(kDefaultWidgetApplicationName);\n+  parts.push_back(name);\n+  return JoinString(parts, '.');\n+}\n+\n+// Creates a dictionary representing an app-widget element with all required\n+// fields and child elements set.\n+scoped_ptr<base::DictionaryValue> CreateMinimalAppWidget(\n+    const std::string& name, const std::string& primary) {\n+  std::string id = CreateAppWidgetId(name);\n+\n+  scoped_ptr<base::DictionaryValue> result = CreateAppWidget(id, primary);\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxLabelKey,\n+      CreateBoxLabel(\"sample label\"), result.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  scoped_ptr<base::DictionaryValue> box_content =\n+      CreateBoxContent(\"index.html\");\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxContentSizeKey,\n+      CreateBoxSize(\"1x1\"), box_content.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxContentKey,\n+      box_content.Pass(), result.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  return result.Pass();\n+}\n+\n+// Creates a dictionary representing an app-widget element with all fields and\n+// child elements set. Each optional field is set to something different than\n+// its default value if specified.\n+scoped_ptr<base::DictionaryValue> CreateFullAppWidget(\n+    const std::string& name, const std::string& primary) {\n+  std::string id = CreateAppWidgetId(name);\n+\n+  scoped_ptr<base::DictionaryValue> result =\n+      CreateAppWidget(id, primary, \"1800.0\", \"true\");\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxLabelKey,\n+      CreateBoxLabel(\"sample label\"), result.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxLabelKey,\n+      CreateBoxLabel(\"sample en label\", \"en\"), result.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxIconKey,\n+      CreateBoxIcon(\"icon.png\"), result.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  scoped_ptr<base::DictionaryValue> box_content =\n+      CreateBoxContent(\"index.html\", \"true\", \"false\");\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxContentSizeKey,\n+      CreateBoxSize(\"1x1\"), box_content.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxContentSizeKey,\n+      CreateBoxSize(\"2x1\", \"image.png\"), box_content.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxContentSizeKey,\n+      CreateBoxSize(\"2x2\", \"\", \"false\"), box_content.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxContentDropViewKey,\n+      CreateBoxDropView(\"index.html\", \"720\", \"150\"), box_content.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  if (!AddDictionary(keys::kTizenAppWidgetBoxContentKey,\n+      box_content.Pass(), result.get()))\n+    return scoped_ptr<base::DictionaryValue>();\n+\n+  return result.Pass();\n+}\n+\n+// Tests wheter specified value type is a dictionary or a list.\n+bool IsComplexValueType(base::Value::Type type) {\n+  return type == base::Value::TYPE_DICTIONARY || type == base::Value::TYPE_LIST;\n+}\n+\n+// Searches for a child value specified by name in specified root value and\n+// if the child is found, fills child and parent arguments with the found child\n+// and its parent. Both parent and child arguments are optional.\n+bool GetParentAndChild(const std::string& name, base::Value* root,\n+    base::DictionaryValue** parent, base::Value** child) {\n+  if (name.empty() || !root)\n+    return false;\n+\n+  base::DictionaryValue* tmp_parent = nullptr;\n+  if (!root->GetAsDictionary(&tmp_parent))\n+    return false;\n+\n+  base::Value* tmp_child;\n+  if (!tmp_parent->Get(name, &tmp_child))\n+    return false;\n+\n+  if (parent)\n+    *parent = tmp_parent;\n+  if (child)\n+    *child = tmp_child;\n+\n+  return true;\n+}\n+\n+// Searches for a child value specified by name and index in specified root\n+// value and if the child is found, fills child and parent arguments with\n+// the found child and its parent. Both parent and child arguments are optional.\n+bool GetParentAndChild(const std::string& name, size_t index,\n+    base::Value* root, base::ListValue** parent, base::Value** child) {\n+  if (name.empty() || !root)\n+    return false;\n+\n+  base::Value* first_level_child;\n+  if (!GetParentAndChild(name, root, nullptr, &first_level_child))\n+    return false;\n+\n+  base::ListValue* tmp_parent = nullptr;\n+  if (!first_level_child->GetAsList(&tmp_parent))\n+    return false;\n+\n+  base::Value* tmp_child;\n+  if (!tmp_parent->Get(index, &tmp_child))\n+    return false;\n+\n+  if (parent)\n+    *parent = tmp_parent;\n+  if (child)\n+    *child = tmp_child;\n+\n+  return true;\n+}\n+\n+// If the value argument is nullptr, the function removes the value specified by\n+// path, otherwise it changes the value specified by path to the value argument.\n+bool ChangeOrRemove(const std::string& path, base::Value * root,\n+    const std::string* value = nullptr) {\n+  if (path.empty() || !root)\n+    return false;\n+\n+  base::Value* current = root;\n+\n+  std::vector<std::string> parts;\n+  base::SplitString(path, '.', &parts);\n+  for (size_t i = 0, count = parts.size(); i < count; ++i) {\n+    const std::string& part = parts[i];\n+\n+    std::vector<std::string> name_and_index;\n+    base::SplitString(part, ':', &name_and_index);\n+    if (name_and_index.size() == 1) {  // current part refers to a dictionary\n+      std::string name = name_and_index[0];\n+\n+      base::DictionaryValue* parent;\n+      base::Value* child;\n+      if (!GetParentAndChild(name, current, &parent, &child))\n+        return false;\n+\n+      if (i == count - 1) {\n+        if (value) {\n+          if (IsComplexValueType(child->GetType()))\n+            return false;\n+          parent->SetString(name, *value);\n+          return true;\n+        }\n+        return parent->Remove(name, nullptr);\n+      }\n+\n+      current = child;\n+    } else if (name_and_index.size() == 2) {  // current part refers to a list\n+      std::string name = name_and_index[0];\n+      unsigned index;\n+      if (!base::StringToUint(name_and_index[1], &index))\n+        return false;  // invalid path\n+\n+      base::ListValue* parent;\n+      base::Value* child;\n+      if (!GetParentAndChild(name, index, current, &parent, &child))\n+        return false;\n+\n+      if (i == count - 1) {\n+        if (value) {\n+          if (IsComplexValueType(child->GetType()))\n+            return false;\n+          parent->Set(index, new base::StringValue(*value));\n+          return true;\n+        }\n+        return parent->Remove(index, nullptr);\n+      }\n+\n+      current = child;\n+    } else {  // current part is invalid\n+      return false;\n+    }\n+  }\n+\n+  return current;\n+}\n+\n+// Creates a key representing a list value item. For example \"box-size:2\".\n+std::string MakeListItemKey(const std::string& name, size_t index) {\n+  return name + ':' + base::UintToString(index);\n+}\n+\n+// Makes a path to widget.app-widget.element.\n+std::string MakeAppWidgetPath(const std::string& element) {\n+  return MakeElementPath(keys::kTizenAppWidgetFullKey, element);\n+}\n+\n+// Makes a path to widget.app-widget.box-label:index.element.\n+std::string MakeBoxLabelPath(size_t index, const std::string& element) {\n+  const std::string key = keys::kTizenAppWidgetBoxLabelKey;\n+  const std::string label = MakeListItemKey(key, index);\n+  return MakeElementPath(MakeAppWidgetPath(label), element);\n+}\n+\n+// Makes a path to widget.app-widget.box-icon.element.\n+std::string MakeBoxIconPath(const std::string& element) {\n+  const std::string key = keys::kTizenAppWidgetBoxIconKey;\n+  return MakeElementPath(MakeAppWidgetPath(key), element);\n+}\n+\n+// Makes a path to widget.app-widget.box-content.element.\n+std::string MakeBoxContentPath(const std::string& element) {\n+  const std::string key = keys::kTizenAppWidgetBoxContentKey;\n+  return MakeElementPath(MakeAppWidgetPath(key), element);\n+}\n+\n+// Makes a path to widget.app-widget.box-content.box-size:index.element.\n+std::string MakeSizePath(size_t index, const std::string& element) {\n+  const std::string key = keys::kTizenAppWidgetBoxContentSizeKey;\n+  const std::string size = MakeListItemKey(key, index);\n+  return MakeElementPath(MakeBoxContentPath(size), element);\n+}\n+\n+// Makes a path to widget.app-widget.box-content.pd.element.\n+std::string MakeDropViewPath(const std::string& element) {\n+  const std::string key = keys::kTizenAppWidgetBoxContentDropViewKey;\n+  return MakeElementPath(MakeBoxContentPath(key), element);\n+}\n+\n+}  // namespace\n+\n+class TizenAppWidgetHandlerTest: public testing::Test {\n+ public:\n+  void ChangedOrRemovedFieldTest(const std::string& path,\n+                                 const std::string* value = nullptr) {\n+    scoped_ptr<base::DictionaryValue> manifest = CreateDefaultWidgetConfig();\n+\n+    scoped_ptr<base::DictionaryValue> app_widget =\n+        CreateFullAppWidget(\"first\", \"true\");\n+    EXPECT_NE(nullptr, app_widget.get());\n+\n+    EXPECT_TRUE(AddDictionary(keys::kTizenAppWidgetFullKey,\n+        app_widget.Pass(), manifest.get()));\n+\n+    EXPECT_TRUE(ChangeOrRemove(path, manifest.get(), value));\n+\n+    scoped_refptr<ApplicationData> application =\n+        CreateApplication(Manifest::TYPE_WIDGET, *manifest);\n+    EXPECT_FALSE(application.get());\n+  }\n+\n+  // Defines a test in which a field specified by path is removed from\n+  // manifest created by CreateDefaultWidgetConfig and complemented by\n+  // app-widget element created by CreateFullAppWidget.\n+  // Can be used when path is precise (there is no dictionary list in the way).\n+  void MissingFieldTest(const std::string& path) {\n+    ChangedOrRemovedFieldTest(path);\n+  }\n+\n+  // Defines a test in which a field specified by path is changed in\n+  // manifest created by CreateDefaultWidgetConfig and complemented by\n+  // app-widget element created by CreateFullAppWidget.\n+  // Can be used when path is precise (there is no dictionary list in the way).\n+  void InvalidFieldValueTest(const std::string& path,\n+                             const std::string& value) {\n+    ChangedOrRemovedFieldTest(path, &value);\n+  }\n+};\n+\n+// Test case for no app-widget element.\n+TEST_F(TizenAppWidgetHandlerTest, NoAppWidget) {\n+  scoped_ptr<base::DictionaryValue> manifest = CreateDefaultWidgetConfig();\n+\n+  scoped_refptr<ApplicationData> application =\n+      CreateApplication(Manifest::TYPE_WIDGET, *manifest);\n+  EXPECT_TRUE(application.get());\n+  EXPECT_EQ(Manifest::TYPE_WIDGET, application->GetManifest()->type());\n+\n+  const TizenAppWidgetInfo* info = GetInfo(application);\n+  EXPECT_FALSE(info);\n+}\n+\n+// Test case for one app-widget element with only required attributes and child\n+// elements set.\n+TEST_F(TizenAppWidgetHandlerTest, OneMinimalAppWidget) {\n+  scoped_ptr<base::DictionaryValue> manifest = CreateDefaultWidgetConfig();\n+\n+  scoped_ptr<base::DictionaryValue> app_widget =\n+      CreateMinimalAppWidget(\"first\", \"true\");\n+  EXPECT_NE(nullptr, app_widget.get());\n+\n+  EXPECT_TRUE(AddDictionary(keys::kTizenAppWidgetFullKey,\n+      app_widget.Pass(), manifest.get()));\n+\n+  scoped_refptr<ApplicationData> application =\n+      CreateApplication(Manifest::TYPE_WIDGET, *manifest);\n+  EXPECT_TRUE(application.get());\n+  EXPECT_EQ(Manifest::TYPE_WIDGET, application->GetManifest()->type());\n+\n+  const TizenAppWidgetInfo* info = GetInfo(application);\n+  EXPECT_TRUE(info);\n+\n+  const TizenAppWidgetVector& app_widgets = info->app_widgets();\n+  EXPECT_EQ(1, app_widgets.size());\n+\n+  const TizenAppWidget& element = app_widgets[0];\n+\n+  std::vector<std::string> id_parts;\n+  base::SplitString(element.id, '.', &id_parts);\n+  EXPECT_EQ(3, id_parts.size());\n+  EXPECT_STREQ(\"first\", id_parts[2].c_str());\n+  EXPECT_TRUE(element.primary);\n+  EXPECT_EQ(0, element.update_period.size());\n+  EXPECT_FALSE(element.auto_launch);\n+  EXPECT_STREQ(\"sample label\", element.label.default_value.c_str());\n+  EXPECT_EQ(0, element.label.lang_value_map.size());\n+  EXPECT_STREQ(\"\", element.icon_src.c_str());\n+  EXPECT_STREQ(\"index.html\", element.content_src.c_str());\n+  EXPECT_FALSE(element.content_mouse_event);\n+  EXPECT_TRUE(element.content_touch_effect);\n+  EXPECT_EQ(1, element.content_size.size());\n+  EXPECT_EQ(TizenAppWidgetSizeType::k1x1, element.content_size[0].type);\n+  EXPECT_STREQ(\"\", element.content_size[0].preview.c_str());\n+  EXPECT_TRUE(element.content_size[0].use_decoration);\n+  EXPECT_EQ(0, element.content_drop_view.size());\n+}\n+\n+// Test case for two app-widget elements with only required attributes and child\n+// elements set.\n+TEST_F(TizenAppWidgetHandlerTest, TwoMinimalAppWidgets) {\n+  scoped_ptr<base::DictionaryValue> manifest = CreateDefaultWidgetConfig();\n+\n+  scoped_ptr<base::DictionaryValue> app_widget =\n+      CreateMinimalAppWidget(\"first\", \"true\");\n+  EXPECT_NE(nullptr, app_widget.get());\n+\n+  EXPECT_TRUE(AddDictionary(keys::kTizenAppWidgetFullKey,\n+      app_widget.Pass(), manifest.get()));\n+\n+  app_widget = CreateMinimalAppWidget(\"second\", \"false\");\n+  EXPECT_NE(nullptr, app_widget.get());\n+\n+  EXPECT_TRUE(AddDictionary(keys::kTizenAppWidgetFullKey,\n+      app_widget.Pass(), manifest.get()));\n+\n+  scoped_refptr<ApplicationData> application =\n+      CreateApplication(Manifest::TYPE_WIDGET, *manifest);\n+  EXPECT_TRUE(application.get());\n+  EXPECT_EQ(Manifest::TYPE_WIDGET, application->GetManifest()->type());\n+\n+  const TizenAppWidgetInfo* info = GetInfo(application);\n+  EXPECT_TRUE(info);","path":"application/common/manifest_handlers/tizen_appwidget_handler_unittest.cc","position":491,"original_position":491,"commit_id":"f4bbe92c1817b83a737e8a0f946e01e759dfd5e7","original_commit_id":"f4bbe92c1817b83a737e8a0f946e01e759dfd5e7","user":{"login":"pozdnyakov","id":998253,"avatar_url":"https://avatars.githubusercontent.com/u/998253?v=3","gravatar_id":"","url":"https://api.github.com/users/pozdnyakov","html_url":"https://github.com/pozdnyakov","followers_url":"https://api.github.com/users/pozdnyakov/followers","following_url":"https://api.github.com/users/pozdnyakov/following{/other_user}","gists_url":"https://api.github.com/users/pozdnyakov/gists{/gist_id}","starred_url":"https://api.github.com/users/pozdnyakov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pozdnyakov/subscriptions","organizations_url":"https://api.github.com/users/pozdnyakov/orgs","repos_url":"https://api.github.com/users/pozdnyakov/repos","events_url":"https://api.github.com/users/pozdnyakov/events{/privacy}","received_events_url":"https://api.github.com/users/pozdnyakov/received_events","type":"User","site_admin":false},"body":"info != nullptr","created_at":"2014-12-10T10:01:18Z","updated_at":"2014-12-10T10:01:18Z","html_url":"https://github.com/crosswalk-project/crosswalk/pull/2702#discussion_r21593711","pull_request_url":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702","_links":{"self":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/comments/21593711"},"html":{"href":"https://github.com/crosswalk-project/crosswalk/pull/2702#discussion_r21593711"},"pull_request":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702"}}},"pull_request":{"url":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702","id":25564524,"html_url":"https://github.com/crosswalk-project/crosswalk/pull/2702","diff_url":"https://github.com/crosswalk-project/crosswalk/pull/2702.diff","patch_url":"https://github.com/crosswalk-project/crosswalk/pull/2702.patch","issue_url":"https://api.github.com/repos/crosswalk-project/crosswalk/issues/2702","number":2702,"state":"open","locked":false,"title":"[Tizen] Add unit test for app-widget configuration element handler","user":{"login":"tweglarski","id":8805561,"avatar_url":"https://avatars.githubusercontent.com/u/8805561?v=3","gravatar_id":"","url":"https://api.github.com/users/tweglarski","html_url":"https://github.com/tweglarski","followers_url":"https://api.github.com/users/tweglarski/followers","following_url":"https://api.github.com/users/tweglarski/following{/other_user}","gists_url":"https://api.github.com/users/tweglarski/gists{/gist_id}","starred_url":"https://api.github.com/users/tweglarski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tweglarski/subscriptions","organizations_url":"https://api.github.com/users/tweglarski/orgs","repos_url":"https://api.github.com/users/tweglarski/repos","events_url":"https://api.github.com/users/tweglarski/events{/privacy}","received_events_url":"https://api.github.com/users/tweglarski/received_events","type":"User","site_admin":false},"body":"This patch adds tizen_appwidget_handler_unittest.cc. New tests verify\r\nthat the handler properly handles the following configuration elements:\r\n\r\nwidget.app-widget @id @primary @update-period @auto-launch\r\nwidget.app-widget.box-label @lang #text\r\nwidget.app-widget.box-icon @src\r\nwidget.app-widget.box-content @src @mouse-event @touch-effect\r\nwidget.app-widget.box-content.box-size @preview @use-decoration #text\r\nwidget.app-widget.box-content.pd @src @width @height\r\n\r\nBUG=XWALK-1515, XWALK-1516","created_at":"2014-12-05T11:27:55Z","updated_at":"2014-12-10T10:01:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0e14a694cf2e33e6fef7d1a6036db1d9bf82f55c","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702/commits","review_comments_url":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702/comments","review_comment_url":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/comments/{number}","comments_url":"https://api.github.com/repos/crosswalk-project/crosswalk/issues/2702/comments","statuses_url":"https://api.github.com/repos/crosswalk-project/crosswalk/statuses/f4bbe92c1817b83a737e8a0f946e01e759dfd5e7","head":{"label":"tweglarski:AppWidgetUnitTest","ref":"AppWidgetUnitTest","sha":"f4bbe92c1817b83a737e8a0f946e01e759dfd5e7","user":{"login":"tweglarski","id":8805561,"avatar_url":"https://avatars.githubusercontent.com/u/8805561?v=3","gravatar_id":"","url":"https://api.github.com/users/tweglarski","html_url":"https://github.com/tweglarski","followers_url":"https://api.github.com/users/tweglarski/followers","following_url":"https://api.github.com/users/tweglarski/following{/other_user}","gists_url":"https://api.github.com/users/tweglarski/gists{/gist_id}","starred_url":"https://api.github.com/users/tweglarski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tweglarski/subscriptions","organizations_url":"https://api.github.com/users/tweglarski/orgs","repos_url":"https://api.github.com/users/tweglarski/repos","events_url":"https://api.github.com/users/tweglarski/events{/privacy}","received_events_url":"https://api.github.com/users/tweglarski/received_events","type":"User","site_admin":false},"repo":{"id":24841655,"name":"crosswalk","full_name":"tweglarski/crosswalk","owner":{"login":"tweglarski","id":8805561,"avatar_url":"https://avatars.githubusercontent.com/u/8805561?v=3","gravatar_id":"","url":"https://api.github.com/users/tweglarski","html_url":"https://github.com/tweglarski","followers_url":"https://api.github.com/users/tweglarski/followers","following_url":"https://api.github.com/users/tweglarski/following{/other_user}","gists_url":"https://api.github.com/users/tweglarski/gists{/gist_id}","starred_url":"https://api.github.com/users/tweglarski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tweglarski/subscriptions","organizations_url":"https://api.github.com/users/tweglarski/orgs","repos_url":"https://api.github.com/users/tweglarski/repos","events_url":"https://api.github.com/users/tweglarski/events{/privacy}","received_events_url":"https://api.github.com/users/tweglarski/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tweglarski/crosswalk","description":"","fork":true,"url":"https://api.github.com/repos/tweglarski/crosswalk","forks_url":"https://api.github.com/repos/tweglarski/crosswalk/forks","keys_url":"https://api.github.com/repos/tweglarski/crosswalk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tweglarski/crosswalk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tweglarski/crosswalk/teams","hooks_url":"https://api.github.com/repos/tweglarski/crosswalk/hooks","issue_events_url":"https://api.github.com/repos/tweglarski/crosswalk/issues/events{/number}","events_url":"https://api.github.com/repos/tweglarski/crosswalk/events","assignees_url":"https://api.github.com/repos/tweglarski/crosswalk/assignees{/user}","branches_url":"https://api.github.com/repos/tweglarski/crosswalk/branches{/branch}","tags_url":"https://api.github.com/repos/tweglarski/crosswalk/tags","blobs_url":"https://api.github.com/repos/tweglarski/crosswalk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tweglarski/crosswalk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tweglarski/crosswalk/git/refs{/sha}","trees_url":"https://api.github.com/repos/tweglarski/crosswalk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tweglarski/crosswalk/statuses/{sha}","languages_url":"https://api.github.com/repos/tweglarski/crosswalk/languages","stargazers_url":"https://api.github.com/repos/tweglarski/crosswalk/stargazers","contributors_url":"https://api.github.com/repos/tweglarski/crosswalk/contributors","subscribers_url":"https://api.github.com/repos/tweglarski/crosswalk/subscribers","subscription_url":"https://api.github.com/repos/tweglarski/crosswalk/subscription","commits_url":"https://api.github.com/repos/tweglarski/crosswalk/commits{/sha}","git_commits_url":"https://api.github.com/repos/tweglarski/crosswalk/git/commits{/sha}","comments_url":"https://api.github.com/repos/tweglarski/crosswalk/comments{/number}","issue_comment_url":"https://api.github.com/repos/tweglarski/crosswalk/issues/comments/{number}","contents_url":"https://api.github.com/repos/tweglarski/crosswalk/contents/{+path}","compare_url":"https://api.github.com/repos/tweglarski/crosswalk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tweglarski/crosswalk/merges","archive_url":"https://api.github.com/repos/tweglarski/crosswalk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tweglarski/crosswalk/downloads","issues_url":"https://api.github.com/repos/tweglarski/crosswalk/issues{/number}","pulls_url":"https://api.github.com/repos/tweglarski/crosswalk/pulls{/number}","milestones_url":"https://api.github.com/repos/tweglarski/crosswalk/milestones{/number}","notifications_url":"https://api.github.com/repos/tweglarski/crosswalk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tweglarski/crosswalk/labels{/name}","releases_url":"https://api.github.com/repos/tweglarski/crosswalk/releases{/id}","created_at":"2014-10-06T10:25:23Z","updated_at":"2014-12-05T11:20:05Z","pushed_at":"2014-12-10T09:01:46Z","git_url":"git://github.com/tweglarski/crosswalk.git","ssh_url":"git@github.com:tweglarski/crosswalk.git","clone_url":"https://github.com/tweglarski/crosswalk.git","svn_url":"https://github.com/tweglarski/crosswalk","homepage":"https://crosswalk-project.org/","size":11686,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"crosswalk-project:master","ref":"master","sha":"dc68f76ddac6067a50ba22c902aa76b50dcb8aac","user":{"login":"crosswalk-project","id":4867377,"avatar_url":"https://avatars.githubusercontent.com/u/4867377?v=3","gravatar_id":"","url":"https://api.github.com/users/crosswalk-project","html_url":"https://github.com/crosswalk-project","followers_url":"https://api.github.com/users/crosswalk-project/followers","following_url":"https://api.github.com/users/crosswalk-project/following{/other_user}","gists_url":"https://api.github.com/users/crosswalk-project/gists{/gist_id}","starred_url":"https://api.github.com/users/crosswalk-project/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crosswalk-project/subscriptions","organizations_url":"https://api.github.com/users/crosswalk-project/orgs","repos_url":"https://api.github.com/users/crosswalk-project/repos","events_url":"https://api.github.com/users/crosswalk-project/events{/privacy}","received_events_url":"https://api.github.com/users/crosswalk-project/received_events","type":"Organization","site_admin":false},"repo":{"id":9207280,"name":"crosswalk","full_name":"crosswalk-project/crosswalk","owner":{"login":"crosswalk-project","id":4867377,"avatar_url":"https://avatars.githubusercontent.com/u/4867377?v=3","gravatar_id":"","url":"https://api.github.com/users/crosswalk-project","html_url":"https://github.com/crosswalk-project","followers_url":"https://api.github.com/users/crosswalk-project/followers","following_url":"https://api.github.com/users/crosswalk-project/following{/other_user}","gists_url":"https://api.github.com/users/crosswalk-project/gists{/gist_id}","starred_url":"https://api.github.com/users/crosswalk-project/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crosswalk-project/subscriptions","organizations_url":"https://api.github.com/users/crosswalk-project/orgs","repos_url":"https://api.github.com/users/crosswalk-project/repos","events_url":"https://api.github.com/users/crosswalk-project/events{/privacy}","received_events_url":"https://api.github.com/users/crosswalk-project/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/crosswalk-project/crosswalk","description":"","fork":false,"url":"https://api.github.com/repos/crosswalk-project/crosswalk","forks_url":"https://api.github.com/repos/crosswalk-project/crosswalk/forks","keys_url":"https://api.github.com/repos/crosswalk-project/crosswalk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/crosswalk-project/crosswalk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/crosswalk-project/crosswalk/teams","hooks_url":"https://api.github.com/repos/crosswalk-project/crosswalk/hooks","issue_events_url":"https://api.github.com/repos/crosswalk-project/crosswalk/issues/events{/number}","events_url":"https://api.github.com/repos/crosswalk-project/crosswalk/events","assignees_url":"https://api.github.com/repos/crosswalk-project/crosswalk/assignees{/user}","branches_url":"https://api.github.com/repos/crosswalk-project/crosswalk/branches{/branch}","tags_url":"https://api.github.com/repos/crosswalk-project/crosswalk/tags","blobs_url":"https://api.github.com/repos/crosswalk-project/crosswalk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/crosswalk-project/crosswalk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/crosswalk-project/crosswalk/git/refs{/sha}","trees_url":"https://api.github.com/repos/crosswalk-project/crosswalk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/crosswalk-project/crosswalk/statuses/{sha}","languages_url":"https://api.github.com/repos/crosswalk-project/crosswalk/languages","stargazers_url":"https://api.github.com/repos/crosswalk-project/crosswalk/stargazers","contributors_url":"https://api.github.com/repos/crosswalk-project/crosswalk/contributors","subscribers_url":"https://api.github.com/repos/crosswalk-project/crosswalk/subscribers","subscription_url":"https://api.github.com/repos/crosswalk-project/crosswalk/subscription","commits_url":"https://api.github.com/repos/crosswalk-project/crosswalk/commits{/sha}","git_commits_url":"https://api.github.com/repos/crosswalk-project/crosswalk/git/commits{/sha}","comments_url":"https://api.github.com/repos/crosswalk-project/crosswalk/comments{/number}","issue_comment_url":"https://api.github.com/repos/crosswalk-project/crosswalk/issues/comments/{number}","contents_url":"https://api.github.com/repos/crosswalk-project/crosswalk/contents/{+path}","compare_url":"https://api.github.com/repos/crosswalk-project/crosswalk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/crosswalk-project/crosswalk/merges","archive_url":"https://api.github.com/repos/crosswalk-project/crosswalk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/crosswalk-project/crosswalk/downloads","issues_url":"https://api.github.com/repos/crosswalk-project/crosswalk/issues{/number}","pulls_url":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls{/number}","milestones_url":"https://api.github.com/repos/crosswalk-project/crosswalk/milestones{/number}","notifications_url":"https://api.github.com/repos/crosswalk-project/crosswalk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/crosswalk-project/crosswalk/labels{/name}","releases_url":"https://api.github.com/repos/crosswalk-project/crosswalk/releases{/id}","created_at":"2013-04-03T23:30:12Z","updated_at":"2014-12-10T09:50:29Z","pushed_at":"2014-12-10T09:50:27Z","git_url":"git://github.com/crosswalk-project/crosswalk.git","ssh_url":"git@github.com:crosswalk-project/crosswalk.git","clone_url":"https://github.com/crosswalk-project/crosswalk.git","svn_url":"https://github.com/crosswalk-project/crosswalk","homepage":"https://crosswalk-project.org/","size":143467,"stargazers_count":490,"watchers_count":490,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":180,"mirror_url":null,"open_issues_count":110,"forks":180,"open_issues":110,"watchers":490,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702"},"html":{"href":"https://github.com/crosswalk-project/crosswalk/pull/2702"},"issue":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/issues/2702"},"comments":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/issues/2702/comments"},"review_comments":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702/comments"},"review_comment":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/pulls/2702/commits"},"statuses":{"href":"https://api.github.com/repos/crosswalk-project/crosswalk/statuses/f4bbe92c1817b83a737e8a0f946e01e759dfd5e7"}}}}