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