40e2160f185324407e6fefcf7bfe6e0e772f8f31
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / common / xwalk_paths.cc
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "xwalk/runtime/common/xwalk_paths.h"
6
7 #include "base/file_util.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/path_service.h"
12
13 #if defined(OS_WIN)
14 #include "base/base_paths_win.h"
15 #elif defined(OS_LINUX)
16 #include "base/environment.h"
17 #include "base/nix/xdg_util.h"
18 #elif defined(OS_MACOSX) && !defined(OS_IOS)
19 #import "base/mac/mac_util.h"
20 #endif
21
22 namespace xwalk {
23
24 namespace {
25
26 #if defined(OS_MACOSX) && !defined(OS_IOS)
27
28 base::FilePath GetVersionedDirectory() {
29   // Start out with the path to the running executable.
30   base::FilePath path;
31   PathService::Get(base::FILE_EXE, &path);
32
33   // One step up to MacOS, another to Contents.
34   path = path.DirName().DirName();
35   DCHECK_EQ(path.BaseName().value(), "Contents");
36
37   if (base::mac::IsBackgroundOnlyProcess()) {
38     // path identifies the helper .app's Contents directory in the browser
39     // .app's versioned directory.  Go up two steps to get to the browser
40     // .app's versioned directory.
41     path = path.DirName().DirName();
42   }
43
44   return path;
45 }
46
47 base::FilePath GetFrameworkBundlePath() {
48   // It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really
49   // slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating
50   // that it may be more efficient than +bundleForClass:.  +bundleForClass:
51   // itself takes 1-2ms.  Getting an NSBundle from a path, on the other hand,
52   // essentially takes no time at all, at least when the bundle has already
53   // been loaded as it will have been in this case.  The FilePath operations
54   // needed to compute the framework's path are also effectively free, so that
55   // is the approach that is used here.  NSBundle is also documented as being
56   // not thread-safe, and thread safety may be a concern here.
57
58   // The framework bundle is at a known path and name from the browser .app's
59   // versioned directory.
60   return GetVersionedDirectory().Append("XWalk");
61 }
62 #endif
63
64 // File name of the internal NaCl plugin on different platforms.
65 const base::FilePath::CharType kInternalNaClPluginFileName[] =
66     FILE_PATH_LITERAL("internal-nacl-plugin");
67
68 #if defined(OS_LINUX)
69 base::FilePath GetConfigPath() {
70   scoped_ptr<base::Environment> env(base::Environment::Create());
71   return base::nix::GetXDGDirectory(
72       env.get(), base::nix::kXdgConfigHomeEnvVar, base::nix::kDotConfigDir);
73 }
74 #endif
75
76 bool GetXWalkDataPath(base::FilePath* path) {
77   base::FilePath::StringType xwalk_suffix;
78 #if defined(SHARED_PROCESS_MODE)
79   xwalk_suffix = FILE_PATH_LITERAL("xwalk-service");
80 #else
81   xwalk_suffix = FILE_PATH_LITERAL("xwalk");
82 #endif
83   base::FilePath cur;
84
85 #if defined(OS_WIN)
86   CHECK(PathService::Get(base::DIR_LOCAL_APP_DATA, &cur));
87   cur = cur.Append(xwalk_suffix);
88
89 #elif defined(OS_TIZEN) || defined(OS_LINUX)
90   cur = GetConfigPath().Append(xwalk_suffix);
91
92 #elif defined(OS_MACOSX)
93   CHECK(PathService::Get(base::DIR_APP_DATA, &cur));
94   cur = cur.Append(xwalk_suffix);
95
96 #else
97   NOTIMPLEMENTED() << "Unsupported OS platform.";
98   return false;
99 #endif
100
101   *path = cur;
102   return true;
103 }
104
105 bool GetInternalPluginsDirectory(base::FilePath* result) {
106 #if defined(OS_MACOSX) && !defined(OS_IOS)
107   // If called from Chrome, get internal plugins from a subdirectory of the
108   // framework.
109   if (base::mac::AmIBundled()) {
110     *result = xwalk::GetFrameworkBundlePath();
111     DCHECK(!result->empty());
112     *result = result->Append("Internet Plug-Ins");
113     return true;
114   }
115   // In tests, just look in the module directory (below).
116 #endif
117
118   // The rest of the world expects plugins in the module directory.
119   return PathService::Get(base::DIR_MODULE, result);
120 }
121
122 }  // namespace
123
124 bool PathProvider(int key, base::FilePath* path) {
125   base::FilePath cur;
126   switch (key) {
127     case xwalk::DIR_DATA_PATH:
128       return GetXWalkDataPath(path);
129       break;
130     case xwalk::DIR_INTERNAL_PLUGINS:
131       if (!GetInternalPluginsDirectory(&cur))
132         return false;
133       break;
134     case xwalk::FILE_NACL_PLUGIN:
135       if (!GetInternalPluginsDirectory(&cur))
136         return false;
137       cur = cur.Append(kInternalNaClPluginFileName);
138       break;
139     // Where PNaCl files are ultimately located.  The default finds the files
140     // inside the InternalPluginsDirectory / build directory, as if it
141     // was shipped along with xwalk.  The value can be overridden
142     // if it is installed via component updater.
143     case xwalk::DIR_PNACL_COMPONENT:
144 #if defined(OS_MACOSX)
145       // PNaCl really belongs in the InternalPluginsDirectory but actually
146       // copying it there would result in the files also being shipped, which
147       // we don't want yet. So for now, just find them in the directory where
148       // they get built.
149       if (!PathService::Get(base::DIR_EXE, &cur))
150         return false;
151       if (base::mac::AmIBundled()) {
152         // If we're called from xwalk, it's beside the app (outside the
153         // app bundle), if we're called from a unittest, we'll already be
154         // outside the bundle so use the exe dir.
155         // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
156         cur = cur.DirName();
157         cur = cur.DirName();
158         cur = cur.DirName();
159       }
160 #else
161       if (!GetInternalPluginsDirectory(&cur))
162         return false;
163 #endif
164       cur = cur.Append(FILE_PATH_LITERAL("pnacl"));
165       break;
166     case xwalk::DIR_TEST_DATA:
167       if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
168         return false;
169       cur = cur.Append(FILE_PATH_LITERAL("xwalk"));
170       cur = cur.Append(FILE_PATH_LITERAL("test"));
171       cur = cur.Append(FILE_PATH_LITERAL("data"));
172       break;
173     case xwalk::DIR_WGT_STORAGE_PATH:
174       if (!GetXWalkDataPath(&cur))
175         return false;
176       cur = cur.Append(FILE_PATH_LITERAL("Widget Storage"));
177       break;
178     default:
179       return false;
180   }
181   *path = cur;
182   return true;
183 }
184
185 void RegisterPathProvider() {
186   PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
187 }
188
189 }  // namespace xwalk