Support security origin for W3C filesystem API
authorJihoon Chung <jihoon.chung@samsung.com>
Fri, 12 Oct 2012 00:51:30 +0000 (09:51 +0900)
committerJihoon Chung <jihoon.chung@samsung.com>
Fri, 23 Nov 2012 12:10:55 +0000 (21:10 +0900)
[Issue#] N/A
[Problem] Support security origin for file API
[Cause] N/A
[Solution] Implement security origin stored database after user
makes decision on the asking popup
[SCMRequest] N/A
This commit needs https://tizendev.org/gerrit/#/c/14079/2

Change-Id: I14968d51ab4df8fde53473c30b103969b215b38c

data/Daemon.edc
src/view/webkit/CMakeLists.txt
src/view/webkit/view_logic.cpp
src/view/webkit/view_logic.h
src/view/webkit/view_logic_filesystem_support.cpp [new file with mode: 0644]
src/view/webkit/view_logic_filesystem_support.h [new file with mode: 0644]

index 817d883..23dd6b7 100644 (file)
@@ -164,4 +164,140 @@ collections {
             }
         }//end of programs
     }//end of group
+
+    group {
+        name: "popupWithCheck";
+        parts {
+            part {
+                name: "pad_t";
+                scale : 1;
+                mouse_events: 0;
+                repeat_events: 1;
+                description {
+                    state: "default" 0.0;
+                    align: 0.5 0.0;
+                    min: 0 22;
+                    fixed: 0 1;
+                    rel1 {
+                        relative: 1.0 0.0;to_x: "pad_l";
+                    }
+                    rel2 {
+                        relative: 0.0 0.0;to_x: "pad_r";
+                    }
+                }
+            }
+            part {
+                name: "pad_l";
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min : 16 0;
+                    fixed: 1 0;
+                    rel1 {
+                        relative: 0.0 0.0;
+                    }
+                    rel2 {
+                        relative: 0.0 1.0;
+                    }
+                    align: 0.0 0.0;
+                }
+            }
+            part {
+                name: "pad_r";
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min : 16 0;
+                    fixed: 1 0;
+                    rel1 {
+                        relative: 1.0 0.0;
+                    }
+                    rel2 {
+                        relative: 1.0 1.0;
+                    }
+                    align: 1.0 0.0;
+                }
+            }
+            part {
+                name:"elm.swallow.content";
+                type: SWALLOW;
+                scale : 1;
+                description {
+                    state: "default" 0.0;
+                    min: 380 0;
+                    align: 0.5 0.5;
+                    fixed: 1 0;
+                    rel1 {
+                        relative: 0.5 1.0;
+                        to: "pad_t";
+                    }
+                    rel2 {
+                        relative: 0.5 0.0;
+                        to: "pad_b";
+                    }
+                }
+            }
+            part {
+                name: "pad_b";
+                scale : 1;
+                mouse_events: 0;
+                description {
+                    state: "default" 0.0;
+                    align: 0.5 1.0;
+                    min: 0 66;
+                    fixed: 0 1;
+                    rel1 {
+                        relative: 1.0 1.0;to_x: "pad_l";
+                    }
+                    rel2 {
+                        relative: 0.0 1.0;to_x: "pad_r";
+                    }
+                }
+            }
+            part {
+                name: "elm.swallow.end";
+                type: SWALLOW;
+                scale : 1;
+                mouse_events: 1;
+                repeat_events: 1;
+                description {
+                    state: "default" 0.0;
+                    align: 0.0 0.5;
+                    rel1 {
+                        relative: 0.18 0.0;
+                        to: "pad_b";
+                    }
+                    rel2 {
+                        relative: 1.0 1.0;
+                        to: "pad_b";
+                    }
+                }
+            }
+            part {
+                name: "elm.text";
+                type: TEXT;
+                scale : 1;
+                description {
+                    state: "default" 0.0;
+                    text {
+                        font: "SLP:style=Medium";
+                        size: 24;
+                        min: 0 0;
+                        align: 0.5 0.5;
+                        text_class: "slp";
+                    }
+                    color: 0 0 0 255;
+                    align: 0.0 0.5;
+                    rel1 {
+                        relative: 0.0 0.0;
+                        to: "pad_b";
+                    }
+                    rel2 {
+                        relative: 1.0 1.0;
+                        to: "pad_b";
+                    }
+                }
+            }
+        }
+    }
 }//end of collection
