1// Copyright 2014 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 "content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h"
6
7#include "content/common/screen_orientation_messages.h"
8#include "content/public/browser/navigation_details.h"
9#include "content/public/browser/render_frame_host.h"
10#include "content/public/browser/render_process_host.h"
11#include "content/public/browser/render_view_host.h"
12#include "content/public/browser/render_widget_host.h"
13#include "content/public/browser/screen_orientation_provider.h"
14#include "content/public/browser/web_contents.h"
15#include "third_party/WebKit/public/platform/WebScreenInfo.h"
16
17namespace content {
18
19ScreenOrientationDispatcherHostImpl::LockInformation::LockInformation(
20    int request_id, int process_id, int routing_id)
21    : request_id(request_id),
22      process_id(process_id),
23      routing_id(routing_id) {
24}
25
26ScreenOrientationDispatcherHostImpl::ScreenOrientationDispatcherHostImpl(
27    WebContents* web_contents)
28  : WebContentsObserver(web_contents),
29    current_lock_(NULL) {
30  provider_.reset(ScreenOrientationProvider::Create(this, web_contents));
31}
32
33ScreenOrientationDispatcherHostImpl::~ScreenOrientationDispatcherHostImpl() {
34  ResetCurrentLock();
35}
36
37void ScreenOrientationDispatcherHostImpl::ResetCurrentLock() {
38  if (current_lock_) {
39    delete current_lock_;
40    current_lock_ = 0;
41  }
42}
43
44bool ScreenOrientationDispatcherHostImpl::OnMessageReceived(
45    const IPC::Message& message,
46    RenderFrameHost* render_frame_host) {
47  bool handled = true;
48
49  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ScreenOrientationDispatcherHostImpl, message,
50                                   render_frame_host)
51    IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_LockRequest, OnLockRequest)
52    IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_Unlock, OnUnlockRequest)
53    IPC_MESSAGE_UNHANDLED(handled = false)
54  IPC_END_MESSAGE_MAP()
55
56  return handled;
57}
58
59void ScreenOrientationDispatcherHostImpl::DidNavigateMainFrame(
60    const LoadCommittedDetails& details, const FrameNavigateParams& params) {
61  if (!provider_ || details.is_in_page)
62    return;
63  provider_->UnlockOrientation();
64}
65
66RenderFrameHost*
67ScreenOrientationDispatcherHostImpl::GetRenderFrameHostForRequestID(
68    int request_id) {
69  if (!current_lock_ || current_lock_->request_id != request_id)
70    return NULL;
71
72  return RenderFrameHost::FromID(current_lock_->process_id,
73                                 current_lock_->routing_id);
74}
75
76void ScreenOrientationDispatcherHostImpl::NotifyLockSuccess(int request_id) {
77  RenderFrameHost* render_frame_host =
78      GetRenderFrameHostForRequestID(request_id);
79  if (!render_frame_host)
80    return;
81
82  render_frame_host->Send(new ScreenOrientationMsg_LockSuccess(
83      render_frame_host->GetRoutingID(), request_id));
84  ResetCurrentLock();
85}
86
87void ScreenOrientationDispatcherHostImpl::NotifyLockError(
88    int request_id, blink::WebLockOrientationError error) {
89  RenderFrameHost* render_frame_host =
90      GetRenderFrameHostForRequestID(request_id);
91  if (!render_frame_host)
92    return;
93
94  NotifyLockError(request_id, render_frame_host, error);
95}
96
97void ScreenOrientationDispatcherHostImpl::NotifyLockError(
98    int request_id,
99    RenderFrameHost* render_frame_host,
100    blink::WebLockOrientationError error) {
101  render_frame_host->Send(new ScreenOrientationMsg_LockError(
102      render_frame_host->GetRoutingID(), request_id, error));
103  ResetCurrentLock();
104}
105
106void ScreenOrientationDispatcherHostImpl::OnOrientationChange() {
107  if (provider_)
108    provider_->OnOrientationChange();
109}
110
111void ScreenOrientationDispatcherHostImpl::OnLockRequest(
112    RenderFrameHost* render_frame_host,
113    blink::WebScreenOrientationLockType orientation,
114    int request_id) {
115  if (current_lock_) {
116    NotifyLockError(current_lock_->request_id, render_frame_host,
117                    blink::WebLockOrientationErrorCanceled);
118  }
119
120  if (!provider_) {
121    NotifyLockError(request_id, render_frame_host,
122                    blink::WebLockOrientationErrorNotAvailable);
123    return;
124  }
125
126  current_lock_ = new LockInformation(request_id,
127                                      render_frame_host->GetProcess()->GetID(),
128                                      render_frame_host->GetRoutingID());
129
130  provider_->LockOrientation(request_id, orientation);
131}
132
133void ScreenOrientationDispatcherHostImpl::OnUnlockRequest(
134    RenderFrameHost* render_frame_host) {
135  if (current_lock_) {
136    NotifyLockError(current_lock_->request_id, render_frame_host,
137                    blink::WebLockOrientationErrorCanceled);
138  }
139
140  if (!provider_)
141    return;
142
143  provider_->UnlockOrientation();
144}
145
146}  // namespace content
147