Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: ui/base/dragdrop/os_exchange_data_provider_win.cc

Issue 13979012: Fix deadlock between UI thread and drag and drop thread on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Stage cleanups into a separate patch Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/base/dragdrop/os_exchange_data_provider_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" 5 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 } 483 }
484 484
485 bool OSExchangeDataProviderWin::HasCustomFormat(CLIPFORMAT format) const { 485 bool OSExchangeDataProviderWin::HasCustomFormat(CLIPFORMAT format) const {
486 FORMATETC format_etc = 486 FORMATETC format_etc =
487 { format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; 487 { format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
488 return (source_object_->QueryGetData(&format_etc) == S_OK); 488 return (source_object_->QueryGetData(&format_etc) == S_OK);
489 } 489 }
490 490
491 void OSExchangeDataProviderWin::SetDownloadFileInfo( 491 void OSExchangeDataProviderWin::SetDownloadFileInfo(
492 const OSExchangeData::DownloadFileInfo& download) { 492 const OSExchangeData::DownloadFileInfo& download) {
493 // If the filename is not provided, set stoarge to NULL to indicate that 493 // If the filename is not provided, set storage to NULL to indicate that
494 // the delay rendering will be used. 494 // the delay rendering will be used.
495 // TODO(dcheng): Is it actually possible for filename to be empty here? I
496 // think we always synthesize one in WebContentsDragWin.
495 STGMEDIUM* storage = NULL; 497 STGMEDIUM* storage = NULL;
496 if (!download.filename.empty()) 498 if (!download.filename.empty())
497 storage = GetStorageForFileName(download.filename); 499 storage = GetStorageForFileName(download.filename);
498 500
499 // Add CF_HDROP. 501 // Add CF_HDROP.
500 DataObjectImpl::StoredDataInfo* info = new DataObjectImpl::StoredDataInfo( 502 DataObjectImpl::StoredDataInfo* info = new DataObjectImpl::StoredDataInfo(
501 ClipboardUtil::GetCFHDropFormat()->cfFormat, storage); 503 ClipboardUtil::GetCFHDropFormat()->cfFormat, storage);
502 info->downloader = download.downloader; 504 info->downloader = download.downloader;
503 data_->contents_.push_back(info); 505 data_->contents_.push_back(info);
504 } 506 }
505 507
508 void OSExchangeDataProviderWin::SetInDragLoop(bool in_drag_loop) {
509 data_->set_in_drag_loop(in_drag_loop);
510 }
511
506 #if defined(USE_AURA) 512 #if defined(USE_AURA)
507 513
508 void OSExchangeDataProviderWin::SetDragImage( 514 void OSExchangeDataProviderWin::SetDragImage(
509 const gfx::ImageSkia& image, 515 const gfx::ImageSkia& image,
510 const gfx::Vector2d& cursor_offset) { 516 const gfx::Vector2d& cursor_offset) {
511 drag_image_ = image; 517 drag_image_ = image;
512 drag_image_offset_ = cursor_offset; 518 drag_image_offset_ = cursor_offset;
513 } 519 }
514 520
515 const gfx::ImageSkia& OSExchangeDataProviderWin::GetDragImage() const { 521 const gfx::ImageSkia& OSExchangeDataProviderWin::GetDragImage() const {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 break; 596 break;
591 } 597 }
592 598
593 destination->tymed = source->tymed; 599 destination->tymed = source->tymed;
594 destination->pUnkForRelease = source->pUnkForRelease; 600 destination->pUnkForRelease = source->pUnkForRelease;
595 if (destination->pUnkForRelease) 601 if (destination->pUnkForRelease)
596 destination->pUnkForRelease->AddRef(); 602 destination->pUnkForRelease->AddRef();
597 } 603 }
598 604
599 DataObjectImpl::DataObjectImpl() 605 DataObjectImpl::DataObjectImpl()
600 : is_aborting_(false), 606 : is_aborting_(false),
jianli 2013/04/26 01:07:18 in_drag_loop_ is not initialized.
dcheng 2013/04/26 18:05:44 Done.
601 in_async_mode_(false), 607 in_async_mode_(false),
602 async_operation_started_(false), 608 async_operation_started_(false),
603 observer_(NULL) { 609 observer_(NULL) {
604 } 610 }
605 611
606 DataObjectImpl::~DataObjectImpl() { 612 DataObjectImpl::~DataObjectImpl() {
607 StopDownloads(); 613 StopDownloads();
608 STLDeleteContainerPointers(contents_.begin(), contents_.end()); 614 STLDeleteContainerPointers(contents_.begin(), contents_.end());
609 if (observer_) 615 if (observer_)
610 observer_->OnDataObjectDisposed(); 616 observer_->OnDataObjectDisposed();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 673
668 StoredData::iterator iter = contents_.begin(); 674 StoredData::iterator iter = contents_.begin();
669 while (iter != contents_.end()) { 675 while (iter != contents_.end()) {
670 if ((*iter)->format_etc.cfFormat == format_etc->cfFormat && 676 if ((*iter)->format_etc.cfFormat == format_etc->cfFormat &&
671 (*iter)->format_etc.lindex == format_etc->lindex && 677 (*iter)->format_etc.lindex == format_etc->lindex &&
672 ((*iter)->format_etc.tymed & format_etc->tymed)) { 678 ((*iter)->format_etc.tymed & format_etc->tymed)) {
673 // If medium is NULL, delay-rendering will be used. 679 // If medium is NULL, delay-rendering will be used.
674 if ((*iter)->medium) { 680 if ((*iter)->medium) {
675 DuplicateMedium((*iter)->format_etc.cfFormat, (*iter)->medium, medium); 681 DuplicateMedium((*iter)->format_etc.cfFormat, (*iter)->medium, medium);
676 } else { 682 } else {
677 // Check if the left button is down. 683 // Fail all GetData() attempts for DownloadURL data if the drag and drop
678 bool is_left_button_down = (GetKeyState(VK_LBUTTON) & 0x8000) != 0; 684 // operation is still in progress.
685 if (in_drag_loop_)
686 return DV_E_FORMATETC;
679 687
680 bool wait_for_data = false; 688 bool wait_for_data = false;
681 if ((*iter)->in_delay_rendering) {
682 // Make sure the left button is up. Sometimes the drop target, like
683 // Shell, might be too aggresive in calling GetData when the left
684 // button is not released.
685 if (is_left_button_down)
686 return DV_E_FORMATETC;
687 689
688 // In async mode, we do not want to start waiting for the data before 690 // In async mode, we do not want to start waiting for the data before
689 // the async operation is started. This is because we want to postpone 691 // the async operation is started. This is because we want to postpone
690 // until Shell kicks off a background thread to do the work so that 692 // until Shell kicks off a background thread to do the work so that
691 // we do not block the UI thread. 693 // we do not block the UI thread.
692 if (!in_async_mode_ || async_operation_started_) 694 if (!in_async_mode_ || async_operation_started_)
693 wait_for_data = true; 695 wait_for_data = true;
694 } else {
695 // If the left button is up and the target has not requested the data
696 // yet, it probably means that the target does not support delay-
697 // rendering. So instead, we wait for the data.
698 if (is_left_button_down) {
jianli 2013/04/26 01:07:18 I am a bit concerned about this logic being remove
dcheng 2013/04/26 18:05:44 I have tested on XP, Vista, 7, and 8, and it works
699 (*iter)->in_delay_rendering = true;
700 memset(medium, 0, sizeof(STGMEDIUM));
701 } else {
702 wait_for_data = true;
703 }
704 }
705 696
706 if (!wait_for_data) 697 if (!wait_for_data)
707 return DV_E_FORMATETC; 698 return DV_E_FORMATETC;
708 699
709 // Notify the observer we start waiting for the data. This gives 700 // Notify the observer we start waiting for the data. This gives
710 // an observer a chance to end the drag and drop. 701 // an observer a chance to end the drag and drop.
711 if (observer_) 702 if (observer_)
712 observer_->OnWaitForData(); 703 observer_->OnWaitForData();
713 704
714 // Now we can start the download. 705 // Now we can start the download.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 *local_medium = *medium; 753 *local_medium = *medium;
763 } else { 754 } else {
764 DuplicateMedium(format_etc->cfFormat, medium, local_medium); 755 DuplicateMedium(format_etc->cfFormat, medium, local_medium);
765 } 756 }
766 757
767 DataObjectImpl::StoredDataInfo* info = 758 DataObjectImpl::StoredDataInfo* info =
768 new DataObjectImpl::StoredDataInfo(format_etc->cfFormat, local_medium); 759 new DataObjectImpl::StoredDataInfo(format_etc->cfFormat, local_medium);
769 info->medium->tymed = format_etc->tymed; 760 info->medium->tymed = format_etc->tymed;
770 info->owns_medium = !!should_release; 761 info->owns_medium = !!should_release;
771 // Make newly added data appear first. 762 // Make newly added data appear first.
763 // TODO(dcheng): Make various setters agree whether elements should be
764 // prioritized from front to back or back to front.
772 contents_.insert(contents_.begin(), info); 765 contents_.insert(contents_.begin(), info);
773 766
774 return S_OK; 767 return S_OK;
775 } 768 }
776 769
777 HRESULT DataObjectImpl::EnumFormatEtc( 770 HRESULT DataObjectImpl::EnumFormatEtc(
778 DWORD direction, IEnumFORMATETC** enumerator) { 771 DWORD direction, IEnumFORMATETC** enumerator) {
779 if (direction == DATADIR_GET) { 772 if (direction == DATADIR_GET) {
780 FormatEtcEnumerator* e = 773 FormatEtcEnumerator* e =
781 new FormatEtcEnumerator(contents_.begin(), contents_.end()); 774 new FormatEtcEnumerator(contents_.begin(), contents_.end());
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 return new OSExchangeDataProviderWin(); 979 return new OSExchangeDataProviderWin();
987 } 980 }
988 981
989 // static 982 // static
990 OSExchangeData::CustomFormat OSExchangeData::RegisterCustomFormat( 983 OSExchangeData::CustomFormat OSExchangeData::RegisterCustomFormat(
991 const std::string& type) { 984 const std::string& type) {
992 return RegisterClipboardFormat(ASCIIToUTF16(type).c_str()); 985 return RegisterClipboardFormat(ASCIIToUTF16(type).c_str());
993 } 986 }
994 987
995 } // namespace ui 988 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/dragdrop/os_exchange_data_provider_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698