index 6b6ad87..2bd9031 100644 (file)
@@ -40,6 +40,7 @@ SET(VIEW_MODULE_SOURCES
     ${PROJECT_SOURCE_DIR}/src/domain/user_callback_controller.cpp #TODO this should be moved to separate module
     ${PROJECT_SOURCE_DIR}/src/domain/user_callback_logic.cpp #TODO this should be moved to separate module
     ${PROJECT_SOURCE_DIR}/src/view/webkit/view_logic.cpp
+    ${PROJECT_SOURCE_DIR}/src/view/webkit/view_logic_filesystem_support.cpp
     ${PROJECT_SOURCE_DIR}/src/view/webkit/view_logic_scheme_support.cpp
     ${PROJECT_SOURCE_DIR}/src/view/webkit/view_logic_geolocation_support_webkit2.cpp
     ${PROJECT_SOURCE_DIR}/src/view/webkit/bundles/plugin_module_support.cpp
index 2055dc5..12908ad 100644 (file)
@@ -50,7 +50,8 @@
 #include <common/view_logic_vibration_support.h>
 #include <common/view_logic_web_notification_support.h>
 #include <view_logic_scheme_support.h>
-#include "view_logic_geolocation_support_webkit2.h"
+#include <view_logic_filesystem_support.h>
+#include <view_logic_geolocation_support_webkit2.h>
 #include "bundles/plugin_module_support.h"
 
 #include <EWebKit2.h>
@@ -104,13 +105,12 @@ const char * const EWK_VIBRATION_VIBRATE = "vibration,vibrate";
 const char * const EWK_VIBRATION_CANCEL = "vibration,cancel";
 
 const char * const EWK_CONTEXT_EXCEEDED_QUOATA  = "database,quota,exceeded";
-const char * const EWK_CONTEXT_FILE_SYSTEM_PERMISSION = "filesystem,permission,request";
+const char * const EWK_FILESYSTEM_PERMISSION_REQUEST = "filesystem,permission,request";
 const char * const EWK_FULLSCREEN_ENTER = "fullscreen,enterfullscreen";
 const char * const EWK_FULLSCREEN_EXIT = "fullscreen,exitfullscreen";
 
 // DataBase Use Ask Title
 const char * const DATABASE_USE_ASK_TITLE = "Increase Database Size?";
-const char * const FILESYSTEM_USE_ASK_TITLE = "Use FileSystem?";
 
 // IME Callback
 const char * const EWK_INPUTMETHOD_CHANGED = "inputmethod,changed";
@@ -619,12 +619,11 @@ void ViewLogic::ewkClientInit(Evas_Object *wkView) {
         EWK_CONTEXT_EXCEEDED_QUOATA,
         databaseUsagePermissionRequestCallback,
         this);
-    // The followings are provisional comment for preventing popup
-    //evas_object_smart_callback_add(
-        //wkView,
-        //EWK_CONTEXT_FILE_SYSTEM_PERMISSION,
-        //fileSystemPermissionRequestCallback,
-        //this);
+    evas_object_smart_callback_add(
+        wkView,
+        EWK_FILESYSTEM_PERMISSION_REQUEST,
+        fileSystemPermissionRequestCallback,
+        this);
 
     // EWK Orientation Callback
     ewk_view_orientation_lock_callback_set(
@@ -774,11 +773,10 @@ void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
         wkView,
         EWK_CONTEXT_EXCEEDED_QUOATA,
         databaseUsagePermissionRequestCallback);
-    //The followings are provisional comment for preventing popup
-    //evas_object_smart_callback_del(
-        //wkView,
-        //EWK_CONTEXT_FILE_SYSTEM_PERMISSION,
-        //fileSystemPermissionRequestCallback);
+    evas_object_smart_callback_del(
+        wkView,
+        EWK_FILESYSTEM_PERMISSION_REQUEST,
+        fileSystemPermissionRequestCallback);
 
     // EWK Orientation Callback
     ewk_view_orientation_lock_callback_set(
@@ -1672,50 +1670,14 @@ void ViewLogic::fileSystemPermissionRequestCallback(
     Evas_Object* /*obj*/,
     void* eventInfo)
 {
-    LogDebug("filesystemPermissionRequestCallback called");
+    LogDebug("fileSystemPermissionRequestCallback called");
     Assert(data);
     ViewLogic* This = static_cast<ViewLogic*>(data);
-    This->fileSystemPermissionRequest(eventInfo);
-    return;
- }
-
-void ViewLogic::fileSystemPermissionRequest(
-    void* eventInfo)
-{
-    LogDebug("filesystemPermissionRequest called");
     Assert(eventInfo);
-    Ewk_Context_File_System_Permission* fileSystemPermission =
-        static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
-    bool state = askUserForFileSystemPermission(
-        fileSystemPermission);
-
-    if (true == state) {
-        LogDebug("permit");
-        ewk_context_file_system_permission_allow_set(
-            fileSystemPermission, EINA_TRUE);
-    } else {
-        LogDebug("deny");
-    }
-    return ;
- }
-
-bool ViewLogic::askUserForFileSystemPermission(
-    Ewk_Context_File_System_Permission* fileSystemPermission)
-{
-    LogDebug("askUserForFileSystemPermission called");
-    Ewk_Security_Origin* origin =
-        ewk_context_file_system_permission_origin_get(
-        fileSystemPermission);
-
-    char fileSystemPermissionAskTitle[110];
-    snprintf(fileSystemPermissionAskTitle,
-        sizeof(fileSystemPermissionAskTitle),
-        "Do you want to allow %s to use persistent filesystem?",
-        ewk_security_origin_host_get(origin));
-
-    return Wrt::PopupInvoker().askYesNo(
-        FILESYSTEM_USE_ASK_TITLE,
-        fileSystemPermissionAskTitle);
+    ViewModule::FileSystemSupport::fileSystemPermissionRequest(
+        This->m_window,
+        This->m_securityOriginSupport->getSecurityOriginDAO(),
+        eventInfo);
 }
 
 void ViewLogic::didRecieveMessageFromInjectedBundle(
index 016b76c..4527a4d 100644 (file)
@@ -241,10 +241,6 @@ class ViewLogic : public ViewModule::IViewModule
         void* data,
         Evas_Object* obj,
         void* eventInfo);
-    void fileSystemPermissionRequest(
-           void* eventInfo);
-    bool askUserForFileSystemPermission(
-        Ewk_Context_File_System_Permission* fileSystemPermission);
 
     //bundle
     void didRecieveMessageFromInjectedBundle(
diff --git a/src/view/webkit/view_logic_filesystem_support.cpp b/src/view/webkit/view_logic_filesystem_support.cpp
new file mode 100644 (file)
index 0000000..4be37bb
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file    view_logic_filesystem_support.cpp
+ * @author  Jihoon Chung (jihoon.chung@samsung.com)
+ */
+
+#include "view_logic_filesystem_support.h"
+
+#include <string>
+#include <dpl/log/log.h>
+#include <dpl/assert.h>
+#include <wrt-commons/security-origin-dao/security_origin_dao_types.h>
+#include <wrt-commons/security-origin-dao/security_origin_dao.h>
+#include <EWebKit2.h>
+#include <PopupInvoker.h>
+#include <common/view_logic_security_origin_support.h>
+#include <Evas.h>
+#include <Elementary.h>
+
+namespace ViewModule {
+
+using namespace SecurityOriginDB;
+
+// class declare
+class PermissionData
+{
+  public:
+    SecurityOriginDB::SecurityOriginDAO* m_originDao;
+    SecurityOriginDB::SecurityOriginData m_originData;
+    void* m_data;
+
+    PermissionData(
+        SecurityOriginDB::SecurityOriginDAO* originDao,
+        SecurityOriginDB::SecurityOriginData originData,
+        void* data) :
+            m_originDao(originDao),
+            m_originData(originData),
+            m_data(data)
+    {
+    };
+};
+
+namespace {
+const char* const DAEMON_EDJ_PATH = "/usr/share/edje/wrt/Daemon.edj";
+const char* const FILESYSTEM_USE_ASK_TITLE = "Use FileSystem?";
+const char* const FILESYSTEM_USE_ASK_BODY_PREFIX = "Do you want to allow ";
+const char* const FILESYSTEM_USE_ASK_BODY_POSTFIX =
+    " to use persistent filesystem?";
+
+// function declare
+void askUserForFileSystemPermission(
+    Evas_Object* window,
+    const SecurityOriginData& originData);
+Evas_Object* createPopup(Evas_Object* window,
+                         const char* bodyText,
+                         const char* checkText,
+                         Evas_Smart_Cb lButtonCallback,
+                         Evas_Smart_Cb rButtonCallback,
+                         void* data);
+static void allowCallback(void* data, Evas_Object* obj, void* eventInfo);
+static void denyCallback(void* data, Evas_Object* obj, void* eventInfo);
+
+Result searchDatabase(
+    SecurityOriginDAO* dao,
+    const SecurityOriginData& originData);
+void saveResult(
+    SecurityOriginDAO* dao,
+    const SecurityOriginData &securityOriginData,
+    const Result result);
+
+void askUserForFileSystemPermission(Evas_Object* window, PermissionData* data)
+{
+    LogDebug("askUserForFileSystemPermission called");
+    std::string body =
+        FILESYSTEM_USE_ASK_BODY_PREFIX +
+        DPL::ToUTF8String(data->m_originData.origin.host) +
+        FILESYSTEM_USE_ASK_BODY_POSTFIX;
+    Evas_Object* popup = createPopup(window,
+                                     body.c_str(),
+                                     "Don't ask again",
+                                     allowCallback,
+                                     denyCallback,
+                                     data);
+    if (popup == NULL) {
+        LogError("Fail to find popup object");
+        delete data;
+        return;
+    }
+    evas_object_show(popup);
+}
+
+Evas_Object* createPopup(Evas_Object* window,
+                         const char* bodyText,
+                         const char* checkText,
+                         Evas_Smart_Cb lButtonCallback,
+                         Evas_Smart_Cb rButtonCallback,
+                         void* data)
+{
+    LogDebug("createPopup");
+    Evas_Object* popup = elm_popup_add(window);
+
+    Evas_Object* label = elm_label_add(popup);
+    elm_object_style_set(label, "popup/default");
+    elm_label_line_wrap_set(label, ELM_WRAP_MIXED);
+    elm_object_text_set(label, bodyText);
+    evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0);
+    evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_show(label);
+
+    Evas_Object* layout = elm_layout_add(popup);
+    elm_layout_file_set(layout, DAEMON_EDJ_PATH, "popupWithCheck");
+    evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+    Evas_Object* check = elm_check_add(popup);
+    evas_object_size_hint_align_set(check, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_size_hint_weight_set(check, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+    evas_object_show(check);
+
+    elm_object_part_text_set(layout, "elm.text", checkText);
+    elm_object_part_content_set(layout, "elm.swallow.content", label);
+    elm_object_part_content_set(layout, "elm.swallow.end", check);
+
+    evas_object_show(layout);
+    elm_object_content_set(popup, layout);
+    Evas_Object* btn1 = elm_button_add(popup);
+    elm_object_text_set(btn1, "YES");
+    elm_object_part_content_set(popup, "button1", btn1);
+    evas_object_smart_callback_add(btn1, "clicked", lButtonCallback, data);
+    Evas_Object* btn2 = elm_button_add(popup);
+    elm_object_text_set(btn2, "NO");
+    elm_object_part_content_set(popup, "button2", btn2);
+    evas_object_smart_callback_add(btn2, "clicked", rButtonCallback, data);
+    return popup;
+}
+
+void allowCallback(void* data, Evas_Object* obj, void* /*eventInfo*/)
+{
+    LogDebug("allow");
+    Assert(data);
+    PermissionData* permData = static_cast<PermissionData*>(data);
+    Ewk_Context_File_System_Permission* fileSystemPermission =
+            static_cast<Ewk_Context_File_System_Permission*>(permData->m_data);
+
+    // get popup evas_object
+    Evas_Object* popup = obj;
+    const char* type = elm_object_widget_type_get(popup);
+    while (type != NULL && strcmp(type, "popup")) {
+        popup = elm_object_parent_widget_get(popup);
+        type = elm_object_widget_type_get(popup);
+    }
+    if (type == NULL) {
+        LogError("Fail to find popup object");
+        ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                     EINA_FALSE);
+        delete permData;
+        evas_object_del(popup);
+        return;
+    }
+
+    // get check evas_object
+    Evas_Object* check = elm_object_part_content_get(
+        elm_object_content_get(popup),
+        "elm.swallow.end");
+    if (check == NULL) {
+        LogError("Fail to find check object");
+        ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                     EINA_FALSE);
+        delete permData;
+        evas_object_del(popup);
+        return;
+    }
+
+    Result result = elm_check_state_get(check) ? RESULT_ALLOW_ALWAYS : RESULT_ALLOW_ONCE;
+    LogDebug("permit");
+    saveResult(permData->m_originDao, permData->m_originData, result);
+    ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                 EINA_TRUE);
+    delete permData;
+    evas_object_del(popup);
+}
+
+void denyCallback(void* data, Evas_Object* obj, void* /*eventInfo*/)
+{
+    LogDebug("deny");
+    Assert(data);
+    PermissionData* permData = static_cast<PermissionData*>(data);
+    Ewk_Context_File_System_Permission* fileSystemPermission =
+            static_cast<Ewk_Context_File_System_Permission*>(permData->m_data);
+
+    // get popup evas_object
+    Evas_Object* popup = obj;
+    const char* type = elm_object_widget_type_get(popup);
+    while (type != NULL && strcmp(type, "popup")) {
+        popup = elm_object_parent_widget_get(popup);
+        type = elm_object_widget_type_get(popup);
+    }
+    if (type == NULL) {
+        LogError("Fail to find popup object");
+        ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                             EINA_FALSE);
+        delete permData;
+        evas_object_del(popup);
+        return;
+    }
+
+    // get check evas_object
+    Evas_Object* check = elm_object_part_content_get(
+        elm_object_content_get(popup),
+        "elm.swallow.end");
+    if (check == NULL) {
+        LogError("Fail to find check object");
+        ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                             EINA_FALSE);
+        delete permData;
+        evas_object_del(popup);
+        return;
+    }
+
+    Result result = elm_check_state_get(check) ? RESULT_DENY_ALWAYS : RESULT_DENY_ONCE;
+    LogDebug("permit");
+    saveResult(permData->m_originDao, permData->m_originData, result);
+    ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                 EINA_FALSE);
+    delete permData;
+    evas_object_del(popup);
+}
+
+Result searchDatabase(SecurityOriginDAO* dao,
+                      const SecurityOriginData& originData)
+{
+    LogDebug("searchDatabase called");
+    return dao->getResult(originData);
+}
+
+void saveResult(SecurityOriginDAO* dao,
+                const SecurityOriginData &securityOriginData,
+                const Result result)
+{
+    LogDebug("searchDatabase called");
+    dao->setSecurityOriginData(securityOriginData, result);
+    return;
+}
+} // namespace
+
+void FileSystemSupport::fileSystemPermissionRequest(
+    Evas_Object* window,
+    SecurityOriginDAO* securityOriginDAO,
+    void* data)
+{
+    LogDebug("fileSystemPermissionRequest called");
+    Assert(securityOriginDAO);
+    Assert(data);
+    Ewk_Context_File_System_Permission* fileSystemPermission =
+        static_cast<Ewk_Context_File_System_Permission*>(data);
+    Ewk_Security_Origin* ewkOrigin =
+        ewk_context_file_system_permission_origin_get(
+        fileSystemPermission);
+    Assert(ewkOrigin);
+
+    SecurityOriginData securityOriginData(
+        FEATURE_FILE_SYSTEM_ACCESS,
+        Origin(DPL::FromUTF8String(ewk_security_origin_protocol_get(ewkOrigin)),
+               DPL::FromUTF8String(ewk_security_origin_host_get(ewkOrigin)),
+               ewk_security_origin_port_get(ewkOrigin)));
+
+    // check cache database
+    Result result = searchDatabase(securityOriginDAO, securityOriginData);
+    if (RESULT_ALLOW_ONCE == result || RESULT_ALLOW_ALWAYS == result) {
+        LogDebug("permit");
+        ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                     EINA_TRUE);
+        return;
+    } else if (RESULT_DENY_ONCE == result || RESULT_DENY_ALWAYS == result) {
+        LogDebug("deny");
+        ewk_context_file_system_permission_allow_set(fileSystemPermission,
+                                                     EINA_FALSE);
+        return;
+    }
+
+    // case of no stored data in the cache database, ask user
+    PermissionData* permissionData = new PermissionData(securityOriginDAO, securityOriginData, fileSystemPermission);
+    askUserForFileSystemPermission(window, permissionData);
+    return;
+}
+} // namespace ViewModule
diff --git a/src/view/webkit/view_logic_filesystem_support.h b/src/view/webkit/view_logic_filesystem_support.h
new file mode 100644 (file)
index 0000000..e0f24eb
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file    view_logic_filesystem_support.h
+ * @author  Jihoon Chung (jihoon.chung@samsung.com)
+ */
+
+#ifndef VIEW_LOGIC_FILESYSTEM_SUPPORT_H_
+#define VIEW_LOGIC_FILESYSTEM_SUPPORT_H_
+
+#include <memory.h>
+#include <Elementary.h>
+
+namespace SecurityOriginDB {
+    class SecurityOriginDAO;
+}
+
+namespace ViewModule {
+namespace FileSystemSupport {
+
+void fileSystemPermissionRequest(
+        Evas_Object* window,
+        SecurityOriginDB::SecurityOriginDAO* securityOriginDAO,
+        void* data);
+
+} // namespace FileSystemSupport
+} // namespace ViewModule
+
+#endif // VIEW_LOGIC_FILESYSTEM_SUPPORT_H_