Bug 1036863 - [MTP] Rename file/folder via MTP, r=dhylands
authorEric Chou <echou@mozilla.com>
Mon, 21 Jul 2014 09:57:04 +0800
changeset 195313 80464b4faafef904677b9917c7e533491d0a61d5
parent 195312 9c12611908299593fdebce7cfb0ce1cf21be7d45
child 195314 5c8fdf919214dd40a795470f75f7b09140b8c999
push id46575
push userkwierso@gmail.com
push dateTue, 22 Jul 2014 00:35:21 +0000
treeherdermozilla-inbound@fee5c4bdd713 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdhylands
bugs1036863
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1036863 - [MTP] Rename file/folder via MTP, r=dhylands This patch fixed 'unable to rename file/folder via MTP' by responding to MTP operation 'setObjectPropertyValue' correctly
dom/system/gonk/MozMtpCommon.h
dom/system/gonk/MozMtpDatabase.cpp
--- a/dom/system/gonk/MozMtpCommon.h
+++ b/dom/system/gonk/MozMtpCommon.h
@@ -23,22 +23,24 @@
 #define END_MTP_NAMESPACE \
   } /* namespace mtp */ } /* namespace system */ } /* namespace mozilla */
 #define USING_MTP_NAMESPACE \
   using namespace mozilla::system::mtp;
 
 namespace android {
   class MOZ_EXPORT MtpServer;
   class MOZ_EXPORT MtpStorage;
+  class MOZ_EXPORT MtpStringBuffer;
   class MOZ_EXPORT MtpDatabase;
   class MOZ_EXPORT MtpDataPacket;
   class MOZ_EXPORT MtpProperty;
 }
 
 #include <mtp.h>
 #include <MtpDatabase.h>
 #include <MtpObjectInfo.h>
 #include <MtpProperty.h>
 #include <MtpServer.h>
 #include <MtpStorage.h>
+#include <MtpStringBuffer.h>
 #include <MtpTypes.h>
 
 #endif // mozilla_system_mtpcommon_h__
