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/ui/webui/screenshot_source.h" 6 7 #include "base/file_util.h" 8 #include "base/memory/ref_counted_memory.h" 9 #include "base/path_service.h" 10 #include "base/synchronization/waitable_event.h" 11 #include "base/task.h" 12 #include "chrome/common/chrome_paths.h" 13 #include "chrome/common/url_constants.h" 14 #include "content/browser/browser_thread.h" 15 16 static const char kCurrentScreenshot[] = "current"; 17 #if defined(OS_CHROMEOS) 18 static const char kSavedScreenshots[] = "saved/"; 19 #endif 20 21 static const char kScreenshotsRelativePath[] = "/Screenshots/"; 22 23 #if defined(OS_CHROMEOS) 24 // Read the file from the screenshots directory into the read_bytes vector. 25 void ReadScreenshot(const std::string& filename, 26 std::vector<unsigned char>* read_bytes, 27 base::WaitableEvent* read_complete) { 28 read_bytes->clear(); 29 30 FilePath fileshelf_path; 31 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &fileshelf_path)) { 32 read_complete->Signal(); 33 return; 34 } 35 36 FilePath file(fileshelf_path.value() + std::string(kScreenshotsRelativePath) + 37 filename); 38 39 int64 file_size = 0; 40 if (!file_util::GetFileSize(file, &file_size)) { 41 read_complete->Signal(); 42 return; 43 } 44 45 // expand vector to file size 46 read_bytes->resize(file_size); 47 // read file into the vector 48 int bytes_read = 0; 49 if (!(bytes_read = file_util::ReadFile(file, 50 reinterpret_cast<char*>( 51 &read_bytes->front()), 52 static_cast<int>(file_size)))) 53 read_bytes->clear(); 54 55 // We're done, if successful, read_bytes will have the data 56 // otherwise, it'll be empty. 57 read_complete->Signal(); 58 } 59 60 // Get a saved screenshot - read on the FILE thread. 61 std::vector<unsigned char> GetSavedScreenshot(std::string filename) { 62 base::WaitableEvent read_complete(true, false); 63 std::vector<unsigned char> bytes; 64 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 65 NewRunnableFunction(&ReadScreenshot, filename, 66 &bytes, &read_complete)); 67 read_complete.Wait(); 68 return bytes; 69 } 70 #endif 71 72 std::vector<unsigned char> ScreenshotSource::GetScreenshot( 73 const std::string& full_path) { 74 // Strip the query param value - we only use it as a hack to ensure our 75 // image gets reloaded instead of being pulled from the browser cache 76 std::string path = full_path.substr(0, full_path.find_first_of("?")); 77 if (path == kCurrentScreenshot) { 78 return current_screenshot_; 79 #if defined(OS_CHROMEOS) 80 } else if (path.compare(0, strlen(kSavedScreenshots), 81 kSavedScreenshots) == 0) { 82 // Split the saved screenshot filename from the path 83 std::string filename = path.substr(strlen(kSavedScreenshots)); 84 85 return GetSavedScreenshot(filename); 86 #endif 87 } else { 88 std::vector<unsigned char> ret; 89 // TODO(rkc): Weird vc bug, return std::vector<unsigned char>() causes 90 // the object assigned to the return value of this function magically 91 // change it's address 0x0; look into this eventually. 92 return ret; 93 } 94 } 95 96 ScreenshotSource::ScreenshotSource( 97 std::vector<unsigned char>* current_screenshot) 98 : DataSource(chrome::kChromeUIScreenshotPath, MessageLoop::current()) { 99 // Setup the last screenshot taken. 100 if (current_screenshot) 101 current_screenshot_ = *current_screenshot; 102 else 103 current_screenshot_.clear(); 104 } 105 106 ScreenshotSource::~ScreenshotSource() {} 107 108 void ScreenshotSource::StartDataRequest(const std::string& path, 109 bool is_incognito, 110 int request_id) { 111 SendResponse(request_id, new RefCountedBytes(GetScreenshot(path))); 112 } 113 114 std::string ScreenshotSource::GetMimeType(const std::string&) const { 115 // We need to explicitly return a mime type, otherwise if the user tries to 116 // drag the image they get no extension. 117 return "image/png"; 118 } 119