| OLD | NEW | 
|    1 // Copyright 2013 The Chromium Authors. All rights reserved. |    1 // Copyright 2013 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "chrome/browser/media_galleries/fileapi/iphoto_file_util.h" |    5 #include "chrome/browser/media_galleries/fileapi/iphoto_file_util.h" | 
|    6  |    6  | 
|    7 #include <set> |    7 #include <set> | 
|    8 #include <string> |    8 #include <string> | 
|    9 #include <vector> |    9 #include <vector> | 
|   10  |   10  | 
|   11 #include "base/bind_helpers.h" |   11 #include "base/bind_helpers.h" | 
|   12 #include "base/file_util.h" |   12 #include "base/file_util.h" | 
|   13 #include "base/strings/string_number_conversions.h" |   13 #include "base/strings/string_number_conversions.h" | 
|   14 #include "base/strings/utf_string_conversions.h" |   14 #include "base/strings/utf_string_conversions.h" | 
|   15 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h" |   15 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h" | 
|   16 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" |   16 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" | 
|   17 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" |   17 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" | 
|   18 #include "content/public/browser/browser_thread.h" |   18 #include "content/public/browser/browser_thread.h" | 
|   19 #include "webkit/browser/fileapi/file_system_operation_context.h" |   19 #include "storage/browser/fileapi/file_system_operation_context.h" | 
|   20 #include "webkit/browser/fileapi/file_system_url.h" |   20 #include "storage/browser/fileapi/file_system_url.h" | 
|   21 #include "webkit/browser/fileapi/native_file_util.h" |   21 #include "storage/browser/fileapi/native_file_util.h" | 
|   22 #include "webkit/common/blob/shareable_file_reference.h" |   22 #include "storage/common/blob/shareable_file_reference.h" | 
|   23 #include "webkit/common/fileapi/directory_entry.h" |   23 #include "storage/common/fileapi/directory_entry.h" | 
|   24 #include "webkit/common/fileapi/file_system_util.h" |   24 #include "storage/common/fileapi/file_system_util.h" | 
|   25  |   25  | 
|   26 using fileapi::DirectoryEntry; |   26 using storage::DirectoryEntry; | 
|   27  |   27  | 
|   28 namespace iphoto { |   28 namespace iphoto { | 
|   29  |   29  | 
|   30 namespace { |   30 namespace { | 
|   31  |   31  | 
|   32 base::File::Error MakeDirectoryFileInfo(base::File::Info* file_info) { |   32 base::File::Error MakeDirectoryFileInfo(base::File::Info* file_info) { | 
|   33   base::File::Info result; |   33   base::File::Info result; | 
|   34   result.is_directory = true; |   34   result.is_directory = true; | 
|   35   *file_info = result; |   35   *file_info = result; | 
|   36   return base::File::FILE_OK; |   36   return base::File::FILE_OK; | 
|   37 } |   37 } | 
|   38  |   38  | 
|   39 template <typename T> |   39 template <typename T> | 
|   40 bool ContainsElement(const std::vector<T>& collection, const T& key) { |   40 bool ContainsElement(const std::vector<T>& collection, const T& key) { | 
|   41   typename std::vector<T>::const_iterator it = collection.begin(); |   41   typename std::vector<T>::const_iterator it = collection.begin(); | 
|   42   while (it != collection.end()) { |   42   while (it != collection.end()) { | 
|   43     if (*it == key) |   43     if (*it == key) | 
|   44       return true; |   44       return true; | 
|   45     it++; |   45     it++; | 
|   46   } |   46   } | 
|   47   return false; |   47   return false; | 
|   48 } |   48 } | 
|   49  |   49  | 
|   50 std::vector<std::string> GetVirtualPathComponents( |   50 std::vector<std::string> GetVirtualPathComponents( | 
|   51     const fileapi::FileSystemURL& url) { |   51     const storage::FileSystemURL& url) { | 
|   52   ImportedMediaGalleryRegistry* imported_registry = |   52   ImportedMediaGalleryRegistry* imported_registry = | 
|   53       ImportedMediaGalleryRegistry::GetInstance(); |   53       ImportedMediaGalleryRegistry::GetInstance(); | 
|   54   base::FilePath root = imported_registry->ImportedRoot().AppendASCII("iphoto"); |   54   base::FilePath root = imported_registry->ImportedRoot().AppendASCII("iphoto"); | 
|   55  |   55  | 
|   56   DCHECK(root.IsParent(url.path()) || root == url.path()); |   56   DCHECK(root.IsParent(url.path()) || root == url.path()); | 
|   57   base::FilePath virtual_path; |   57   base::FilePath virtual_path; | 
|   58   root.AppendRelativePath(url.path(), &virtual_path); |   58   root.AppendRelativePath(url.path(), &virtual_path); | 
|   59  |   59  | 
|   60   std::vector<std::string> result; |   60   std::vector<std::string> result; | 
|   61   fileapi::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result); |   61   storage::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result); | 
|   62   return result; |   62   return result; | 
|   63 } |   63 } | 
|   64  |   64  | 
|   65 }  // namespace |   65 }  // namespace | 
|   66  |   66  | 
|   67 const char kIPhotoAlbumsDir[] = "Albums"; |   67 const char kIPhotoAlbumsDir[] = "Albums"; | 
|   68 const char kIPhotoOriginalsDir[] = "Originals"; |   68 const char kIPhotoOriginalsDir[] = "Originals"; | 
|   69  |   69  | 
|   70 IPhotoFileUtil::IPhotoFileUtil(MediaPathFilter* media_path_filter) |   70 IPhotoFileUtil::IPhotoFileUtil(MediaPathFilter* media_path_filter) | 
|   71     : NativeMediaFileUtil(media_path_filter), |   71     : NativeMediaFileUtil(media_path_filter), | 
|   72       weak_factory_(this), |   72       weak_factory_(this), | 
|   73       imported_registry_(NULL) { |   73       imported_registry_(NULL) { | 
|   74 } |   74 } | 
|   75  |   75  | 
|   76 IPhotoFileUtil::~IPhotoFileUtil() { |   76 IPhotoFileUtil::~IPhotoFileUtil() { | 
|   77 } |   77 } | 
|   78  |   78  | 
|   79 void IPhotoFileUtil::GetFileInfoOnTaskRunnerThread( |   79 void IPhotoFileUtil::GetFileInfoOnTaskRunnerThread( | 
|   80     scoped_ptr<fileapi::FileSystemOperationContext> context, |   80     scoped_ptr<storage::FileSystemOperationContext> context, | 
|   81     const fileapi::FileSystemURL& url, |   81     const storage::FileSystemURL& url, | 
|   82     const GetFileInfoCallback& callback) { |   82     const GetFileInfoCallback& callback) { | 
|   83   IPhotoDataProvider* data_provider = GetDataProvider(); |   83   IPhotoDataProvider* data_provider = GetDataProvider(); | 
|   84   // |data_provider| may be NULL if the file system was revoked before this |   84   // |data_provider| may be NULL if the file system was revoked before this | 
|   85   // operation had a chance to run. |   85   // operation had a chance to run. | 
|   86   if (!data_provider) { |   86   if (!data_provider) { | 
|   87     GetFileInfoWithFreshDataProvider(context.Pass(), url, callback, false); |   87     GetFileInfoWithFreshDataProvider(context.Pass(), url, callback, false); | 
|   88   } else { |   88   } else { | 
|   89     data_provider->RefreshData( |   89     data_provider->RefreshData( | 
|   90         base::Bind(&IPhotoFileUtil::GetFileInfoWithFreshDataProvider, |   90         base::Bind(&IPhotoFileUtil::GetFileInfoWithFreshDataProvider, | 
|   91                    weak_factory_.GetWeakPtr(), base::Passed(&context), url, |   91                    weak_factory_.GetWeakPtr(), base::Passed(&context), url, | 
|   92                    callback)); |   92                    callback)); | 
|   93   } |   93   } | 
|   94 } |   94 } | 
|   95  |   95  | 
|   96 void IPhotoFileUtil::ReadDirectoryOnTaskRunnerThread( |   96 void IPhotoFileUtil::ReadDirectoryOnTaskRunnerThread( | 
|   97     scoped_ptr<fileapi::FileSystemOperationContext> context, |   97     scoped_ptr<storage::FileSystemOperationContext> context, | 
|   98     const fileapi::FileSystemURL& url, |   98     const storage::FileSystemURL& url, | 
|   99     const ReadDirectoryCallback& callback) { |   99     const ReadDirectoryCallback& callback) { | 
|  100   IPhotoDataProvider* data_provider = GetDataProvider(); |  100   IPhotoDataProvider* data_provider = GetDataProvider(); | 
|  101   // |data_provider| may be NULL if the file system was revoked before this |  101   // |data_provider| may be NULL if the file system was revoked before this | 
|  102   // operation had a chance to run. |  102   // operation had a chance to run. | 
|  103   if (!data_provider) { |  103   if (!data_provider) { | 
|  104     ReadDirectoryWithFreshDataProvider(context.Pass(), url, callback, false); |  104     ReadDirectoryWithFreshDataProvider(context.Pass(), url, callback, false); | 
|  105   } else { |  105   } else { | 
|  106     data_provider->RefreshData( |  106     data_provider->RefreshData( | 
|  107         base::Bind(&IPhotoFileUtil::ReadDirectoryWithFreshDataProvider, |  107         base::Bind(&IPhotoFileUtil::ReadDirectoryWithFreshDataProvider, | 
|  108                    weak_factory_.GetWeakPtr(), base::Passed(&context), url, |  108                    weak_factory_.GetWeakPtr(), base::Passed(&context), url, | 
|  109                    callback)); |  109                    callback)); | 
|  110   } |  110   } | 
|  111 } |  111 } | 
|  112  |  112  | 
|  113 void IPhotoFileUtil::CreateSnapshotFileOnTaskRunnerThread( |  113 void IPhotoFileUtil::CreateSnapshotFileOnTaskRunnerThread( | 
|  114     scoped_ptr<fileapi::FileSystemOperationContext> context, |  114     scoped_ptr<storage::FileSystemOperationContext> context, | 
|  115     const fileapi::FileSystemURL& url, |  115     const storage::FileSystemURL& url, | 
|  116     const CreateSnapshotFileCallback& callback) { |  116     const CreateSnapshotFileCallback& callback) { | 
|  117   IPhotoDataProvider* data_provider = GetDataProvider(); |  117   IPhotoDataProvider* data_provider = GetDataProvider(); | 
|  118   // |data_provider| may be NULL if the file system was revoked before this |  118   // |data_provider| may be NULL if the file system was revoked before this | 
|  119   // operation had a chance to run. |  119   // operation had a chance to run. | 
|  120   if (!data_provider) { |  120   if (!data_provider) { | 
|  121     CreateSnapshotFileWithFreshDataProvider(context.Pass(), url, callback, |  121     CreateSnapshotFileWithFreshDataProvider(context.Pass(), url, callback, | 
|  122                                             false); |  122                                             false); | 
|  123   } else { |  123   } else { | 
|  124     data_provider->RefreshData( |  124     data_provider->RefreshData( | 
|  125         base::Bind(&IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider, |  125         base::Bind(&IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider, | 
|  126                    weak_factory_.GetWeakPtr(), base::Passed(&context), url, |  126                    weak_factory_.GetWeakPtr(), base::Passed(&context), url, | 
|  127                    callback)); |  127                    callback)); | 
|  128   } |  128   } | 
|  129 } |  129 } | 
|  130  |  130  | 
|  131 void IPhotoFileUtil::GetFileInfoWithFreshDataProvider( |  131 void IPhotoFileUtil::GetFileInfoWithFreshDataProvider( | 
|  132     scoped_ptr<fileapi::FileSystemOperationContext> context, |  132     scoped_ptr<storage::FileSystemOperationContext> context, | 
|  133     const fileapi::FileSystemURL& url, |  133     const storage::FileSystemURL& url, | 
|  134     const GetFileInfoCallback& callback, |  134     const GetFileInfoCallback& callback, | 
|  135     bool valid_parse) { |  135     bool valid_parse) { | 
|  136   if (!valid_parse) { |  136   if (!valid_parse) { | 
|  137     if (!callback.is_null()) { |  137     if (!callback.is_null()) { | 
|  138       content::BrowserThread::PostTask( |  138       content::BrowserThread::PostTask( | 
|  139           content::BrowserThread::IO, |  139           content::BrowserThread::IO, | 
|  140           FROM_HERE, |  140           FROM_HERE, | 
|  141           base::Bind(callback, base::File::FILE_ERROR_IO, base::File::Info())); |  141           base::Bind(callback, base::File::FILE_ERROR_IO, base::File::Info())); | 
|  142     } |  142     } | 
|  143     return; |  143     return; | 
|  144   } |  144   } | 
|  145   NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context.Pass(), url, |  145   NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context.Pass(), url, | 
|  146                                                      callback); |  146                                                      callback); | 
|  147 } |  147 } | 
|  148  |  148  | 
|  149 void IPhotoFileUtil::ReadDirectoryWithFreshDataProvider( |  149 void IPhotoFileUtil::ReadDirectoryWithFreshDataProvider( | 
|  150     scoped_ptr<fileapi::FileSystemOperationContext> context, |  150     scoped_ptr<storage::FileSystemOperationContext> context, | 
|  151     const fileapi::FileSystemURL& url, |  151     const storage::FileSystemURL& url, | 
|  152     const ReadDirectoryCallback& callback, |  152     const ReadDirectoryCallback& callback, | 
|  153     bool valid_parse) { |  153     bool valid_parse) { | 
|  154   if (!valid_parse) { |  154   if (!valid_parse) { | 
|  155     if (!callback.is_null()) { |  155     if (!callback.is_null()) { | 
|  156       content::BrowserThread::PostTask( |  156       content::BrowserThread::PostTask( | 
|  157           content::BrowserThread::IO, |  157           content::BrowserThread::IO, | 
|  158           FROM_HERE, |  158           FROM_HERE, | 
|  159           base::Bind(callback, base::File::FILE_ERROR_IO, EntryList(), false)); |  159           base::Bind(callback, base::File::FILE_ERROR_IO, EntryList(), false)); | 
|  160     } |  160     } | 
|  161     return; |  161     return; | 
|  162   } |  162   } | 
|  163   NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context.Pass(), url, |  163   NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context.Pass(), url, | 
|  164                                                        callback); |  164                                                        callback); | 
|  165 } |  165 } | 
|  166  |  166  | 
|  167 void IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider( |  167 void IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider( | 
|  168     scoped_ptr<fileapi::FileSystemOperationContext> context, |  168     scoped_ptr<storage::FileSystemOperationContext> context, | 
|  169     const fileapi::FileSystemURL& url, |  169     const storage::FileSystemURL& url, | 
|  170     const CreateSnapshotFileCallback& callback, |  170     const CreateSnapshotFileCallback& callback, | 
|  171     bool valid_parse) { |  171     bool valid_parse) { | 
|  172   if (!valid_parse) { |  172   if (!valid_parse) { | 
|  173     if (!callback.is_null()) { |  173     if (!callback.is_null()) { | 
|  174       base::File::Info file_info; |  174       base::File::Info file_info; | 
|  175       base::FilePath platform_path; |  175       base::FilePath platform_path; | 
|  176       scoped_refptr<webkit_blob::ShareableFileReference> file_ref; |  176       scoped_refptr<storage::ShareableFileReference> file_ref; | 
|  177       content::BrowserThread::PostTask( |  177       content::BrowserThread::PostTask( | 
|  178           content::BrowserThread::IO, |  178           content::BrowserThread::IO, | 
|  179           FROM_HERE, |  179           FROM_HERE, | 
|  180           base::Bind(callback, base::File::FILE_ERROR_IO, file_info, |  180           base::Bind(callback, base::File::FILE_ERROR_IO, file_info, | 
|  181                      platform_path, file_ref)); |  181                      platform_path, file_ref)); | 
|  182     } |  182     } | 
|  183     return; |  183     return; | 
|  184   } |  184   } | 
|  185   NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(context.Pass(), url, |  185   NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(context.Pass(), url, | 
|  186                                                             callback); |  186                                                             callback); | 
|  187 } |  187 } | 
|  188  |  188  | 
|  189 // Begin actual implementation. |  189 // Begin actual implementation. | 
|  190  |  190  | 
|  191 base::File::Error IPhotoFileUtil::GetFileInfoSync( |  191 base::File::Error IPhotoFileUtil::GetFileInfoSync( | 
|  192     fileapi::FileSystemOperationContext* context, |  192     storage::FileSystemOperationContext* context, | 
|  193     const fileapi::FileSystemURL& url, |  193     const storage::FileSystemURL& url, | 
|  194     base::File::Info* file_info, |  194     base::File::Info* file_info, | 
|  195     base::FilePath* platform_path) { |  195     base::FilePath* platform_path) { | 
|  196   std::vector<std::string> components = GetVirtualPathComponents(url); |  196   std::vector<std::string> components = GetVirtualPathComponents(url); | 
|  197  |  197  | 
|  198   if (components.size() == 0) { |  198   if (components.size() == 0) { | 
|  199     return MakeDirectoryFileInfo(file_info); |  199     return MakeDirectoryFileInfo(file_info); | 
|  200   } |  200   } | 
|  201  |  201  | 
|  202   // The 'Albums' directory. |  202   // The 'Albums' directory. | 
|  203   if (components[0] == kIPhotoAlbumsDir) { |  203   if (components[0] == kIPhotoAlbumsDir) { | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|  231         return NativeMediaFileUtil::GetFileInfoSync( |  231         return NativeMediaFileUtil::GetFileInfoSync( | 
|  232             context, url, file_info, platform_path); |  232             context, url, file_info, platform_path); | 
|  233       } |  233       } | 
|  234     } |  234     } | 
|  235   } |  235   } | 
|  236  |  236  | 
|  237   return base::File::FILE_ERROR_NOT_FOUND; |  237   return base::File::FILE_ERROR_NOT_FOUND; | 
|  238 } |  238 } | 
|  239  |  239  | 
|  240 base::File::Error IPhotoFileUtil::ReadDirectorySync( |  240 base::File::Error IPhotoFileUtil::ReadDirectorySync( | 
|  241     fileapi::FileSystemOperationContext* context, |  241     storage::FileSystemOperationContext* context, | 
|  242     const fileapi::FileSystemURL& url, |  242     const storage::FileSystemURL& url, | 
|  243     EntryList* file_list) { |  243     EntryList* file_list) { | 
|  244   DCHECK(file_list->empty()); |  244   DCHECK(file_list->empty()); | 
|  245   std::vector<std::string> components = GetVirtualPathComponents(url); |  245   std::vector<std::string> components = GetVirtualPathComponents(url); | 
|  246  |  246  | 
|  247   // Root directory. Child is the /Albums dir. |  247   // Root directory. Child is the /Albums dir. | 
|  248   if (components.size() == 0) { |  248   if (components.size() == 0) { | 
|  249     file_list->push_back(DirectoryEntry(kIPhotoAlbumsDir, |  249     file_list->push_back(DirectoryEntry(kIPhotoAlbumsDir, | 
|  250                                         DirectoryEntry::DIRECTORY, |  250                                         DirectoryEntry::DIRECTORY, | 
|  251                                         0, base::Time())); |  251                                         0, base::Time())); | 
|  252     return base::File::FILE_OK; |  252     return base::File::FILE_OK; | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  302                                             info.size, info.last_modified)); |  302                                             info.size, info.last_modified)); | 
|  303       } |  303       } | 
|  304       return base::File::FILE_OK; |  304       return base::File::FILE_OK; | 
|  305     } |  305     } | 
|  306   } |  306   } | 
|  307  |  307  | 
|  308   return base::File::FILE_ERROR_NOT_FOUND; |  308   return base::File::FILE_ERROR_NOT_FOUND; | 
|  309 } |  309 } | 
|  310  |  310  | 
|  311 base::File::Error IPhotoFileUtil::DeleteDirectorySync( |  311 base::File::Error IPhotoFileUtil::DeleteDirectorySync( | 
|  312     fileapi::FileSystemOperationContext* context, |  312     storage::FileSystemOperationContext* context, | 
|  313     const fileapi::FileSystemURL& url) { |  313     const storage::FileSystemURL& url) { | 
|  314   return base::File::FILE_ERROR_SECURITY; |  314   return base::File::FILE_ERROR_SECURITY; | 
|  315 } |  315 } | 
|  316  |  316  | 
|  317 base::File::Error IPhotoFileUtil::DeleteFileSync( |  317 base::File::Error IPhotoFileUtil::DeleteFileSync( | 
|  318     fileapi::FileSystemOperationContext* context, |  318     storage::FileSystemOperationContext* context, | 
|  319     const fileapi::FileSystemURL& url) { |  319     const storage::FileSystemURL& url) { | 
|  320   return base::File::FILE_ERROR_SECURITY; |  320   return base::File::FILE_ERROR_SECURITY; | 
|  321 } |  321 } | 
|  322  |  322  | 
|  323  |  | 
|  324 base::File::Error IPhotoFileUtil::GetLocalFilePath( |  323 base::File::Error IPhotoFileUtil::GetLocalFilePath( | 
|  325     fileapi::FileSystemOperationContext* context, |  324     storage::FileSystemOperationContext* context, | 
|  326     const fileapi::FileSystemURL& url, |  325     const storage::FileSystemURL& url, | 
|  327     base::FilePath* local_file_path) { |  326     base::FilePath* local_file_path) { | 
|  328   std::vector<std::string> components = GetVirtualPathComponents(url); |  327   std::vector<std::string> components = GetVirtualPathComponents(url); | 
|  329  |  328  | 
|  330   if (components.size() == 3 && components[0] == kIPhotoAlbumsDir) { |  329   if (components.size() == 3 && components[0] == kIPhotoAlbumsDir) { | 
|  331     base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum( |  330     base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum( | 
|  332         components[1], components[2]); |  331         components[1], components[2]); | 
|  333     if (!location.empty()) { |  332     if (!location.empty()) { | 
|  334       *local_file_path = location; |  333       *local_file_path = location; | 
|  335       return base::File::FILE_OK; |  334       return base::File::FILE_OK; | 
|  336     } |  335     } | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  350   return base::File::FILE_ERROR_NOT_FOUND; |  349   return base::File::FILE_ERROR_NOT_FOUND; | 
|  351 } |  350 } | 
|  352  |  351  | 
|  353 IPhotoDataProvider* IPhotoFileUtil::GetDataProvider() { |  352 IPhotoDataProvider* IPhotoFileUtil::GetDataProvider() { | 
|  354   if (!imported_registry_) |  353   if (!imported_registry_) | 
|  355     imported_registry_ = ImportedMediaGalleryRegistry::GetInstance(); |  354     imported_registry_ = ImportedMediaGalleryRegistry::GetInstance(); | 
|  356   return imported_registry_->IPhotoDataProvider(); |  355   return imported_registry_->IPhotoDataProvider(); | 
|  357 } |  356 } | 
|  358  |  357  | 
|  359 }  // namespace iphoto |  358 }  // namespace iphoto | 
| OLD | NEW |