Set OS X cache directory to ~/Library/Caches/[app name]/[profile name] 

 - Added implementation of GetUserCacheDirectory() for OS X. 
 - Added FilePath::GetRelativePath(). 
 - Implemented per-profile cache directories for OS X.

Patch by Fred Akalin <akalin@gmail.com>

Code review URL: http://codereview.chromium.org/174053
Review URL: http://codereview.chromium.org/204043

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26387 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 405a64b63ae9a6869923aa5b80cc77acf66e71bf
diff --git a/base/file_path.cc b/base/file_path.cc
index a521b37..1d90674 100644
--- a/base/file_path.cc
+++ b/base/file_path.cc
@@ -159,6 +159,11 @@
 }
 
 bool FilePath::IsParent(const FilePath& child) const {
+  return AppendRelativePath(child, NULL);
+}
+
+bool FilePath::AppendRelativePath(const FilePath& child,
+                                  FilePath* path) const {
   std::vector<FilePath::StringType> parent_components;
   std::vector<FilePath::StringType> child_components;
   GetComponents(&parent_components);
@@ -194,6 +199,11 @@
     ++child_comp;
   }
 
+  if (path != NULL) {
+    for (; child_comp != child_components.end(); ++child_comp) {
+      *path = path->Append(*child_comp);
+    }
+  }
   return true;
 }
 
diff --git a/base/file_path.h b/base/file_path.h
index e1dbd22..672d589 100644
--- a/base/file_path.h
+++ b/base/file_path.h
@@ -157,6 +157,16 @@
   // parent.
   bool IsParent(const FilePath& child) const;
 
+  // If IsParent(child) holds, appends to path (if non-NULL) the
+  // relative path to child and returns true.  For example, if parent
+  // holds "/Users/johndoe/Library/Application Support", child holds
+  // "/Users/johndoe/Library/Application Support/Google/Chrome/Default", and
+  // *path holds "/Users/johndoe/Library/Caches", then after
+  // parent.AppendRelativePath(child, path) is called *path will hold
+  // "/Users/johndoe/Library/Caches/Google/Chrome/Default".  Otherwise,
+  // returns false.
+  bool AppendRelativePath(const FilePath& child, FilePath* path) const;
+
   // Returns a FilePath corresponding to the directory containing the path
   // named by this object, stripping away the file component.  If this object
   // only contains one component, returns a FilePath identifying
diff --git a/base/file_path_unittest.cc b/base/file_path_unittest.cc
index e14bbca..a2afa1e 100644
--- a/base/file_path_unittest.cc
+++ b/base/file_path_unittest.cc
@@ -485,6 +485,76 @@
   }
 }
 
