OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. 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 "chrome/browser/chromeos/usb_mount_observer.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/json/json_writer.h" | |
9 #include "base/singleton.h" | |
10 #include "chrome/browser/chromeos/cros/cros_library.h" | |
11 #include "chrome/browser/profiles/profile.h" | |
12 #include "chrome/browser/ui/browser.h" | |
13 #include "chrome/browser/ui/browser_list.h" | |
14 #include "chrome/browser/ui/browser_window.h" | |
15 #include "chrome/browser/ui/webui/filebrowse_ui.h" | |
16 #include "chrome/common/chrome_switches.h" | |
17 #include "chrome/common/url_constants.h" | |
18 #include "content/browser/tab_contents/tab_contents.h" | |
19 | |
20 | |
21 namespace chromeos { | |
22 | |
23 const char* kFilebrowseURLHash = "chrome://filebrowse#"; | |
24 const char* kFilebrowseScanning = "scanningdevice"; | |
25 const int kPopupLeft = 0; | |
26 const int kPopupTop = 0; | |
27 const int kPopupWidth = 250; | |
28 const int kPopupHeight = 300; | |
29 | |
30 // static | |
31 USBMountObserver* USBMountObserver::GetInstance() { | |
32 return Singleton<USBMountObserver>::get(); | |
33 } | |
34 | |
35 void USBMountObserver::Observe(NotificationType type, | |
36 const NotificationSource& source, | |
37 const NotificationDetails& details) { | |
38 DCHECK(type == NotificationType::BROWSER_CLOSED); | |
39 for (BrowserIterator i = browsers_.begin(); i != browsers_.end(); | |
40 ++i) { | |
41 if (Source<Browser>(source).ptr() == i->browser) { | |
42 i->browser = NULL; | |
43 registrar_.Remove(this, | |
44 NotificationType::BROWSER_CLOSED, | |
45 source); | |
46 return; | |
47 } | |
48 } | |
49 } | |
50 | |
51 void USBMountObserver::OpenFileBrowse(const std::string& url, | |
52 const std::string& device_path, | |
53 bool small) { | |
54 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
55 switches::kEnableAdvancedFileSystem)) { | |
56 return; | |
57 } | |
58 Browser* browser; | |
59 Profile* profile; | |
60 browser = BrowserList::GetLastActive(); | |
61 if (browser == NULL) { | |
62 return; | |
63 } | |
64 profile = browser->profile(); | |
65 if (small) { | |
66 browser = FileBrowseUI::OpenPopup(profile, | |
67 url, | |
68 FileBrowseUI::kSmallPopupWidth, | |
69 FileBrowseUI::kSmallPopupHeight); | |
70 } else { | |
71 browser = FileBrowseUI::OpenPopup(profile, | |
72 url, | |
73 FileBrowseUI::kPopupWidth, | |
74 FileBrowseUI::kPopupHeight); | |
75 } | |
76 | |
77 BrowserIterator iter = FindBrowserForPath(device_path); | |
78 if (iter == browsers_.end()) { | |
79 registrar_.Add(this, | |
80 NotificationType::BROWSER_CLOSED, | |
81 Source<Browser>(browser)); | |
82 BrowserWithPath new_browser; | |
83 new_browser.browser = browser; | |
84 new_browser.device_path = device_path; | |
85 browsers_.push_back(new_browser); | |
86 } else { | |
87 iter->browser = browser; | |
88 } | |
89 } | |
90 | |
91 void USBMountObserver::DiskChanged(MountLibraryEventType event, | |
92 const MountLibrary::Disk* disk) { | |
93 if (event == MOUNT_DISK_ADDED) { | |
94 OnDiskAdded(disk); | |
95 } else if (event == MOUNT_DISK_REMOVED) { | |
96 OnDiskRemoved(disk); | |
97 } else if (event == MOUNT_DISK_CHANGED) { | |
98 OnDiskChanged(disk); | |
99 } | |
100 } | |
101 | |
102 void USBMountObserver::DeviceChanged(MountLibraryEventType event, | |
103 const std::string& device_path) { | |
104 if (event == MOUNT_DEVICE_ADDED) { | |
105 OnDeviceAdded(device_path); | |
106 }else if (event == MOUNT_DEVICE_REMOVED) { | |
107 OnDeviceRemoved(device_path); | |
108 } else if (event == MOUNT_DEVICE_SCANNED) { | |
109 OnDeviceScanned(device_path); | |
110 } | |
111 } | |
112 | |
113 void USBMountObserver::FireFileSystemChanged( | |
114 const std::string& web_path) { | |
115 // TODO(zelidrag): Send message to all extensions that file system has | |
116 // changed. | |
117 return; | |
118 } | |
119 | |
120 void USBMountObserver::OnDiskAdded(const MountLibrary::Disk* disk) { | |
121 VLOG(1) << "Disk added: " << disk->device_path(); | |
122 if (disk->device_path().empty()) { | |
123 VLOG(1) << "Empty system path for " << disk->device_path(); | |
124 return; | |
125 } | |
126 if (disk->is_parent()) { | |
127 if (!disk->has_media()) | |
128 RemoveBrowserFromVector(disk->system_path()); | |
129 return; | |
130 } | |
131 | |
132 // If disk is not mounted yet, give it a try. | |
133 if (disk->mount_path().empty()) { | |
134 // Initiate disk mount operation. | |
135 chromeos::MountLibrary* lib = | |
136 chromeos::CrosLibrary::Get()->GetMountLibrary(); | |
137 lib->MountPath(disk->device_path().c_str()); | |
138 } | |
139 } | |
140 | |
141 void USBMountObserver::OnDiskRemoved(const MountLibrary::Disk* disk) { | |
142 VLOG(1) << "Disk removed: " << disk->device_path(); | |
143 RemoveBrowserFromVector(disk->system_path()); | |
144 MountPointMap::iterator iter = mounted_devices_.find(disk->device_path()); | |
145 if (iter == mounted_devices_.end()) | |
146 return; | |
147 | |
148 chromeos::MountLibrary* lib = | |
149 chromeos::CrosLibrary::Get()->GetMountLibrary(); | |
150 // TODO(zelidrag): This for some reason does not work as advertized. | |
151 // we might need to clean up mount directory on FILE thread here as well. | |
152 lib->UnmountPath(disk->device_path().c_str()); | |
153 | |
154 FireFileSystemChanged(iter->second); | |
155 mounted_devices_.erase(iter); | |
156 } | |
157 | |
158 void USBMountObserver::OnDiskChanged(const MountLibrary::Disk* disk) { | |
159 VLOG(1) << "Disk changed : " << disk->device_path(); | |
160 if (!disk->mount_path().empty()) { | |
161 // Remember this mount point. | |
162 mounted_devices_.insert( | |
163 std::pair<std::string, std::string>(disk->device_path(), | |
164 disk->mount_path())); | |
165 FireFileSystemChanged(disk->mount_path()); | |
166 | |
167 // TODO(zelidrag): We should remove old file browser stuff later. | |
168 // Doing second search to see if the current disk has already | |
169 // been popped up due to its parent device being plugged in. | |
170 BrowserIterator iter = FindBrowserForPath(disk->system_path()); | |
171 if (iter != browsers_.end() && iter->browser) { | |
172 std::string url = kFilebrowseURLHash; | |
173 url += disk->mount_path(); | |
174 TabContents* tab = iter->browser->GetSelectedTabContents(); | |
175 iter->browser->window()->SetBounds(gfx::Rect( | |
176 0, 0, FileBrowseUI::kPopupWidth, FileBrowseUI::kPopupHeight)); | |
177 tab->OpenURL(GURL(url), GURL(), CURRENT_TAB, | |
178 PageTransition::LINK); | |
179 tab->NavigateToPendingEntry(NavigationController::RELOAD); | |
180 iter->device_path = disk->device_path(); | |
181 iter->mount_path = disk->mount_path(); | |
182 } else { | |
183 OpenFileBrowse(disk->mount_path(), disk->device_path(), false); | |
184 } | |
185 } | |
186 } | |
187 | |
188 void USBMountObserver::OnDeviceAdded(const std::string& device_path) { | |
189 VLOG(1) << "Device added : " << device_path; | |
190 OpenFileBrowse(kFilebrowseScanning, device_path, true); | |
191 } | |
192 | |
193 void USBMountObserver::OnDeviceRemoved(const std::string& system_path) { | |
194 // New device is added, initiate disk rescan. | |
195 RemoveBrowserFromVector(system_path); | |
196 } | |
197 | |
198 void USBMountObserver::OnDeviceScanned(const std::string& device_path) { | |
199 VLOG(1) << "Device scanned : " << device_path; | |
200 } | |
201 | |
202 USBMountObserver::BrowserIterator USBMountObserver::FindBrowserForPath( | |
203 const std::string& path) { | |
204 for (BrowserIterator i = browsers_.begin();i != browsers_.end(); | |
205 ++i) { | |
206 const std::string& device_path = i->device_path; | |
207 // Doing a substring match so that we find if this new one is a subdevice | |
208 // of another already inserted device. | |
209 if (path.find(device_path) != std::string::npos) { | |
210 return i; | |
211 } | |
212 } | |
213 return browsers_.end(); | |
214 } | |
215 | |
216 void USBMountObserver::RemoveBrowserFromVector(const std::string& system_path) { | |
217 BrowserIterator i = FindBrowserForPath(system_path); | |
218 std::string mount_path; | |
219 if (i != browsers_.end()) { | |
220 registrar_.Remove(this, | |
221 NotificationType::BROWSER_CLOSED, | |
222 Source<Browser>(i->browser)); | |
223 mount_path = i->mount_path; | |
224 browsers_.erase(i); | |
225 } | |
226 std::vector<Browser*> close_these; | |
227 for (BrowserList::const_iterator it = BrowserList::begin(); | |
228 it != BrowserList::end(); ++it) { | |
229 if ((*it)->type() == Browser::TYPE_POPUP) { | |
230 if (*it && (*it)->GetTabContentsAt((*it)->selected_index())) { | |
231 const GURL& url = | |
232 (*it)->GetTabContentsAt((*it)->selected_index())->GetURL(); | |
233 if (url.SchemeIs(chrome::kChromeUIScheme) && | |
234 url.host() == chrome::kChromeUIFileBrowseHost && | |
235 url.ref().find(mount_path) != std::string::npos && | |
236 !mount_path.empty()) { | |
237 close_these.push_back(*it); | |
238 } | |
239 } | |
240 } | |
241 } | |
242 for (size_t x = 0; x < close_these.size(); x++) { | |
243 if (close_these[x]->window()) { | |
244 close_these[x]->window()->Close(); | |
245 } | |
246 } | |
247 } | |
248 | |
249 } // namespace chromeos | |
OLD | NEW |