--- a/dom/system/gonk/MozMtpDatabase.cpp
+++ b/dom/system/gonk/MozMtpDatabase.cpp
@@ -24,16 +24,17 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLAT
 
 BEGIN_MTP_NAMESPACE
 
 static const char *
 ObjectPropertyAsStr(MtpObjectProperty aProperty)
 {
   switch (aProperty) {
     case MTP_PROPERTY_STORAGE_ID:       return "MTP_PROPERTY_STORAGE_ID";
+    case MTP_PROPERTY_OBJECT_FILE_NAME: return "MTP_PROPERTY_OBJECT_FILE_NAME";
     case MTP_PROPERTY_OBJECT_FORMAT:    return "MTP_PROPERTY_OBJECT_FORMAT";
     case MTP_PROPERTY_OBJECT_SIZE:      return "MTP_PROPERTY_OBJECT_SIZE";
     case MTP_PROPERTY_WIDTH:            return "MTP_PROPERTY_WIDTH";
     case MTP_PROPERTY_HEIGHT:           return "MTP_PROPERTY_HEIGHT";
     case MTP_PROPERTY_IMAGE_BIT_DEPTH:  return "MTP_PROPERTY_IMAGE_BIT_DEPTH";
     case MTP_PROPERTY_DISPLAY_NAME:     return "MTP_PROPERTY_DISPLAY_NAME";
   }
   return "MTP_PROPERTY_???";
@@ -97,16 +98,32 @@ MozMtpDatabase::BaseName(const nsCString
   if (file) {
     nsCString leafName;
     file->GetNativeLeafName(leafName);
     return leafName;
   }
   return path;
 }
 
+static nsCString
+GetPathWithoutFileName(const nsCString& aFullPath)
+{
+  nsCString path;
+
+  int32_t offset = aFullPath.RFindChar('/');
+  if (offset != kNotFound) {
+    // The trailing slash will be as part of 'path'
+    path = StringHead(aFullPath, offset + 1);
+  }
+
+  MTP_LOG("returning '%s'", path.get());
+
+  return path;
+}
+
 void
 MozMtpDatabase::ParseDirectory(const char *aDir, MtpObjectHandle aParent)
 {
   ScopedCloseDir dir;
 
   if (!(dir = PR_OpenDir(aDir))) {
     MTP_ERR("Unable to open directory '%s'", aDir);
     return;
@@ -348,24 +365,94 @@ MozMtpDatabase::getObjectPropertyValue(M
     default:
       MTP_LOG("Invalid Property: 0x%08x", aProperty);
       return MTP_RESPONSE_INVALID_OBJECT_PROP_CODE;
   }
 
   return MTP_RESPONSE_OK;
 }
 
+static int
+GetTypeOfObjectProp(MtpObjectProperty aProperty)
+{
+  struct PropertyTableEntry {
+    MtpObjectProperty property;
+    int type;
+  };
+
+  static const PropertyTableEntry kObjectPropertyTable[] = {
+    {MTP_PROPERTY_STORAGE_ID,        MTP_TYPE_UINT32  },
+    {MTP_PROPERTY_OBJECT_FORMAT,     MTP_TYPE_UINT16  },
+    {MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16  },
+    {MTP_PROPERTY_OBJECT_SIZE,       MTP_TYPE_UINT64  },
+    {MTP_PROPERTY_OBJECT_FILE_NAME,  MTP_TYPE_STR     },
+    {MTP_PROPERTY_DATE_MODIFIED,     MTP_TYPE_STR     },
+    {MTP_PROPERTY_PARENT_OBJECT,     MTP_TYPE_UINT32  },
+    {MTP_PROPERTY_DISPLAY_NAME,      MTP_TYPE_STR     },
+    {MTP_PROPERTY_DATE_ADDED,        MTP_TYPE_STR     },
+  };
+
+  int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
+  const PropertyTableEntry* entryProp = kObjectPropertyTable;
+  int type = 0;
+
+  for (int i = 0; i < count; ++i, ++entryProp) {
+    if (entryProp->property == aProperty) {
+      type = entryProp->type;
+      break;
+    }
+  }
+
+  return type;
+}
+
 //virtual
 MtpResponseCode
 MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
                                      MtpObjectProperty aProperty,
                                      MtpDataPacket& aPacket)
 {
-  MTP_LOG("Handle: 0x%08x (NOT SUPPORTED)", aHandle);
-  return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
+  MTP_LOG("Handle: 0x%08x Property: 0x%08x", aHandle, aProperty);
+
+  // Only support file name change
+  if (aProperty != MTP_PROPERTY_OBJECT_FILE_NAME) {
+    MTP_ERR("property 0x%x not supported", aProperty);
+    return  MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+  }
+
+  if (GetTypeOfObjectProp(aProperty) != MTP_TYPE_STR) {
+    MTP_ERR("property type 0x%x not supported", GetTypeOfObjectProp(aProperty));
+    return MTP_RESPONSE_GENERAL_ERROR;
+  }
+
+  RefPtr<DbEntry> entry = GetEntry(aHandle);
+  if (!entry) {
+    MTP_ERR("Invalid Handle: 0x%08x", aHandle);
+    return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+  }
+
+  MtpStringBuffer buf;
+  aPacket.getString(buf);
+
+  nsDependentCString newFileName(buf);
+  nsCString newFileFullPath(GetPathWithoutFileName(entry->mPath) + newFileName);
+
+  if (PR_Rename(entry->mPath.get(), newFileFullPath.get()) != PR_SUCCESS) {
+    MTP_ERR("Failed to rename '%s' to '%s'",
+            entry->mPath.get(), newFileFullPath.get());
+    return MTP_RESPONSE_GENERAL_ERROR;
+  }
+
+  MTP_LOG("renamed '%s' to '%s'", entry->mPath.get(), newFileFullPath.get());
+
+  entry->mPath = newFileFullPath;
+  entry->mObjectName = BaseName(entry->mPath);
+  entry->mDisplayName = entry->mObjectName;
+
+  return MTP_RESPONSE_OK;
 }
 
 //virtual
 MtpResponseCode
 MozMtpDatabase::getDevicePropertyValue(MtpDeviceProperty aProperty,
                                      MtpDataPacket& aPacket)
 {
   MTP_LOG("(GENERAL ERROR)");