| Index: chrome/renderer/render_view.cc | 
| =================================================================== | 
| --- chrome/renderer/render_view.cc	(revision 76768) | 
| +++ chrome/renderer/render_view.cc	(working copy) | 
| @@ -540,6 +540,7 @@ | 
| : params(p), | 
| completion(c) { | 
| } | 
| + | 
| ViewHostMsg_RunFileChooser_Params params; | 
| WebFileChooserCompletion* completion;  // MAY BE NULL to skip callback. | 
| }; | 
| @@ -591,6 +592,7 @@ | 
| spellcheck_provider_(NULL), | 
| accessibility_ack_pending_(false), | 
| p2p_socket_dispatcher_(NULL), | 
| +      enumeration_completion_id_(0), | 
| pending_app_icon_requests_(0), | 
| session_storage_namespace_id_(session_storage_namespace_id) { | 
| #if defined(OS_MACOSX) | 
| @@ -690,7 +692,8 @@ | 
| if (decrement_shared_popup_at_destruction_) | 
| shared_popup_counter_->data--; | 
|  | 
| -  // If file chooser is still waiting for answer, dispatch empty answer. | 
| +  // If file chooser or directory enumeration | 
| +  // is still waiting for answer, dispatch empty answer. | 
| while (!file_chooser_completions_.empty()) { | 
| if (file_chooser_completions_.front()->completion) { | 
| file_chooser_completions_.front()->completion->didChooseFile( | 
| @@ -699,6 +702,14 @@ | 
| file_chooser_completions_.pop_front(); | 
| } | 
|  | 
| +  while (!enumeration_completions_.empty()) { | 
| +    if (enumeration_completions_.begin()->second) { | 
| +      enumeration_completions_.begin()->second->didChooseFile( | 
| +          WebVector<WebString>()); | 
| +    } | 
| +    enumeration_completions_.erase(enumeration_completions_.begin()); | 
| +  } | 
| + | 
| #if defined(OS_MACOSX) | 
| // Tell the spellchecker that the document is closed. | 
| if (has_document_tag_) | 
| @@ -1060,6 +1071,8 @@ | 
| IPC_MESSAGE_HANDLER(ViewMsg_DisplayPrerenderedPage, | 
| OnDisplayPrerenderedPage) | 
| IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse) | 
| +    IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse, | 
| +                        OnEnumerateDirectoryResponse) | 
| IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode) | 
| IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage, | 
| OnGetAllSavableResourceLinksForCurrentPage) | 
| @@ -2368,6 +2381,17 @@ | 
| word)); | 
| } | 
|  | 
| +bool RenderView::enumerateDirectory( | 
| +    const WebString& path, | 
| +    WebFileChooserCompletion* chooser_completion) { | 
| +  int id = enumeration_completion_id_++; | 
| +  enumeration_completions_[id] = chooser_completion; | 
| +  return Send(new ViewHostMsg_EnumerateDirectory( | 
| +      routing_id_, | 
| +      id, | 
| +      webkit_glue::WebStringToFilePath(path))); | 
| +} | 
| + | 
| void RenderView::continuousSpellCheckingEnabledStateChanged() { | 
| UpdateToggleSpellCheckCommandState(); | 
| } | 
| @@ -4737,6 +4761,20 @@ | 
| } | 
| } | 
|  | 
| +void RenderView::OnEnumerateDirectoryResponse( | 
| +    int id, | 
| +    const std::vector<FilePath>& paths) { | 
| +  if (!enumeration_completions_[id]) | 
| +    return; | 
| + | 
| +  WebVector<WebString> ws_file_names(paths.size()); | 
| +  for (size_t i = 0; i < paths.size(); ++i) | 
| +    ws_file_names[i] = webkit_glue::FilePathToWebString(paths[i]); | 
| + | 
| +  enumeration_completions_[id]->didChooseFile(ws_file_names); | 
| +  enumeration_completions_.erase(id); | 
| +} | 
| + | 
| void RenderView::OnFileChooserResponse(const std::vector<FilePath>& paths) { | 
| // This could happen if we navigated to a different page before the user | 
| // closed the chooser. | 
|  |