+TEST_F(FilePathTest, AppendRelativePathTest) {
+  const struct BinaryTestData cases[] = {
+    { { FPL("/"),             FPL("/foo/bar/baz") },      FPL("foo/bar/baz")},
+    { { FPL("/foo/bar"),      FPL("/foo/bar/baz") },      FPL("baz")},
+    { { FPL("/foo/bar/"),     FPL("/foo/bar/baz") },      FPL("baz")},
+    { { FPL("//foo/bar/"),    FPL("//foo/bar/baz") },     FPL("baz")},
+    { { FPL("/foo/bar"),      FPL("/foo2/bar/baz") },     FPL("")},
+    { { FPL("/foo/bar.txt"),  FPL("/foo/bar/baz") },      FPL("")},
+    { { FPL("/foo/bar"),      FPL("/foo/bar2/baz") },     FPL("")},
+    { { FPL("/foo/bar"),      FPL("/foo/bar") },          FPL("")},
+    { { FPL("/foo/bar/baz"),  FPL("/foo/bar") },          FPL("")},
+    { { FPL("foo/bar"),       FPL("foo/bar/baz") },       FPL("baz")},
+    { { FPL("foo/bar"),       FPL("foo2/bar/baz") },      FPL("")},
+    { { FPL("foo/bar"),       FPL("foo/bar2/baz") },      FPL("")},
+    { { FPL(""),              FPL("foo") },               FPL("")},
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+    { { FPL("c:/foo/bar"),    FPL("c:/foo/bar/baz") },    FPL("baz")},
+    { { FPL("E:/foo/bar"),    FPL("e:/foo/bar/baz") },    FPL("baz")},
+    { { FPL("f:/foo/bar"),    FPL("F:/foo/bar/baz") },    FPL("baz")},
+    { { FPL("E:/Foo/bar"),    FPL("e:/foo/bar/baz") },    FPL("")},
+    { { FPL("f:/foo/bar"),    FPL("F:/foo/Bar/baz") },    FPL("")},
+    { { FPL("c:/"),           FPL("c:/foo/bar/baz") },    FPL("foo/bar/baz")},
+    { { FPL("c:"),            FPL("c:/foo/bar/baz") },    FPL("foo/bar/baz")},
+    { { FPL("c:/foo/bar"),    FPL("d:/foo/bar/baz") },    FPL("")},
+    { { FPL("c:/foo/bar"),    FPL("D:/foo/bar/baz") },    FPL("")},
+    { { FPL("C:/foo/bar"),    FPL("d:/foo/bar/baz") },    FPL("")},
+    { { FPL("c:/foo/bar"),    FPL("c:/foo2/bar/baz") },   FPL("")},
+    { { FPL("e:/foo/bar"),    FPL("E:/foo2/bar/baz") },   FPL("")},
+    { { FPL("F:/foo/bar"),    FPL("f:/foo2/bar/baz") },   FPL("")},
+    { { FPL("c:/foo/bar"),    FPL("c:/foo/bar2/baz") },   FPL("")},
+#endif  // FILE_PATH_USES_DRIVE_LETTERS
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+    { { FPL("\\foo\\bar"),    FPL("\\foo\\bar\\baz") },   FPL("baz")},
+    { { FPL("\\foo/bar"),     FPL("\\foo\\bar\\baz") },   FPL("baz")},
+    { { FPL("\\foo/bar"),     FPL("\\foo/bar/baz") },     FPL("baz")},
+    { { FPL("\\"),            FPL("\\foo\\bar\\baz") },   FPL("foo\\bar\\baz")},
+    { { FPL(""),              FPL("\\foo\\bar\\baz") },   FPL("")},
+    { { FPL("\\foo\\bar"),    FPL("\\foo2\\bar\\baz") },  FPL("")},
+    { { FPL("\\foo\\bar"),    FPL("\\foo\\bar2\\baz") },  FPL("")},
+#endif  // FILE_PATH_USES_WIN_SEPARATORS
+  };
+
+  const FilePath base(FPL("blah"));
+
+  for (size_t i = 0; i < arraysize(cases); ++i) {
+    FilePath parent(cases[i].inputs[0]);
+    FilePath child(cases[i].inputs[1]);
+    {
+      FilePath result;
+      bool success = parent.AppendRelativePath(child, &result);
+      EXPECT_EQ(cases[i].expected[0] != '\0', success) <<
+        "i: " << i << ", parent: " << parent.value() << ", child: " <<
+        child.value();
+      EXPECT_STREQ(cases[i].expected, result.value().c_str()) <<
+        "i: " << i << ", parent: " << parent.value() << ", child: " <<
+        child.value();
+    }
+    {
+      FilePath result(base);
+      bool success = parent.AppendRelativePath(child, &result);
+      EXPECT_EQ(cases[i].expected[0] != '\0', success) <<
+        "i: " << i << ", parent: " << parent.value() << ", child: " <<
+        child.value();
+      EXPECT_EQ(base.Append(cases[i].expected).value(), result.value()) <<
+        "i: " << i << ", parent: " << parent.value() << ", child: " <<
+        child.value();
+    }
+  }
+}
+
 TEST_F(FilePathTest, EqualityTest) {
   const struct BinaryBooleanTestData cases[] = {
     { { FPL("/foo/bar/baz"),  FPL("/foo/bar/baz") },      true},
diff --git a/base/path_service_unittest.cc b/base/path_service_unittest.cc
index 32f49b2..cc86be0 100644
--- a/base/path_service_unittest.cc
+++ b/base/path_service_unittest.cc
@@ -47,7 +47,7 @@
   for (int key = base::DIR_CURRENT; key < base::PATH_END; ++key) {
     EXPECT_PRED1(ReturnsValidPath, key);
   }
-#ifdef OS_WIN
+#if defined(OS_WIN)
   for (int key = base::PATH_WIN_START + 1; key < base::PATH_WIN_END; ++key) {
     if (key == base::DIR_LOCAL_APP_DATA_LOW &&
         win_util::GetWinVersion() < win_util::WINVERSION_VISTA) {
@@ -58,5 +58,9 @@
       EXPECT_TRUE(ReturnsValidPath(key)) << key;
     }
   }
+#elif defined(OS_MACOSX)
+  for (int key = base::PATH_MAC_START + 1; key < base::PATH_MAC_END; ++key) {
+      EXPECT_PRED1(ReturnsValidPath, key);
+  }
 #endif
 }