| /* |
| * Copyright (C) 2009 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "third_party/blink/renderer/core/loader/navigation_policy.h" |
| |
| #include "build/build_config.h" |
| #include "third_party/blink/public/common/input/web_keyboard_event.h" |
| #include "third_party/blink/public/common/input/web_mouse_event.h" |
| #include "third_party/blink/public/web/web_navigation_policy.h" |
| #include "third_party/blink/public/web/web_window_features.h" |
| #include "third_party/blink/renderer/core/events/current_input_event.h" |
| #include "third_party/blink/renderer/core/events/gesture_event.h" |
| #include "third_party/blink/renderer/core/events/keyboard_event.h" |
| #include "third_party/blink/renderer/core/events/mouse_event.h" |
| #include "third_party/blink/renderer/core/events/ui_event_with_key_state.h" |
| #include "third_party/blink/renderer/platform/keyboard_codes.h" |
| #include "third_party/blink/renderer/platform/wtf/assertions.h" |
| |
| namespace blink { |
| |
| namespace { |
| |
| NavigationPolicy NavigationPolicyFromEventModifiers(int16_t button, |
| bool ctrl, |
| bool shift, |
| bool alt, |
| bool meta) { |
| #if defined(OS_MACOSX) |
| const bool new_tab_modifier = (button == 1) || meta; |
| #else |
| const bool new_tab_modifier = (button == 1) || ctrl; |
| #endif |
| if (!new_tab_modifier && !shift && !alt) |
| return kNavigationPolicyCurrentTab; |
| |
| if (new_tab_modifier) { |
| if (shift) |
| return kNavigationPolicyNewForegroundTab; |
| else |
| return kNavigationPolicyNewBackgroundTab; |
| } else { |
| if (shift) |
| return kNavigationPolicyNewWindow; |
| else |
| return kNavigationPolicyDownload; |
| } |
| return kNavigationPolicyCurrentTab; |
| } |
| |
| NavigationPolicy NavigationPolicyFromEventInternal(const Event* event) { |
| if (!event) |
| return kNavigationPolicyCurrentTab; |
| |
| if (const auto* mouse_event = DynamicTo<MouseEvent>(event)) { |
| return NavigationPolicyFromEventModifiers( |
| mouse_event->button(), mouse_event->ctrlKey(), mouse_event->shiftKey(), |
| mouse_event->altKey(), mouse_event->metaKey()); |
| } else if (const KeyboardEvent* key_event = DynamicTo<KeyboardEvent>(event)) { |
| // The click is simulated when triggering the keypress event. |
| return NavigationPolicyFromEventModifiers( |
| 0, key_event->ctrlKey(), key_event->shiftKey(), key_event->altKey(), |
| key_event->metaKey()); |
| } else if (const auto* gesture_event = DynamicTo<GestureEvent>(event)) { |
| // The click is simulated when triggering the gesture-tap event |
| return NavigationPolicyFromEventModifiers( |
| 0, gesture_event->ctrlKey(), gesture_event->shiftKey(), |
| gesture_event->altKey(), gesture_event->metaKey()); |
| } |
| return kNavigationPolicyCurrentTab; |
| } |
| |
| NavigationPolicy NavigationPolicyFromCurrentEvent() { |
| const WebInputEvent* event = CurrentInputEvent::Get(); |
| if (!event) |
| return kNavigationPolicyCurrentTab; |
| |
| int16_t button = 0; |
| if (event->GetType() == WebInputEvent::kMouseUp) { |
| const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(event); |
| |
| switch (mouse_event->button) { |
| case WebMouseEvent::Button::kLeft: |
| button = 0; |
| break; |
| case WebMouseEvent::Button::kMiddle: |
| button = 1; |
| break; |
| case WebMouseEvent::Button::kRight: |
| button = 2; |
| break; |
| default: |
| return kNavigationPolicyCurrentTab; |
| } |
| } else if ((WebInputEvent::IsKeyboardEventType(event->GetType()) && |
| static_cast<const WebKeyboardEvent*>(event)->windows_key_code == |
| VKEY_RETURN) || |
| WebInputEvent::IsGestureEventType(event->GetType())) { |
| // Keyboard and gesture events can simulate mouse events. |
| button = 0; |
| } else { |
| return kNavigationPolicyCurrentTab; |
| } |
| |
| return NavigationPolicyFromEventModifiers( |
| button, event->GetModifiers() & WebInputEvent::kControlKey, |
| event->GetModifiers() & WebInputEvent::kShiftKey, |
| event->GetModifiers() & WebInputEvent::kAltKey, |
| event->GetModifiers() & WebInputEvent::kMetaKey); |
| } |
| |
| } // namespace |
| |
| NavigationPolicy NavigationPolicyFromEvent(const Event* event) { |
| NavigationPolicy event_policy = NavigationPolicyFromEventInternal(event); |
| NavigationPolicy input_policy = NavigationPolicyFromCurrentEvent(); |
| |
| if (event_policy == kNavigationPolicyDownload && |
| input_policy != kNavigationPolicyDownload) { |
| // No downloads from synthesized events without user intention. |
| return kNavigationPolicyCurrentTab; |
| } |
| |
| if (event_policy == kNavigationPolicyNewBackgroundTab && |
| input_policy != kNavigationPolicyNewBackgroundTab && |
| !UIEventWithKeyState::NewTabModifierSetFromIsolatedWorld()) { |
| // No "tab-unders" from synthesized events without user intention. |
| // Events originating from an isolated world are exempt. |
| return kNavigationPolicyNewForegroundTab; |
| } |
| |
| return event_policy; |
| } |
| |
| NavigationPolicy NavigationPolicyForCreateWindow( |
| const WebWindowFeatures& features) { |
| // If our default configuration was modified by a script or wasn't |
| // created by a user gesture, then show as a popup. Else, let this |
| // new window be opened as a toplevel window. |
| bool as_popup = !features.tool_bar_visible || !features.status_bar_visible || |
| !features.scrollbars_visible || !features.menu_bar_visible || |
| !features.resizable; |
| NavigationPolicy app_policy = |
| as_popup ? kNavigationPolicyNewPopup : kNavigationPolicyNewForegroundTab; |
| NavigationPolicy user_policy = NavigationPolicyFromCurrentEvent(); |
| |
| if (user_policy == kNavigationPolicyNewWindow && |
| app_policy == kNavigationPolicyNewPopup) { |
| // User and app agree that we want a new window; let the app override the |
| // decorations. |
| return app_policy; |
| } |
| |
| if (user_policy == kNavigationPolicyCurrentTab) { |
| // User doesn't want a specific policy, use app policy instead. |
| return app_policy; |
| } |
| |
| if (user_policy == kNavigationPolicyDownload) { |
| // When the input event suggests a download, but the navigation was |
| // initiated by script, we should not override it. |
| return app_policy; |
| } |
| |
| return user_policy; |
| } |
| |
| STATIC_ASSERT_ENUM(kWebNavigationPolicyDownload, kNavigationPolicyDownload); |
| STATIC_ASSERT_ENUM(kWebNavigationPolicyCurrentTab, kNavigationPolicyCurrentTab); |
| STATIC_ASSERT_ENUM(kWebNavigationPolicyNewBackgroundTab, |
| kNavigationPolicyNewBackgroundTab); |
| STATIC_ASSERT_ENUM(kWebNavigationPolicyNewForegroundTab, |
| kNavigationPolicyNewForegroundTab); |
| STATIC_ASSERT_ENUM(kWebNavigationPolicyNewWindow, kNavigationPolicyNewWindow); |
| STATIC_ASSERT_ENUM(kWebNavigationPolicyNewPopup, kNavigationPolicyNewPopup); |
| |
| } // namespace blink |