Commit Graph

56 Commits

Author SHA1 Message Date
Nik Pavlov 39142413a0 chrome: Fix unintended show of minimized window on navigation (fixes #3618) 2023-12-18 14:02:42 -05:00
Nik Pavlov 8d7001adc3 Replace ReadOnlySharedMemoryRegion with WritableSharedMemoryRegion (see #3502)
Write access to the shared memory region is required because JavaScript lacks
the capability to create read-only ArrayBuffers. When a user attempts to modify
an ArrayBuffer that utilizes a ReadOnlySharedMemoryRegion as its BackingStore
it triggers an access violation.

Note that this pull request may be reverted in the future if JavaScript adds
read-only ArrayBuffer support.
2023-10-16 22:43:29 +00:00
Marshall Greenblatt 5042d71408 Remove CEF-specific integer and char16 typedef's (see #3507) 2023-06-01 19:32:36 +03:00
Marshall Greenblatt dc9e64308a Replace NOTREACHED() with DCHECK(false) (fixes #3500)
Restores the old behavior of assertion in Debug build only.
2023-05-08 18:36:00 +03:00
Marshall Greenblatt 4c41f14360 Remove deprecated base::[Dictionary|List]Value API usage 2023-01-30 21:32:19 -05:00
e.jorge b65d59f27e Fix edit command execution on pdf frames (fixes issue #3429) 2023-01-12 21:45:43 +00:00
Marshall Greenblatt b66c2d1bea Revert "Fix dismissal of select popups on NotifyMoveOrResizeStarted (see issue #3294)"
This reverts commit 5f4bccd672.

Reason for revert: This change causes a native parented browser to lose focus
on move (fixes issue #3426).
2023-01-06 13:48:29 -05:00
Marshall Greenblatt 3af3eab3e4 Update source files for bracket style 2023-01-04 17:47:17 -05:00
Marshall Greenblatt 37aee4d3a0 Improve the timing of OnLoadEnd (fixes issue #3341)
Use WebContentsDelegate::DidFinishLoad instead of a custom Mojo message.
This fixes flaky OnLoadEnd behavior with NavigationTest.Order.
2022-08-25 18:23:33 -04:00
Marshall Greenblatt 6d71f5ffd7 Don't reconnect after intentional browser frame detach (see issue #3260)
Send a FrameDetached message from CefFrameHostImpl::Detach before closing
the RenderFrame connection to avoid an immediate reconnect attempt by the
renderer.

When BFCache is disabled the intentionally detached frame will never be
reconnected. When BFCache is enabled the intentionally detached frame will
be reconnected via CefFrameImpl::OnWasShown if/when it exits the cache.
2022-08-19 12:38:32 -04:00
Marshall Greenblatt 2bf3d536ea Improve logging of frame connection state (see issue #3260)
Run with "--vmodule=frame_*=1 --enable-logging=stderr --no-sandbox" on the
command-line to see these log messages from both the browser and renderer
processes.
2022-08-19 12:38:32 -04:00
Nik Pavlov 81e892d19e Add a shared memory variant of CefProcessMessage (fixes issue #3126)
CefSharedProcessMessageBuilder supports creation of a CefProcessMessage
backed by a CefSharedMemoryRegion.

Performance tests comparing the existing ArgumentList approach and the new
SharedMemoryRegion approach have been added to cefclient at
http://tests/ipc_performance.

CefMessageRouter has been updated to use SharedMemoryRegion as transport
for larger message payloads. The threshold is configurable via
|CefMessageRouterConfig.message_size_threshold|.

To test:
run `ceftests --gtest_filter=SendSharedProcessMessageTest.*:SharedProcessMessageTest.*:MessageRouterTest.Threshold*`
2022-07-04 09:49:15 +00:00
Marshall Greenblatt b62dd2b6ee Update to Chromium version 102.0.5005.0 (#992738)
Linux: 32-bit x86 builds are no longer supported (see issue #2676).
2022-04-28 16:38:50 -04:00
Marshall Greenblatt 5f4bccd672 Fix dismissal of select popups on NotifyMoveOrResizeStarted (see issue #3294)
This impacts both Alloy and Chrome runtimes when using a native parent window.
2022-04-11 13:11:08 -04:00
Marshall Greenblatt 3d1bbaf54f Support reconnect of the mojo frame channel (fixes issue #3260)
The mojo channel used for frame communication may disconnect for a variety of
reasons including frame navigation, frame destruction, or insertion into the
BackForwardCache (when the browser-side frame representation is destroyed and
closes the connection). When disconnect occurs we now evaluate the situation
and reconnect if appropriate.

Connections are now initiated solely from the renderer process and the
RenderFrame is passed as an argument to FrameAttached() instead of being
retrieved independently. Messages are queued while the frame is disconnected
and sent only after FrameAttachedAck() is received from the browser process.
The renderer process will be crashed intentionally with a "connection retry
failure" message if the reconnect fails 3 times in a row.
2022-02-14 20:31:04 -05:00
Marshall Greenblatt f3cea7e7df chrome: Fix DCHECK when a temporary CefFrame is destroyed (see issue #2969)
The temporary CefFrame is created in NavigationOnUIThread during PDF loading.
2021-11-16 17:43:37 -05:00
Marshall Greenblatt 7a56371b84 Fix draggable region update with BackForwardCache enabled (see issue #2421)
When BackForwardCache is enabled and the user navigates the main frame
back/forward a new RFH may be created for an existing main frame GlobalId value
and CefFrameHostImpl (e.g. an object that was previously Detach()ed after main
frame navigation called SetMainFrame, but for which RenderFrameDeleted was not
subsequently called due to insertion in the BackForwardCache). In this case we
can re-attach the new RFH to the existing main frame CefFrameHostImpl in
RenderFrameHostStateChanged and resume processing of messages.

Swapping back/forward to an existing (already loaded) renderer does not trigger
new notifications for draggable regions (e.g. RenderFrameObserver::
DraggableRegionsChanged is not called by default). We therefore explicitly
request an update of draggable regions by sending the DidStopLoading message to
the renderer.

A new |reattached| parameter is added to CefFrameHandler::OnFrameAttached to
support identification of BackForwardCache usage by the client.

To test with unit tests:
Run `ceftests --gtest_filter=DraggableRegionsTest.DraggableRegionsCrossOrigin
              --enable-features=BackForwardCache`

To test manually:
1. Run `cefclient --enable-features=BackForwardCache --use-views
   --url=http://tests/draggable`, note that draggable regions work.
2. Load https://www.google.com via the address bar, note that draggable regions
   are removed.
3. Go back to http://tests/draggable, note that draggable regions work.
4. Go forward to https://www.google.com, note that draggable regions are
   removed.
2021-09-16 18:25:43 +03:00
Marshall Greenblatt 955097ea77 Remove usage of FrameTreeNode IDs (see issue #2421)
With the introduction of prerendering in Chromium it is now possible for
RenderFrameHosts (RFH) to move between FrameTrees. As a consequence we can no
longer rely on FrameTreeNode IDs to uniquely identify a RFH over its lifespan.
We must now switch to using GlobalRenderFrameHostId (child_id, frame_routing_id)
instead for that purpose. Additionally, we simplify existing code by using the
GlobalRenderFrameHostId struct in all places that previously used a
(render_process_id, render_frame_id) pair, since these concepts are equivalent.

See https://crbug.com/1179502#c8 for additional background.
2021-08-19 19:41:44 -04:00
Marshall Greenblatt 92ec2dcbdd Fix ceftest failures with BackForwardCache enabled (see issue #2421)
When BackForwardCache is enabled the old RFH tree may be cached instead of being
immediately deleted as a result of main frame navigation. If a RFH is cached
then delivery of the CefFrameHandler::OnFrameDetached callback will be delayed
until the the RFH is ejected from the cache (possibly not occurring until the
browser is destroyed). This change in OnFrameDetached timing was causing
FrameHandlerTest.OrderSubCrossOrigin* to fail, and the inclusion of cached
frames in CefBrowserInfo::GetAllFrames was causing
FrameTest.NestedIframesDiffOrigin to fail.

BackForwardCache is currently being tested via field trials (see
https://crbug.com/1171298) and can be explicitly disabled using the
`--disable-back-forward-cache` or `--disable-features=BackForwardCache`
command-line flags.
2021-07-27 19:03:21 -04:00
Marshall Greenblatt 3c0a4410ad Fix crash if a frame is detached before the attach message arrives (see issue #2421)
This reproduced on Mac with ResourceRequestHandlerTest.BasicStandardUnhandledModifyBeforeResourceLoad
2021-06-10 16:42:44 -04:00
Marshall Greenblatt 00dca9601e Update to Chromium version 92.0.4515.0 (#885287) 2021-06-10 16:42:44 -04:00
Marshall Greenblatt e411b513be Add CefFrameHandler callbacks for tracking CefFrame lifespan (see issue #2421)
See the new cef_frame_handler.h for complete usage documentation.

This change includes the following related enhancements:
- The newly added CefBrowser::IsValid method will return false (in the browser
  process) after CefLifeSpanHandler::OnBeforeClose is called.
- CefBrowser::GetMainFrame will return a valid object (in the browser process)
  until after CefLifeSpanHandler::OnBeforeClose is called.
- The main frame object will change during cross-origin navigation or
  re-navigation after renderer process termination. During that time,
  GetMainFrame will return the new/pending frame (in the browser process) and
  any messages that arrive for the new/pending frame will be correctly
  attributed in OnProcessMessageReceived.
- Commands to be executed in the renderer process that may fail during early
  frame initialization (ExecuteJavaScript, LoadRequest, etc.) will now be
  queued until after the JavaScript context for the frame has been created.
- Logging has been added for any commands that are dropped because they arrived
  after frame detachment.
2021-05-31 18:58:27 -04:00
Marshall Greenblatt 21ac0be8d7 Update process message unit test expectations (see issue #3126)
See related comments in commit f3c513ba.
2021-05-20 14:56:23 -04:00
Marshall Greenblatt f3c513bafd Allow a CefProcessMessage to remain valid after receipt (see issue #3126)
A reference to a received CefProcessMessage object and/or associated argument
list can now be kept outside of the OnProcessMessageReceived callback. The
argument list is no longer explicitly owned by the CefProcessMessage object
and can be individually assigned to other CefValue types as needed (e.g. by
passing to SetList, etc). Depending on client usage this could reduce the
potential for unnecessary copies of the list contents.

Received messages can also be sent back using SendProcessMessage (after which
the CefProcessMessage would become invalid as discussed in issue #3123). This
is not new behavior but we have now added explicit unit test coverage for it.
This also no longer requires a copy of the argument list contents.

Note that a received argument list is initially read-only for logical
consistency. Assignment to another CefValue object could potentially remove
the read-only status because it is not an intrinsic property of the underlying
Chromium data type. This is fine because, at that point, ownership has been
transfered to the new CefValue object and the original logical context (as
part of the CefProcessMessage) no longer applies.
2021-05-20 14:46:19 -04:00
Marshall Greenblatt d9efaee9b9 Fix routing of frame messages after cross-origin navigation (fixes issue #2849)
When navigating cross-origin a speculative RenderFrameHost (RFH) and
CefFrameHostImpl is created in the browser process for the new frame object
created in a new renderer process. The FrameAttached message then arrives for
the speculative RFH, and as a consequence interfaces are bound between the new
CefFrameHostImpl and the speculative RFH. If the pending navigation commits
then the existing RFH will be replaced with the previously speculative RFH.
Since interfaces are already bound we must keep the new CefFrameHostImpl. This
means that frame objects (including for the main frame) will now always change
after cross-origin navigation, and the old frame object will be invalidated.
2021-05-18 21:59:48 -04:00
Marshall Greenblatt ebee84755e Convert legacy IPC messages to Mojo (fixes issue #3123)
This change introduces a few minor CEF API behavior changes:

- A CefProcessMessage object cannot be reused after being passed to
  SendProcessMessage.
- The |extra_info| argument to CefRenderProcessHandler::OnBrowserCreated may
  now be NULL.

Where appropriate, we now utilize the default UTF string encoding format and
shared memory to reduce copies and conversions for the cross-process
transfer of arbitrary-length strings. For example, CefFrame::GetSource/GetText
now involves zero UTF conversions and zero copies in the browser process for
the CefString delivered to CefStringVisitor::Visit().
2021-05-18 21:59:48 -04:00
Marshall Greenblatt 34c63a665d Wait for CefBrowserContext initialization (see issue #2969)
With the Chrome runtime, Profile initialization may be asynchronous. Code that
waited on CefBrowserContext creation now needs to wait on CefBrowserContext
initialization instead.
2021-04-14 21:03:44 -04:00
Cristian Amarie 59c11404e6 Fix loading of URL without scheme (fixes issue #3079) 2021-02-10 13:33:51 -05:00
Marshall Greenblatt a584bd187b Update to Chromium version 88.0.4324.0 (#827102)
- Mac: Xcode 12.2 and the MacOS 11.0 SDK are now required for building.
- MacOS 10.10 (Yosemite) is no longer supported (see https://crbug.com/1126056).
- Flash is no longer supported (see https://www.chromium.org/flash-roadmap).
2020-12-04 15:43:33 -05:00
Marshall Greenblatt 015e3621a3 Update to Chromium version 87.0.4280.0 (#812852)
- Windows: VS2015 Update 2 is now the minimum version requirement for linking
  cef_sandbox from official build binary distributions.
2020-10-15 14:21:06 -04:00
Marshall Greenblatt 4fbd247231 Add chrome runtime support for more callbacks and ceftests (see issue #2969)
This change adds support for:
- Protocol and request handling.
- Loading and navigation events.
- Display and focus events.
- Mouse/keyboard events.
- Popup browsers.
- Callbacks in the renderer process.
- Misc. functionality required for ceftests.

This change also adds a new CefBrowserProcessHandler::GetCookieableSchemes
callback for configuring global state that will be applied to all
CefCookieManagers by default. This global callback is currently required by the
chrome runtime because the primary ProfileImpl is created via
ChromeBrowserMainParts::PreMainMessageLoopRun (CreatePrimaryProfile) before
OnContextCreated can be called.

ProfileImpl will use the "C:\Users\[user]\AppData\Local\CEF\User Data\Default"
directory by default (on Windows). Cookies may persist in this directory when
running ceftests and may need to be manually deleted if those tests fail.

Remaining work includes:
- Support for client-created request contexts.
- Embedding the browser in a Views hierarchy (cefclient support).
- TryCloseBrowser and DoClose support.
- Most of the CefSettings configuration.
- DevTools protocol and window control (ShowDevTools, ExecuteDevToolsMethod).
- CEF-specific WebUI pages (about, license, webui-hosts).
- Context menu customization (CefContextMenuHandler).
- Auto resize (SetAutoResizeEnabled).
- Zoom settings (SetZoomLevel).
- File dialog runner (RunFileDialog).
- File and JS dialog handlers (CefDialogHandler, CefJSDialogHandler).
- Extension loading (LoadExtension, etc).
- Plugin loading (OnBeforePluginLoad).
- Widevine loading (CefRegisterWidevineCdm).
- PDF and print preview does not display.
- Crash reporting is untested.
- Mac: Web content loads but does not display.

The following ceftests are now passing when run with the
"--enable-chrome-runtime" command-line flag:

CorsTest.*
DisplayTest.*:-DisplayTest.AutoResize
DOMTest.*
DraggableRegionsTest.*
ImageTest.*
MessageRouterTest.*
NavigationTest.*
ParserTest.*
RequestContextTest.*Global*
RequestTest.*
ResourceManagerTest.*
ResourceRequestHandlerTest.*
ResponseTest.*
SchemeHandlerTest.*
ServerTest.*
StreamResourceHandlerTest.*
StreamTest.*
StringTest.*
TaskTest.*
TestServerTest.*
ThreadTest.*
URLRequestTest.*Global*
V8Test.*:-V8Test.OnUncaughtExceptionDevTools
ValuesTest.*
WaitableEventTest.*
XmlReaderTest.*
ZipReaderTest.*
2020-09-29 18:31:43 -04:00
Marshall Greenblatt 38d8acfa18 Create a ChromeBrowserHostImpl for every Chrome tab (see issue #2969)
The Browser object represents the top-level Chrome browser window. One or more
tabs (WebContents) are then owned by the Browser object via TabStripModel. A
new Browser object can be created programmatically using "new Browser" or
Browser::Create, or as a result of user action such as dragging a tab out of an
existing window. New or existing tabs can also be added to an already existing
Browser object.

The Browser object acts as the WebContentsDelegate for all attached tabs. CEF
integration requires WebContentsDelegate callbacks and notification of tab
attach/detach. To support this integration we add a cef::BrowserDelegate
(ChromeBrowserDelegate) member that is created in the Browser constructor and
receives delegation for the Browser callbacks. ChromeBrowserDelegate creates a
new ChromeBrowserHostImpl when a tab is added to a Browser for the first time,
and that ChromeBrowserHostImpl continues to exist until the tab's WebContents
is destroyed. The associated WebContents object does not change, but the
Browser object will change when the tab is dragged between windows.

CEF callback logic is shared between the chrome and alloy runtimes where
possible. This shared logic has been extracted from CefBrowserHostImpl to
create new CefBrowserHostBase and CefBrowserContentsDelegate classes. The
CefBrowserHostImpl class is now only used with the alloy runtime and will be
renamed to AlloyBrowserHostImpl in a future commit.
2020-09-21 17:06:56 -04:00
Andrei Kurushin 01f385a6f7 Fix CefFrame::GetSource crash on detached frame (fixes issue #2898) 2020-04-02 21:01:33 +00:00
Marshall Greenblatt a141082b91 Fix navigation to debug URLs 2020-02-17 13:19:09 -05:00
Alexander Guettler 71768ea6c3 Update to Chromium version 80.0.3987.0 (#722274) 2020-02-17 13:19:09 -05:00
Marshall Greenblatt 737ff18498 Remove CefFrame::LoadString method (fixes issue #2586)
This method has not behaved as expected for some time.
2019-10-15 17:34:16 +02:00
Marshall Greenblatt 67b61c4af9 Remove the old network implementation (see issue #2622)
The `--disable-features=NetworkService` flag is no longer supported.
2019-07-29 17:41:45 -04:00
Marshall Greenblatt 241941a44a Move message routing from CefBrowser to CefFrame (see issue #2498).
This change moves the SendProcessMessage method from CefBrowser to CefFrame and
adds CefBrowser parameters to OnProcessMessageReceived and
OnDraggableRegionsChanged.

The internal implementation has changed as follows:
- Frame IDs are now a 64-bit combination of the 32-bit render_process_id and
  render_routing_id values that uniquely identify a RenderFrameHost (RFH).
- CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied
  to RFH expectations. Specifically, a CefFrameHostImpl object representing a
  sub-frame will be created when a RenderFrame is created in the renderer
  process and detached when the associated RenderFrame is deleted or the
  renderer process in which it runs has died.
- The CefFrameHostImpl object representing the main frame will always be valid
  but the underlying RFH (and associated frame ID) may change over time as a
  result of cross-origin navigations. Despite these changes calling LoadURL on
  the main frame object in the browser process will always navigate as expected.
- Speculative RFHs, which may be created as a result of a cross-origin
  navigation and discarded if that navigation is not committed, are now handled
  correctly (e.g. ignored in most cases until they're committed).
- It is less likely, but still possible, to receive a CefFrame object with an
  invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet
  been created for a sub-frame. For example, when OnBeforeBrowse is called
  before initiating navigation in a previously nonexisting sub-frame.

To test: All tests pass with NetworkService enabled and disabled.
2019-05-29 17:44:56 +03:00
Marshall Greenblatt ba0e1b5719 Add NetworkService support for CefURLRequest (see issue #2622).
Requests created using CefURLRequest::Create are not associated with a
browser/frame. When originating from the render process these requests cannot be
intercepted and consequently only http(s) and blob requests are supported. To
work around this limitation a new CefFrame::CreateURLRequest method has been
added that allows the request to be associated with that browser/frame for
interception purposes.

This change also fixes an issue with the NetworkService implementation where
redirected requests could result in two parallel requests being sent to the
target server.

To test: URLRequestTest.* tests pass with NetworkService enabled.
2019-05-17 21:42:25 +03:00
Marshall Greenblatt 69178d519e Fix bugs and test failures with browser-side navigation (issue #2290) 2017-11-30 18:20:24 -05:00
Marshall Greenblatt 5c79944b31 Update to Chromium revision d483fb77 (#474934)
- CefLifeSpanHandler::OnBeforePopup is now called on the UI thread.
- Remove CefBrowserSettings.javascript_open_windows which is no
  longer supported.
2017-06-02 05:55:23 -07:00
Marshall Greenblatt d4f06e3806 Move matching h file to top of header list (issue #2171) 2017-05-19 11:11:18 +02:00
Marshall Greenblatt 31d9407ee2 Apply clang-format to all C, C++ and ObjC files (issue #2171) 2017-05-18 12:30:05 +02:00
Marshall Greenblatt 07d12b78e1 Update to Chromium revision 9cedf753 (#418732)
- Simplify usage of OnBeforePluginLoad (issue #2015)
- Switch crash reporting from crashpad to breakpad on Windows and OS X.
  Adds a new chrome_elf.dll dependency on Windows (issue #1995)
- Remove CefTextfield::GetPlaceholderTextColor() method which is no
  longer supported by Chromium.
2016-10-20 16:54:25 -04:00
Marshall Greenblatt 8aac23386e Update to Chromium revision cb947c01 (#352221)
- Implement CefRequestHandler::OnBeforeBrowse using NavigationThrottle
  instead of ResourceThrottle (see http://crbug.com/537634). The CefRequest
  object passed to OnBeforeBrowse will no longer have an associated request
  identifier.
- Mac: Remove additional helper apps which are no longer required (see
  http://crbug.com/520680)
- Remove the UR_FLAG_REPORT_RAW_HEADERS flag which is no longer supported (see
  http://crbug.com/517114)
- Remove the CefBrowserSettings.java parameter. Java is an NPAPI plugin and
  NPAPI plugins are no longer supported (see http://crbug.com/470301#c11)
- Add CefFormatUrlForSecurityDisplay function in cef_parser.h
- Fix crash when passing `--disable-extensions` command-line flag (issue #1721)
- Linux: Fix NSS handler loading (issue #1727)
2015-10-09 17:31:27 -04:00
Marshall Greenblatt eef89ccdd3 Update to Chromium revision 40af916d (#303546).
- Standardize usage of virtual/override specifiers in CEF internals (see http://crbug.com/417463).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1903 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
2014-11-12 19:25:15 +00:00
Marshall Greenblatt 2ba756d3e1 Update to Chromium revision b0aa1fb5 (#296183).
- Restore CefRenderHandler::OnScrollOffsetChanged.
- Add new RT_PING and RT_SERVICE_WORKER resource type values.
- The resource type for image sub-resource loads has changed from RT_IMAGE to RT_PREFETCH (this is a regression, see http://crbug.com/415253#c23).
- Add a patch to fix a crash in Scheduler::swapQueuesRunPendingTasks* (http://crbug.com/415478).
- Add documentation for cef_key_event_type_t values.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1846 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
2014-09-26 23:48:19 +00:00
Marshall Greenblatt 39ca06a66d Add new FrameTest.* unit tests and fix discovered CefFrame-related bugs.
- Allow empty |name| argument to CefBrowser::GetFrame. This will return the main frame.
- Modify CefBrowser::GetFrame to search both assigned and unique frame names.
- Calling CefFrame::IsFocused on the main frame should return true when there are no other frames.
- Fix CefBrowser::GetFrameIdentifiers and GetFrameNames to return correct values in the renderer process (issue #1236).
- Delete NavigationTest.FrameNameIdent which is now obsoleted by the new FrameTests.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1842 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
2014-09-24 15:38:11 +00:00
Marshall Greenblatt b34963b743 Revert revision 1765 changes due to broken sub-frame loading.
- Move LoadRequest execution to the browser process and use data: URLs for LoadString (issue #579).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1780 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
2014-07-16 21:27:25 +00:00
Marshall Greenblatt b9781aa000 Move LoadRequest execution to the browser process and use data: URLs for LoadString (issue #579).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1765 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
2014-07-10 18:22:09 +00:00