download功能的下载注册与cdp 监听 Observer模式的很好示范

1,DownloadItem中定义Observer,在BrowserHandler中实现

// One DownloadItem per download. This is the model class that stores all the
// state for a download.
class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData {
 public:

  // Callback used with AcquireFileAndDeleteDownload().
  using AcquireFileCallback = base::OnceCallback<void(const base::FilePath&)>;
  using RenameDownloadCallback = base::OnceCallback<void(DownloadRenameResult)>;
............
  // Interface that observers of a particular download must implement in order
  // to receive updates to the download's status.
  class COMPONENTS_DOWNLOAD_EXPORT Observer : public base::CheckedObserver {
   public:
    virtual void OnDownloadUpdated(DownloadItem* download) {}
    virtual void OnDownloadOpened(DownloadItem* download) {}
    virtual void OnDownloadRemoved(DownloadItem* download) {}

    // Called when the download is being destroyed. This happens after
    // every OnDownloadRemoved() as well as when the DownloadManager is going
    // down.
    virtual void OnDownloadDestroyed(DownloadItem* download) {}

    ~Observer() override;
  };
.......

什么时候调用 AddObserver(browserHandler), 用如下代码

item->AddObserver(this);

void BrowserHandler::DownloadWillBegin(FrameTreeNode* ftn,
                                       download::DownloadItem* item) {
  if (!download_events_enabled_)
    return;
  const std::u16string likely_filename = net::GetSuggestedFilename(
      item->GetURL(), item->GetContentDisposition(), std::string(),
      item->GetSuggestedFilename(), item->GetMimeType(), "download");

  frontend_->DownloadWillBegin(
      ftn->current_frame_host()->devtools_frame_token().ToString(),
      item->GetGuid(), item->GetURL().spec(),
      base::UTF16ToUTF8(likely_filename));
  item->AddObserver(this);//========================
  pending_downloads_.insert(item);
}

来自:
void WillBeginDownload(download::DownloadCreateInfo* info,
                       download::DownloadItem* item) {
  if (!item) {
    return;
  }
  auto* rfh = static_cast<RenderFrameHostImpl*>(
      RenderFrameHost::FromID(info->render_process_id, info->render_frame_id));
  FrameTreeNode* ftn =
      rfh ? FrameTreeNode::GloballyFindByID(rfh->GetFrameTreeNodeId())
          : nullptr;
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn, &protocol::BrowserHandler::DownloadWillBegin, ftn,
                   item);
  DispatchToAgents(ftn, &protocol::PageHandler::DownloadWillBegin, ftn, item);

  for (auto* agent_host : BrowserDevToolsAgentHost::Instances()) {
    for (auto* browser_handler :
         protocol::BrowserHandler::ForAgentHost(agent_host)) {
      browser_handler->DownloadWillBegin(ftn, item);//========================
    }
  }
}
/////////////////////////////////////////////////////////////////////////////

从上面可以看到,对browserHandler的对象获取是通过 RenderFrameHost::FromID(info->render_process_id, info->render_frame_id));实现的。 

 

2, 在 DownloadItemImpl 中存放着 observers

// The views of this item in the download shelf and download contents.
 
头文件中放着方法:components/download/public/common/download_item.h;DownloadItemImpl 实现了它们
virtual void UpdateObservers() = 0;
 
3,更新下载进度条
void DownloadItemImpl::UpdateObservers() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DVLOG(20) << __func__ << "()";

  // Nested updates should not be allowed.
  DCHECK(!is_updating_observers_);

  is_updating_observers_ = true;
  for (auto& observer : observers_)
    observer.OnDownloadUpdated(this);
  is_updating_observers_ = false;
}

3.1 谁调用这个 UpdateObservers,应该是下载管理器。

 初始化时注册进那个实现接口的类 BrowserHandler 。在下载管理器知道进度更新时调用 UpdateObservers。

3.2 谁实现这个observer的 OnDownloadUpdate,应该是CDP的browser_handler .

注意这个browser_handler 是在browser进程的content层实现:src\content\browser\devtools\protocol\browser_handler.h

而非 chrome\browser\devtools\protocol\browser_handler.h chrome浏览器的实现;或者headless浏览器的实现 headless\lib\browser\protocol\browser_handler.h

BrowserHandler 确实实现了我们上面的观察者接口: download::DownloadItem::Observer

class BrowserHandler : public DevToolsDomainHandler,
                       public Browser::Backend,
                       public download::DownloadItem::Observer {

.......

  // DownloadItem::Observer overrides
  void OnDownloadUpdated(download::DownloadItem* item) override;
  void OnDownloadDestroyed(download::DownloadItem* item) override;

}

具体实现:

void BrowserHandler::OnDownloadUpdated(download::DownloadItem* item) {
  std::string state;

  switch (item->GetState()) {
    case download::DownloadItem::IN_PROGRESS:
      state = Browser::DownloadProgress::StateEnum::InProgress;
      break;
    case download::DownloadItem::COMPLETE:
      state = Browser::DownloadProgress::StateEnum::Completed;
      break;
    case download::DownloadItem::CANCELLED:
    case download::DownloadItem::INTERRUPTED:
      state = Browser::DownloadProgress::StateEnum::Canceled;

      break;
    case download::DownloadItem::MAX_DOWNLOAD_STATE:
      NOTREACHED();
  }

  frontend_->DownloadProgress(item->GetGuid(), item->GetTotalBytes(),
                              item->GetReceivedBytes(), state);
  if (state != Browser::DownloadProgress::StateEnum::InProgress) {
    item->RemoveObserver(this);
    pending_downloads_.erase(item);
  }

}

 

posted @ 2024-01-12 17:14  Bigben  阅读(13)  评论(0编辑  收藏  举报