| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. |
| 3 * Copyright (C) 2010 Google Inc. All rights reserved. | 3 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 #include "platform/text/PlatformLocale.h" | 41 #include "platform/text/PlatformLocale.h" |
| 42 #include "wtf/PassOwnPtr.h" | 42 #include "wtf/PassOwnPtr.h" |
| 43 #include "wtf/text/StringBuilder.h" | 43 #include "wtf/text/StringBuilder.h" |
| 44 #include "wtf/text/WTFString.h" | 44 #include "wtf/text/WTFString.h" |
| 45 | 45 |
| 46 namespace WebCore { | 46 namespace WebCore { |
| 47 | 47 |
| 48 using WebKit::WebLocalizedString; | 48 using WebKit::WebLocalizedString; |
| 49 using namespace HTMLNames; | 49 using namespace HTMLNames; |
| 50 | 50 |
| 51 inline FileInputType::FileInputType(HTMLInputElement* element) | 51 inline FileInputType::FileInputType(HTMLInputElement& element) |
| 52 : BaseClickableWithKeyInputType(element) | 52 : BaseClickableWithKeyInputType(element) |
| 53 , m_fileList(FileList::create()) | 53 , m_fileList(FileList::create()) |
| 54 { | 54 { |
| 55 } | 55 } |
| 56 | 56 |
| 57 PassRefPtr<InputType> FileInputType::create(HTMLInputElement* element) | 57 PassRefPtr<InputType> FileInputType::create(HTMLInputElement& element) |
| 58 { | 58 { |
| 59 return adoptRef(new FileInputType(element)); | 59 return adoptRef(new FileInputType(element)); |
| 60 } | 60 } |
| 61 | 61 |
| 62 Vector<FileChooserFileInfo> FileInputType::filesFromFormControlState(const FormC
ontrolState& state) | 62 Vector<FileChooserFileInfo> FileInputType::filesFromFormControlState(const FormC
ontrolState& state) |
| 63 { | 63 { |
| 64 Vector<FileChooserFileInfo> files; | 64 Vector<FileChooserFileInfo> files; |
| 65 for (size_t i = 0; i < state.valueSize(); i += 2) { | 65 for (size_t i = 0; i < state.valueSize(); i += 2) { |
| 66 if (!state[i + 1].isEmpty()) | 66 if (!state[i + 1].isEmpty()) |
| 67 files.append(FileChooserFileInfo(state[i], state[i + 1])); | 67 files.append(FileChooserFileInfo(state[i], state[i + 1])); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 91 | 91 |
| 92 void FileInputType::restoreFormControlState(const FormControlState& state) | 92 void FileInputType::restoreFormControlState(const FormControlState& state) |
| 93 { | 93 { |
| 94 if (state.valueSize() % 2) | 94 if (state.valueSize() % 2) |
| 95 return; | 95 return; |
| 96 filesChosen(filesFromFormControlState(state)); | 96 filesChosen(filesFromFormControlState(state)); |
| 97 } | 97 } |
| 98 | 98 |
| 99 bool FileInputType::appendFormData(FormDataList& encoding, bool multipart) const | 99 bool FileInputType::appendFormData(FormDataList& encoding, bool multipart) const |
| 100 { | 100 { |
| 101 FileList* fileList = element()->files(); | 101 FileList* fileList = element().files(); |
| 102 unsigned numFiles = fileList->length(); | 102 unsigned numFiles = fileList->length(); |
| 103 if (!multipart) { | 103 if (!multipart) { |
| 104 // Send only the basenames. | 104 // Send only the basenames. |
| 105 // 4.10.16.4 and 4.10.16.6 sections in HTML5. | 105 // 4.10.16.4 and 4.10.16.6 sections in HTML5. |
| 106 | 106 |
| 107 // Unlike the multipart case, we have no special handling for the empty | 107 // Unlike the multipart case, we have no special handling for the empty |
| 108 // fileList because Netscape doesn't support for non-multipart | 108 // fileList because Netscape doesn't support for non-multipart |
| 109 // submission of file inputs, and Firefox doesn't add "name=" query | 109 // submission of file inputs, and Firefox doesn't add "name=" query |
| 110 // parameter. | 110 // parameter. |
| 111 for (unsigned i = 0; i < numFiles; ++i) | 111 for (unsigned i = 0; i < numFiles; ++i) |
| 112 encoding.appendData(element()->name(), fileList->item(i)->name()); | 112 encoding.appendData(element().name(), fileList->item(i)->name()); |
| 113 return true; | 113 return true; |
| 114 } | 114 } |
| 115 | 115 |
| 116 // If no filename at all is entered, return successful but empty. | 116 // If no filename at all is entered, return successful but empty. |
| 117 // Null would be more logical, but Netscape posts an empty file. Argh. | 117 // Null would be more logical, but Netscape posts an empty file. Argh. |
| 118 if (!numFiles) { | 118 if (!numFiles) { |
| 119 encoding.appendBlob(element()->name(), File::create("")); | 119 encoding.appendBlob(element().name(), File::create("")); |
| 120 return true; | 120 return true; |
| 121 } | 121 } |
| 122 | 122 |
| 123 for (unsigned i = 0; i < numFiles; ++i) | 123 for (unsigned i = 0; i < numFiles; ++i) |
| 124 encoding.appendBlob(element()->name(), fileList->item(i)); | 124 encoding.appendBlob(element().name(), fileList->item(i)); |
| 125 return true; | 125 return true; |
| 126 } | 126 } |
| 127 | 127 |
| 128 bool FileInputType::valueMissing(const String& value) const | 128 bool FileInputType::valueMissing(const String& value) const |
| 129 { | 129 { |
| 130 return element()->isRequired() && value.isEmpty(); | 130 return element().isRequired() && value.isEmpty(); |
| 131 } | 131 } |
| 132 | 132 |
| 133 String FileInputType::valueMissingText() const | 133 String FileInputType::valueMissingText() const |
| 134 { | 134 { |
| 135 return locale().queryString(element()->multiple() ? WebLocalizedString::Vali
dationValueMissingForMultipleFile : WebLocalizedString::ValidationValueMissingFo
rFile); | 135 return locale().queryString(element().multiple() ? WebLocalizedString::Valid
ationValueMissingForMultipleFile : WebLocalizedString::ValidationValueMissingFor
File); |
| 136 } | 136 } |
| 137 | 137 |
| 138 void FileInputType::handleDOMActivateEvent(Event* event) | 138 void FileInputType::handleDOMActivateEvent(Event* event) |
| 139 { | 139 { |
| 140 if (element()->isDisabledFormControl()) | 140 if (element().isDisabledFormControl()) |
| 141 return; | 141 return; |
| 142 | 142 |
| 143 if (!UserGestureIndicator::processingUserGesture()) | 143 if (!UserGestureIndicator::processingUserGesture()) |
| 144 return; | 144 return; |
| 145 | 145 |
| 146 if (Chrome* chrome = this->chrome()) { | 146 if (Chrome* chrome = this->chrome()) { |
| 147 FileChooserSettings settings; | 147 FileChooserSettings settings; |
| 148 HTMLInputElement* input = element(); | 148 HTMLInputElement& input = element(); |
| 149 settings.allowsDirectoryUpload = RuntimeEnabledFeatures::directoryUpload
Enabled() && input->fastHasAttribute(webkitdirectoryAttr); | 149 settings.allowsDirectoryUpload = RuntimeEnabledFeatures::directoryUpload
Enabled() && input.fastHasAttribute(webkitdirectoryAttr); |
| 150 settings.allowsMultipleFiles = settings.allowsDirectoryUpload || input->
fastHasAttribute(multipleAttr); | 150 settings.allowsMultipleFiles = settings.allowsDirectoryUpload || input.f
astHasAttribute(multipleAttr); |
| 151 settings.acceptMIMETypes = input->acceptMIMETypes(); | 151 settings.acceptMIMETypes = input.acceptMIMETypes(); |
| 152 settings.acceptFileExtensions = input->acceptFileExtensions(); | 152 settings.acceptFileExtensions = input.acceptFileExtensions(); |
| 153 settings.selectedFiles = m_fileList->paths(); | 153 settings.selectedFiles = m_fileList->paths(); |
| 154 #if ENABLE(MEDIA_CAPTURE) | 154 #if ENABLE(MEDIA_CAPTURE) |
| 155 settings.useMediaCapture = input->capture(); | 155 settings.useMediaCapture = input.capture(); |
| 156 #endif | 156 #endif |
| 157 chrome->runOpenPanel(input->document().frame(), newFileChooser(settings)
); | 157 chrome->runOpenPanel(input.document().frame(), newFileChooser(settings))
; |
| 158 } | 158 } |
| 159 event->setDefaultHandled(); | 159 event->setDefaultHandled(); |
| 160 } | 160 } |
| 161 | 161 |
| 162 RenderObject* FileInputType::createRenderer(RenderStyle*) const | 162 RenderObject* FileInputType::createRenderer(RenderStyle*) const |
| 163 { | 163 { |
| 164 return new RenderFileUploadControl(element()); | 164 return new RenderFileUploadControl(&element()); |
| 165 } | 165 } |
| 166 | 166 |
| 167 bool FileInputType::canSetStringValue() const | 167 bool FileInputType::canSetStringValue() const |
| 168 { | 168 { |
| 169 return false; | 169 return false; |
| 170 } | 170 } |
| 171 | 171 |
| 172 FileList* FileInputType::files() | 172 FileList* FileInputType::files() |
| 173 { | 173 { |
| 174 return m_fileList.get(); | 174 return m_fileList.get(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 196 // decided to try to parse the value by looking for backslashes | 196 // decided to try to parse the value by looking for backslashes |
| 197 // (because that's what Windows file paths use). To be compatible | 197 // (because that's what Windows file paths use). To be compatible |
| 198 // with that code, we make up a fake path for the file. | 198 // with that code, we make up a fake path for the file. |
| 199 value = "C:\\fakepath\\" + m_fileList->item(0)->name(); | 199 value = "C:\\fakepath\\" + m_fileList->item(0)->name(); |
| 200 return true; | 200 return true; |
| 201 } | 201 } |
| 202 | 202 |
| 203 void FileInputType::setValue(const String&, bool, TextFieldEventBehavior) | 203 void FileInputType::setValue(const String&, bool, TextFieldEventBehavior) |
| 204 { | 204 { |
| 205 m_fileList->clear(); | 205 m_fileList->clear(); |
| 206 element()->setNeedsStyleRecalc(); | 206 element().setNeedsStyleRecalc(); |
| 207 } | 207 } |
| 208 | 208 |
| 209 PassRefPtr<FileList> FileInputType::createFileList(const Vector<FileChooserFileI
nfo>& files) const | 209 PassRefPtr<FileList> FileInputType::createFileList(const Vector<FileChooserFileI
nfo>& files) const |
| 210 { | 210 { |
| 211 RefPtr<FileList> fileList(FileList::create()); | 211 RefPtr<FileList> fileList(FileList::create()); |
| 212 size_t size = files.size(); | 212 size_t size = files.size(); |
| 213 | 213 |
| 214 // If a directory is being selected, the UI allows a directory to be chosen | 214 // If a directory is being selected, the UI allows a directory to be chosen |
| 215 // and the paths provided here share a root directory somewhere up the tree; | 215 // and the paths provided here share a root directory somewhere up the tree; |
| 216 // we want to store only the relative paths from that point. | 216 // we want to store only the relative paths from that point. |
| 217 if (size && element()->fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabl
edFeatures::directoryUploadEnabled()) { | 217 if (size && element().fastHasAttribute(webkitdirectoryAttr) && RuntimeEnable
dFeatures::directoryUploadEnabled()) { |
| 218 // Find the common root path. | 218 // Find the common root path. |
| 219 String rootPath = directoryName(files[0].path); | 219 String rootPath = directoryName(files[0].path); |
| 220 for (size_t i = 1; i < size; i++) { | 220 for (size_t i = 1; i < size; i++) { |
| 221 while (!files[i].path.startsWith(rootPath)) | 221 while (!files[i].path.startsWith(rootPath)) |
| 222 rootPath = directoryName(rootPath); | 222 rootPath = directoryName(rootPath); |
| 223 } | 223 } |
| 224 rootPath = directoryName(rootPath); | 224 rootPath = directoryName(rootPath); |
| 225 ASSERT(rootPath.length()); | 225 ASSERT(rootPath.length()); |
| 226 int rootLength = rootPath.length(); | 226 int rootLength = rootPath.length(); |
| 227 if (rootPath[rootLength - 1] != '\\' && rootPath[rootLength - 1] != '/') | 227 if (rootPath[rootLength - 1] != '\\' && rootPath[rootLength - 1] != '/') |
| (...skipping 11 matching lines...) Expand all Loading... |
| 239 return fileList; | 239 return fileList; |
| 240 } | 240 } |
| 241 | 241 |
| 242 bool FileInputType::isFileUpload() const | 242 bool FileInputType::isFileUpload() const |
| 243 { | 243 { |
| 244 return true; | 244 return true; |
| 245 } | 245 } |
| 246 | 246 |
| 247 void FileInputType::createShadowSubtree() | 247 void FileInputType::createShadowSubtree() |
| 248 { | 248 { |
| 249 ASSERT(element()->shadow()); | 249 ASSERT(element().shadow()); |
| 250 RefPtr<HTMLInputElement> button = HTMLInputElement::create(inputTag, element
()->document(), 0, false); | 250 RefPtr<HTMLInputElement> button = HTMLInputElement::create(inputTag, element
().document(), 0, false); |
| 251 button->setType(InputTypeNames::button()); | 251 button->setType(InputTypeNames::button()); |
| 252 button->setAttribute(valueAttr, locale().queryString(element()->multiple() ?
WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString::Fi
leButtonChooseFileLabel)); | 252 button->setAttribute(valueAttr, locale().queryString(element().multiple() ?
WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString::Fil
eButtonChooseFileLabel)); |
| 253 button->setPart(AtomicString("-webkit-file-upload-button", AtomicString::Con
structFromLiteral)); | 253 button->setPart(AtomicString("-webkit-file-upload-button", AtomicString::Con
structFromLiteral)); |
| 254 element()->userAgentShadowRoot()->appendChild(button.release()); | 254 element().userAgentShadowRoot()->appendChild(button.release()); |
| 255 } | 255 } |
| 256 | 256 |
| 257 void FileInputType::disabledAttributeChanged() | 257 void FileInputType::disabledAttributeChanged() |
| 258 { | 258 { |
| 259 ASSERT(element()->shadow()); | 259 ASSERT(element().shadow()); |
| 260 if (Element* button = toElement(element()->userAgentShadowRoot()->firstChild
())) | 260 if (Element* button = toElement(element().userAgentShadowRoot()->firstChild(
))) |
| 261 button->setBooleanAttribute(disabledAttr, element()->isDisabledFormContr
ol()); | 261 button->setBooleanAttribute(disabledAttr, element().isDisabledFormContro
l()); |
| 262 } | 262 } |
| 263 | 263 |
| 264 void FileInputType::multipleAttributeChanged() | 264 void FileInputType::multipleAttributeChanged() |
| 265 { | 265 { |
| 266 ASSERT(element()->shadow()); | 266 ASSERT(element().shadow()); |
| 267 if (Element* button = toElement(element()->userAgentShadowRoot()->firstChild
())) | 267 if (Element* button = toElement(element().userAgentShadowRoot()->firstChild(
))) |
| 268 button->setAttribute(valueAttr, locale().queryString(element()->multiple
() ? WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString
::FileButtonChooseFileLabel)); | 268 button->setAttribute(valueAttr, locale().queryString(element().multiple(
) ? WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString:
:FileButtonChooseFileLabel)); |
| 269 } | 269 } |
| 270 | 270 |
| 271 void FileInputType::setFiles(PassRefPtr<FileList> files) | 271 void FileInputType::setFiles(PassRefPtr<FileList> files) |
| 272 { | 272 { |
| 273 if (!files) | 273 if (!files) |
| 274 return; | 274 return; |
| 275 | 275 |
| 276 RefPtr<HTMLInputElement> input = element(); | 276 RefPtr<HTMLInputElement> input(element()); |
| 277 | 277 |
| 278 bool pathsChanged = false; | 278 bool pathsChanged = false; |
| 279 if (files->length() != m_fileList->length()) { | 279 if (files->length() != m_fileList->length()) { |
| 280 pathsChanged = true; | 280 pathsChanged = true; |
| 281 } else { | 281 } else { |
| 282 for (unsigned i = 0; i < files->length(); ++i) { | 282 for (unsigned i = 0; i < files->length(); ++i) { |
| 283 if (files->item(i)->path() != m_fileList->item(i)->path()) { | 283 if (files->item(i)->path() != m_fileList->item(i)->path()) { |
| 284 pathsChanged = true; | 284 pathsChanged = true; |
| 285 break; | 285 break; |
| 286 } | 286 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 310 | 310 |
| 311 void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& files) | 311 void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& files) |
| 312 { | 312 { |
| 313 setFiles(createFileList(files)); | 313 setFiles(createFileList(files)); |
| 314 } | 314 } |
| 315 | 315 |
| 316 void FileInputType::receiveDropForDirectoryUpload(const Vector<String>& paths) | 316 void FileInputType::receiveDropForDirectoryUpload(const Vector<String>& paths) |
| 317 { | 317 { |
| 318 if (Chrome* chrome = this->chrome()) { | 318 if (Chrome* chrome = this->chrome()) { |
| 319 FileChooserSettings settings; | 319 FileChooserSettings settings; |
| 320 HTMLInputElement* input = element(); | 320 HTMLInputElement& input = element(); |
| 321 settings.allowsDirectoryUpload = true; | 321 settings.allowsDirectoryUpload = true; |
| 322 settings.allowsMultipleFiles = true; | 322 settings.allowsMultipleFiles = true; |
| 323 settings.selectedFiles.append(paths[0]); | 323 settings.selectedFiles.append(paths[0]); |
| 324 settings.acceptMIMETypes = input->acceptMIMETypes(); | 324 settings.acceptMIMETypes = input.acceptMIMETypes(); |
| 325 settings.acceptFileExtensions = input->acceptFileExtensions(); | 325 settings.acceptFileExtensions = input.acceptFileExtensions(); |
| 326 chrome->enumerateChosenDirectory(newFileChooser(settings)); | 326 chrome->enumerateChosenDirectory(newFileChooser(settings)); |
| 327 } | 327 } |
| 328 } | 328 } |
| 329 | 329 |
| 330 bool FileInputType::receiveDroppedFiles(const DragData* dragData) | 330 bool FileInputType::receiveDroppedFiles(const DragData* dragData) |
| 331 { | 331 { |
| 332 Vector<String> paths; | 332 Vector<String> paths; |
| 333 dragData->asFilenames(paths); | 333 dragData->asFilenames(paths); |
| 334 if (paths.isEmpty()) | 334 if (paths.isEmpty()) |
| 335 return false; | 335 return false; |
| 336 | 336 |
| 337 HTMLInputElement* input = element(); | 337 HTMLInputElement& input = element(); |
| 338 if (input->fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::
directoryUploadEnabled()) { | 338 if (input.fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::d
irectoryUploadEnabled()) { |
| 339 receiveDropForDirectoryUpload(paths); | 339 receiveDropForDirectoryUpload(paths); |
| 340 return true; | 340 return true; |
| 341 } | 341 } |
| 342 | 342 |
| 343 m_droppedFileSystemId = dragData->droppedFileSystemId(); | 343 m_droppedFileSystemId = dragData->droppedFileSystemId(); |
| 344 | 344 |
| 345 Vector<FileChooserFileInfo> files; | 345 Vector<FileChooserFileInfo> files; |
| 346 for (unsigned i = 0; i < paths.size(); ++i) | 346 for (unsigned i = 0; i < paths.size(); ++i) |
| 347 files.append(FileChooserFileInfo(paths[i])); | 347 files.append(FileChooserFileInfo(paths[i])); |
| 348 | 348 |
| 349 if (input->fastHasAttribute(multipleAttr)) { | 349 if (input.fastHasAttribute(multipleAttr)) { |
| 350 filesChosen(files); | 350 filesChosen(files); |
| 351 } else { | 351 } else { |
| 352 Vector<FileChooserFileInfo> firstFileOnly; | 352 Vector<FileChooserFileInfo> firstFileOnly; |
| 353 firstFileOnly.append(files[0]); | 353 firstFileOnly.append(files[0]); |
| 354 filesChosen(firstFileOnly); | 354 filesChosen(firstFileOnly); |
| 355 } | 355 } |
| 356 return true; | 356 return true; |
| 357 } | 357 } |
| 358 | 358 |
| 359 String FileInputType::droppedFileSystemId() | 359 String FileInputType::droppedFileSystemId() |
| (...skipping 12 matching lines...) Expand all Loading... |
| 372 StringBuilder names; | 372 StringBuilder names; |
| 373 for (size_t i = 0; i < listSize; ++i) { | 373 for (size_t i = 0; i < listSize; ++i) { |
| 374 names.append(fileList->item(i)->name()); | 374 names.append(fileList->item(i)->name()); |
| 375 if (i != listSize - 1) | 375 if (i != listSize - 1) |
| 376 names.append('\n'); | 376 names.append('\n'); |
| 377 } | 377 } |
| 378 return names.toString(); | 378 return names.toString(); |
| 379 } | 379 } |
| 380 | 380 |
| 381 } // namespace WebCore | 381 } // namespace WebCore |
| OLD | NEW |